Cloud WorkstationsからGitHubへの安全なアクセスを実現する - Secure Web Proxyによるリポジトリレベル制御
はじめに
開発環境のセキュリティを確保しながら、開発者の生産性を維持することは常に課題です。特にクラウドベースの開発環境では、外部リポジトリへのアクセス制御が重要になります。
本記事では、Google Cloud WorkstationsからGitHubの特定リポジトリのみにアクセスを許可する、Secure Web Proxyを使った実装方法を解説します。
解決したい課題
Cloud Workstationsを使用する際、以下の課題に直面しました:
- セキュリティ要件: 開発環境から外部への無制限なアクセスは許可できない
- 開発効率: GitHubリポジトリへのアクセスは必須
- きめ細かい制御: 組織全体ではなく、必要なリポジトリのみアクセス許可したい
従来のアプローチでは、組織全体(github.com/myorg/*
)へのアクセスを許可することが一般的でしたが、これでは従業員が個人的に作成したリポジトリへの意図しないデータ流出リスクがありました。
アーキテクチャ概要
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
┌─────────────────────┐
│ Cloud Workstation │
│ (VPC内) │
└──────────┬──────────┘
│ Private IP
▼
┌─────────────────────┐
│ Secure Web Proxy │
│ - TLS Inspection │
│ - URL Filtering │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ GitHub │
│ (特定リポジトリ) │
└─────────────────────┘
|
実装詳細
1. Secure Web Proxyの基本設定
1
2
3
4
5
6
7
|
resource "google_network_security_gateway_security_policy" "main" {
project = var.project_id
location = var.region
name = "${var.prefix}-workstation-policy"
description = "Security policy for Cloud Workstations"
tls_inspection_policy = google_network_security_tls_inspection_policy.main.id
}
|
TLS inspectionを有効にすることで、HTTPS通信の中身を検査し、URLパスレベルでの制御が可能になります。
2. リポジトリ単位のアクセス制御
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
resource "google_network_security_gateway_security_policy_rule" "github_repo_access" {
for_each = {
for i, repo in var.allowed_github_repos
: 2000 + i => repo # 動的にpriorityを割り当て
}
name = "github-repo-${each.key}"
description = "Allow access to GitHub repository ${each.value}"
priority = each.key
basic_profile = "ALLOW"
session_matcher = "inIpRange(source.ip, '0.0.0.0/0')"
application_matcher = <<-_EOT_
request.url().startsWith('github.com/${each.value}.git/')
_EOT_
tls_inspection_enabled = true
enabled = true
}
|
3. Priority管理戦略
ルールの評価順序を明確にするため、以下のpriority体系を採用:
Priority範囲 |
用途 |
例 |
1000-1999 |
一般的な許可URL |
パッケージリポジトリ、ドキュメント |
2000-9999 |
GitHub個別リポジトリ |
myorg/frontend , myorg/backend |
10000 |
デフォルト拒否 |
上記以外すべて拒否 |
1
2
3
|
# 2000番台の動的割り当て
# リポジトリが10個の場合: 2000, 2001, 2002, ..., 2009
# リポジトリが100個の場合: 2000, 2001, ..., 2099
|
セキュリティ考慮事項
1. session_matcherの設定
1
|
session_matcher = "inIpRange(source.ip, '0.0.0.0/0')"
|
一見すると全IPを許可しているように見えますが、Secure Web ProxyはVPC内に配置されているため、実質的にVPC内のトラフィックのみが対象となります。外部からの直接アクセスは構造的に不可能です。
2. より厳密な制御が必要な場合
1
2
3
4
5
6
7
8
|
# 特定のWorkstationサブネットのみに制限
session_matcher = "inIpRange(source.ip, '10.0.1.0/24')"
# HTTPメソッドも制限
application_matcher = <<-_EOT_
request.url().startsWith('github.com/${each.value}.git/')
&& request.method.matches('^(GET|POST|HEAD)$')
_EOT_
|
3. 時間帯制御(オプション)
1
2
3
4
5
6
|
# 営業時間内のみアクセス許可
session_matcher = <<-EOT
inIpRange(source.ip, '10.0.1.0/24')
&& request.time.getHours('Asia/Tokyo') >= 9
&& request.time.getHours('Asia/Tokyo') < 18
EOT
|
実装時の注意点
URLマッチングの課題
現在の実装では以下の制限があります:
1
2
3
4
5
6
|
# 現在の実装
request.url().startsWith('github.com/${each.value}.git/')
# 問題:以下のパターンがマッチしない
# - github.com/myorg/repo.git (末尾スラッシュなし)
# - github.com/myorg/repo/info/refs (Git smart HTTP)
|
改善案
1
2
3
4
|
# より柔軟なパターンマッチング
application_matcher = <<-_EOT_
request.url().matches('^github\\.com/${replace(each.value, "/", "\\/")}(\\.git)?(/.*)?$')
_EOT_
|
動作確認
設定前
1
2
3
4
|
$ git clone https://github.com/myorg/restricted-repo.git
Cloning into 'restricted-repo'...
remote: Access denied
fatal: unable to access 'https://github.com/myorg/restricted-repo.git/': The requested URL returned error: 403
|
設定後
1
2
3
4
5
|
$ git clone https://github.com/myorg/allowed-repo.git
Cloning into 'allowed-repo'...
remote: Enumerating objects: 12345, done.
remote: Counting objects: 100% (12345/12345), done.
# 成功!
|
運用上のベストプラクティス
1. 段階的なロールアウト
1
2
3
4
5
6
7
8
9
10
11
12
13
|
variable "allowed_github_repos" {
default = [
# Phase 1: 必須リポジトリのみ
"myorg/core-api",
# Phase 2: チーム固有リポジトリ追加
"myorg/frontend-app",
"myorg/mobile-app",
# Phase 3: ツール・ライブラリ
"myorg/shared-libraries"
]
}
|
2. ログ・監査
1
2
3
4
5
6
7
8
9
|
resource "google_network_security_gateway_security_policy_rule" "github_repo_access" {
# ... 他の設定 ...
# ログ設定を追加(将来の実装)
log_config {
enable = true
sample_rate = 1.0 # 全リクエストをログ
}
}
|
3. 例外処理
緊急時のアクセスや特殊なユースケースに対応:
1
2
3
4
5
6
|
# 緊急時用の一時的なルール(priority 1500)
resource "google_network_security_gateway_security_policy_rule" "emergency_access" {
count = var.enable_emergency_access ? 1 : 0
priority = 1500
# 特定のIPから全GitHubアクセスを許可
}
|
まとめ
Secure Web Proxyを使用することで、Cloud WorkstationsからGitHubへのアクセスを、リポジトリレベルで細かく制御できるようになりました。
メリット
- ✅ セキュリティ: 必要最小限のアクセスのみ許可
- ✅ 柔軟性: リポジトリ単位での制御が可能
- ✅ 拡張性: 動的なルール生成により管理が容易
- ✅ 監査性: アクセスログによる追跡が可能
今後の改善点
- URLマッチングパターンの改善
- HTTPメソッド制限の追加
- より詳細なログ・監視の実装
この実装により、セキュリティと開発効率のバランスを保ちながら、クラウドネイティブな開発環境を実現できました。
参考リンク
この記事は、実際のプロダクション環境での実装経験に基づいています。セキュリティ要件は組織によって異なるため、実装時は自組織のポリシーに合わせて調整してください。