パソコこんにちは!パソコです🔥 この記事、最後まで読んでいってね!
⏺ 記事1: VPC Service ControlsでのGitHub Actions対応:エラーベース権限設定のベストプラクティス
はじめに
Google Cloud の VPC Service Controls(VPC-SC)を enforced mode で運用している環境で、GitHub Actions による Terraform 実行が突然失敗するようになった経験はありませんか?
本記事では、VPC-SC 違反エラーの解決にエラーベース権限設定というアプローチを用いて、セキュリティを保ちながら効率的に権限を設定 する方法を解説します。
問題の背景
VPC Service Controls が dry-run mode から enforced mode に移行すると、今まで動いていた GitHub Actions ワークフローが以下のようなエラーで失敗するようになります:
Error 403: Request is prohibited by organization’s policy. vpcServiceControlsUniqueIdentifier: xxxxx
これは、GitHub Actions の Workload Identity Federation で使用するサービスアカウントが、VPC-SC で保護されたリソースにアクセスできなくなったためです。
エラーベース権限設定とは
従来のアプローチでは、事前に「必要そうな権限」をすべて付与することが多かったのですが、エラーベース権限設定では:
- 最小限の権限でスタート
- 実際にエラーが発生したタイミングで権限を追加
- エラーログから必要な権限を正確に特定
このアプローチにより、真に必要な権限のみを付与することができます。
実践:エラーログの読み方
VPC-SC違反が発生すると、Cloud Logging に詳細なエラーログが記録されます:
{ “protoPayload”: { “serviceName”: “storage.googleapis.com”, “methodName”: “google.storage.buckets.testIamPermissions”, “authenticationInfo”: { “principalEmail”: “github-actions-plan@project.iam.gserviceaccount.com” } } }
このログから以下の情報を読み取れます:
- 対象サービス: storage.googleapis.com
- 必要なメソッド: google.storage.buckets.testIamPermissions
- エラーの主体: GitHub Actions のサービスアカウント
VPC-SC Ingress Policy の設定
エラーログをもとに、ingress policy を設定します:
resource “google_access_context_manager_service_perimeter_ingress_policy” “github_actions” { perimeter = var.service_perimeter_name
ingress_from {
identities = [
"serviceAccount:github-actions-plan@project.iam.gserviceaccount.com",
"serviceAccount:github-actions-apply@project.iam.gserviceaccount.com"
]
sources {
access_level = "*" # GitHub Actions の IP は動的
}
}
ingress_to {
resources = ["projects/123456789"]
operations {
service_name = "storage.googleapis.com"
method_selectors {
method = "google.storage.buckets.testIamPermissions"
}
}
}
}
段階的な権限追加の実例
Terraform での一般的な権限追加パターン:
- 初期設定(Terraform state 管理)
operations { service_name = “storage.googleapis.com” method_selectors { method = “google.storage.objects.list” method = “google.storage.objects.get” method = “google.storage.buckets.get” } }
- エラー発生後の追加
operations { service_name = “storage.googleapis.com” method_selectors { method = “google.storage.objects.create” # state更新用 method = “google.storage.buckets.testIamPermissions” # 権限確認用 } }
- BigQuery リソース管理
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.get” permission = “bigquery.datasets.create” permission = “bigquery.tables.create” } }
ベストプラクティス
- ログ監視の自動化
VPC-SC違反を監視するクエリ例
gcloud logging read ' protoPayload.metadata."@type"=“type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata” AND protoPayload.authenticationInfo.principalEmail:“github-actions” ’ –format=“json”
- 権限の文書化
エラーベースで追加した権限は、なぜその権限が必要なのかをコメントで記録:
operations { service_name = “bigquery.googleapis.com” method_selectors { # Terraform での dataset 存在確認に必要 permission = “bigquery.datasets.get” # BigQuery audit log sink の作成に必要 permission = “bigquery.datasets.create” } }
- 定期的な権限見直し
使用されていない権限を定期的にチェック:
過去30日の API 使用状況を確認
gcloud logging read ' protoPayload.serviceName=“bigquery.googleapis.com” AND protoPayload.authenticationInfo.principalEmail:“github-actions” AND timestamp>=“2024-01-01” ’ –format=“table(protoPayload.methodName)”
まとめ
エラーベース権限設定は、VPC Service Controls 環境での権限管理において:
- セキュリティ向上: 最小権限の原則を実践
- 運用効率化: 不要な権限調査時間を削減
- 透明性確保: 権限付与の根拠が明確
GitHub Actions と VPC-SC の組み合わせでお困りの際は、ぜひこのアプローチを試してみてください。
記事2: Google CloudサービスのVPC Service Controls対応状況:メソッド指定の罠と対策
はじめに
VPC Service Controls(VPC-SC)で ingress/egress policy を設定する際、サービスによってメソッド指定の対応状況が大きく異なることをご存知でしょうか?
本記事では、実際に遭遇したエラーから学んだ、Google Cloud サービス別のメソッド指定対応状況と、それぞれの対策方法を詳しく解説します。
VPC-SC でのメソッド指定の基本
VPC-SC の ingress/egress policy では、以下の2つの方法でアクセス権限を指定できます:
- Permissions 指定
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.get” permission = “bigquery.tables.create” } }
- Methods 指定
operations { service_name = “storage.googleapis.com” method_selectors { method = “google.storage.objects.get” method = “google.storage.buckets.list” } }
サービス別対応状況一覧
実際に検証した結果、サービスごとに対応状況が大きく異なることが判明しました:
| サービス | 個別メソッド指定 | 対応形式 | 備考 |
|---|---|---|---|
| storage.googleapis.com | ✅ | フルパス | google.storage.objects.get |
| bigquery.googleapis.com | ✅ | permissions/methods併用 | 用途により使い分け |
| logging.googleapis.com | ✅ | 短縮形式 | ConfigServiceV2.GetSink |
| monitoring.googleapis.com | ❌ | * のみ | 個別指定不可 |
| secretmanager.googleapis.com | ❌ | * のみ | 個別指定不可 |
| datacatalog.googleapis.com | ❌ | * のみ | 個別指定不可 |
実際のエラーパターンと対策
パターン1: フルパス指定が必要なケース
エラー例(Storage): Error 400: METHOD ‘objects.get’ is not supported in storage.googleapis.com
対策:
❌ 短縮形式
method = “objects.get”
✅ フルパス指定
method = “google.storage.objects.get”
パターン2: 短縮形式でないとエラーになるケース
エラー例(Logging): Error 400: METHOD ‘google.logging.v2.ConfigServiceV2.GetSink’ is not supported in logging.googleapis.com
対策:
❌ フルパス
method = “google.logging.v2.ConfigServiceV2.GetSink”
✅ 短縮形式
method = “ConfigServiceV2.GetSink”
パターン3: 個別指定が一切サポートされないケース
エラー例(Monitoring): Error 400: METHOD ‘NotificationChannelService.GetNotificationChannel’ is not supported in monitoring.googleapis.com
対策:
❌ 個別メソッド指定
method = “NotificationChannelService.GetNotificationChannel”
✅ ワイルドカード使用
method = “*”
BigQuery の特殊ケース
BigQuery は permissions と methods の使い分けが重要です:
Permissions を使用するケース
operations { service_name = “bigquery.googleapis.com” method_selectors { # データセット・テーブル操作 permission = “bigquery.datasets.get” permission = “bigquery.tables.create” } }
Methods を使用するケース
operations { service_name = “bigquery.googleapis.com” method_selectors { # 特定の API 呼び出し method = “DatasetService.InsertDataset” method = “TableDataService.InsertAll” } }
IAM 操作の罠
BigQuery での IAM 操作は特に注意が必要です:
❌ BigQuery サービス内でのIAM指定(エラーになる)
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.getIamPolicy” # サポート外 method = “google.iam.v1.IAMPolicy.GetIamPolicy” # サポート外 } }
✅ 実際にはBigQueryの標準権限で処理される
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.get” permission = “bigquery.datasets.update” } }
効率的な調査方法
- エラーメッセージからの推測
エラーメッセージのパターンで対応状況を推測:
パターン1: フルパス不足
“METHOD ‘objects.get’ is not supported” → google.storage.objects.get を試す
パターン2: フルパス過多
“METHOD ‘google.logging.v2.ConfigServiceV2.GetSink’ is not supported” → ConfigServiceV2.GetSink を試す
パターン3: 個別指定不可
“METHOD ‘NotificationChannelService.GetNotificationChannel’ is not supported” → “*” を使用
- 段階的テスト戦略
Step 1: 具体的メソッドを試す
method = “SpecificMethod.Action”
Step 2: 短縮形式を試す
method = “Action”
Step 3: ワイルドカードにフォールバック
method = “*”
- ドキュメント確認
Google Cloud のドキュメントで対応状況を確認:
まとめとベストプラクティス
対応状況の把握
- Storage/BigQuery: 詳細な制御が可能
- Logging: 短縮形式で制御可能
- Monitoring/SecretManager: ワイルドカードのみ
設定時の推奨手順
- 具体的なメソッド指定から開始
- エラーに応じて形式を調整
- 最終手段として * を使用
- 設定理由をコメントで文書化
コメント記載例
operations { service_name = “monitoring.googleapis.com” method_selectors { method = “*” # 個別のメソッドは未サポート } }
VPC Service Controls の複雑な仕様に惑わされず、段階的なアプローチで効率的に設定を進めていきましょう。
記事3: Terraformプロバイダーから読み解く必要なGoogle Cloud権限設計
はじめに
Terraform で Google Cloud リソースを管理する際、「どの権限が本当に必要なのか?」という疑問を持ったことはありませんか?
特に VPC Service Controls 環境では、過不足ない権限設定が重要になります。本記事では、Terraform のリソース定義から必要な Google Cloud 権限を逆算し、効率的な権限設計を行う方法を解説します。
基本的な考え方
- Terraformリソース ≠ 必要権限
多くの場合、Terraform の1つのリソースを管理するために複数の Google Cloud 権限が必要になります:
resource “google_bigquery_dataset” “example” { dataset_id = “example_dataset” location = “US” }
このシンプルなリソースでも、実際には以下の権限が必要:
- bigquery.datasets.get (状態確認)
- bigquery.datasets.create (作成)
- bigquery.datasets.update (更新)
- CRUD操作の分析
Terraform の操作フローから必要権限を導き出せます:
| Terraform操作 | 必要なGoogle Cloud権限 |
|---|---|
| terraform plan | Read権限 (*.get, *.list) |
| terraform apply (作成) | Create権限 (*.create) |
| terraform apply (更新) | Update権限 (*.update, *.patch) |
| terraform destroy | Delete権限 (*.delete) |
実践例1: BigQuery Dataset管理
Terraformリソース定義
resource “google_bigquery_dataset” “analytics” { dataset_id = “analytics” friendly_name = “Analytics Dataset” description = “Dataset for analytics data” location = “US”
# データセットアクセス制御
access {
role = "OWNER"
special_group = "projectOwners"
}
access {
role = "READER"
user_by_email = "analyst@example.com"
}
}
必要権限の分析
基本的なデータセット操作:
VPC-SC Policy設定例
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.get” # plan時の状態確認 permission = “bigquery.datasets.create” # 初回作成 permission = “bigquery.datasets.update” # 設定変更 } }
アクセス制御の罠:
多くの人が見落とすのが、access ブロックによる IAM 操作です:
❌ 不十分な権限設定
permission = “bigquery.datasets.get” permission = “bigquery.datasets.create”
✅ IAM操作も含めた完全な設定
permission = “bigquery.datasets.get” permission = “bigquery.datasets.create” permission = “bigquery.datasets.update”
access ブロックの変更には update 権限が必要
実践例2: BigQuery Dataset Access管理
より複雑なケース
resource “google_bigquery_dataset_access” “analyst_access” { dataset_id = google_bigquery_dataset.analytics.dataset_id role = “READER” user_by_email = “analyst@example.com” }
resource “google_bigquery_dataset_access” “service_account_access” { dataset_id = google_bigquery_dataset.analytics.dataset_id role = “WRITER” user_by_email = “service-account@project.iam.gserviceaccount.com” }
権限設計
operations { service_name = “bigquery.googleapis.com” method_selectors { # データセット基本操作 permission = “bigquery.datasets.get” permission = “bigquery.datasets.update” # access変更に必要
# IAM操作(dataset_access リソース用)
# 注意: BigQueryのIAM操作は特殊で、標準的なIAM権限ではなく
# BigQuery固有の権限で制御される
}
}
実践例3: テーブル作成を含むケース
Terraformリソース
resource “google_bigquery_table” “user_events” { dataset_id = google_bigquery_dataset.analytics.dataset_id table_id = “user_events”
time_partitioning {
type = "DAY"
field = "event_timestamp"
}
schema = jsonencode([
{
name = "user_id"
type = "STRING"
mode = "REQUIRED"
},
{
name = "event_timestamp"
type = "TIMESTAMP"
mode = "REQUIRED"
}
])
}
拡張された権限設計
operations { service_name = “bigquery.googleapis.com” method_selectors { # データセット操作(依存関係で必要) permission = “bigquery.datasets.get”
# テーブル操作
permission = "bigquery.tables.get" # plan時の確認
permission = "bigquery.tables.create" # 作成
permission = "bigquery.tables.update" # スキーマ変更等
permission = "bigquery.tables.list" # 依存関係確認
}
}
実践例4: ロギング設定を含む複合ケース
Terraformリソース
resource “google_logging_project_sink” “bigquery_sink” { name = “bigquery-audit-sink” destination = “bigquery.googleapis.com/projects/${var.project}/datasets/${google_bigquery_dataset.audit_logs.dataset_id}” filter = “resource.type=bigquery_resource” unique_writer_identity = true }
resource “google_bigquery_dataset” “audit_logs” { dataset_id = “audit_logs” location = “US”
# Sink からの書き込み用アクセス
access {
role = "WRITER"
user_by_email = google_logging_project_sink.bigquery_sink.writer_identity
}
}
マルチサービス権限設計
BigQuery権限
operations { service_name = “bigquery.googleapis.com” method_selectors { permission = “bigquery.datasets.get” permission = “bigquery.datasets.create” permission = “bigquery.datasets.update” } }
Logging権限
operations { service_name = “logging.googleapis.com” method_selectors { method = “ConfigServiceV2.GetSink” # sink状態確認 method = “ConfigServiceV2.CreateSink” # sink作成 method = “ConfigServiceV2.UpdateSink” # sink更新 } }
権限設計のベストプラクティス
- 段階的な権限付与戦略
Phase 1: 基本的な読み取り権限
permission = “bigquery.datasets.get” permission = “bigquery.tables.get”
Phase 2: 作成権限(初回apply時に追加)
permission = “bigquery.datasets.create” permission = “bigquery.tables.create”
Phase 3: 更新権限(設定変更時に追加)
permission = “bigquery.datasets.update” permission = “bigquery.tables.update”
- 依存関係の理解
テーブル作成にはデータセット読み取り権限も必要
resource “google_bigquery_table” “example” { dataset_id = google_bigquery_dataset.example.dataset_id # この参照により必要 table_id = “example_table” }
必要権限:
- bigquery.datasets.get (依存関係確認)
- bigquery.tables.create (テーブル作成)
- 環境別の権限調整
locals { # 開発環境:より多くの権限 dev_permissions = [ “bigquery.datasets.get”, “bigquery.datasets.create”, “bigquery.datasets.update”, “bigquery.datasets.delete”, # 開発では削除も許可 “bigquery.tables.get”, “bigquery.tables.create”, “bigquery.tables.update”, “bigquery.tables.delete” ]
# 本番環境:最小権限
prod_permissions = [
"bigquery.datasets.get",
"bigquery.datasets.update", # 設定変更のみ
"bigquery.tables.get",
"bigquery.tables.update" # スキーマ変更のみ
]
}
検証とモニタリング
- 権限使用状況の確認
実際に使用された権限の確認
gcloud logging read ' protoPayload.serviceName=“bigquery.googleapis.com” AND protoPayload.authenticationInfo.principalEmail:“terraform-service-account” AND timestamp>=TIMESTAMP_FROM_RFC3339(“2024-01-01T00:00:00Z”) ’ –format=“table(protoPayload.methodName, protoPayload.authorizationInfo.permission)”
- 不要権限の特定
付与されているが使用されていない権限を特定
gcloud projects get-iam-policy PROJECT_ID
–flatten=“bindings[].members”
–filter=“bindings.members:terraform-service-account”
–format=“table(bindings.role)”
まとめ
Terraform リソースから Google Cloud 権限を設計する際のポイント:
- リソース定義の詳細分析: 単純なリソースでも複数の権限が必要
- 依存関係の考慮: 参照されるリソースの読み取り権限も必要
- 段階的な権限付与: plan → apply → update の流れに沿って権限を追加
- 環境別の調整: 開発と本番で異なる権限レベルを設定
- 継続的な見直し: 実際の使用状況に基づく権限の最適化
適切な権限設計により、セキュリティを保ちながら効率的な Terraform 運用が実現できます。
