Terraform でインフラストラクチャを管理している場合, tfsec を使用することで,セキュリティとして好ましくない設定を簡単に検知できます.
https://aquasecurity.github.io/tfsec/v1.28.1/
tfsec is a static analysis security scanner for your Terraform code.
好ましくない設定のルールが事前定義されており,以下に公開されています.
https://aquasecurity.github.io/tfsec/v1.28.1/checks/
この中に,google-iam-no-project-level-service-account-impersonation というルールが存在します.
Users should not be granted service account access at the project level.
Users with service account access at project level can impersonate any service account. Instead, they should be given access to particular service accounts as required.
プロジェクトレベルでサービスアカウントへのアクセスを許可してはならない.
プロジェクトレベルでサービスアカウントへのアクセスを許可されたユーザーは,任意のサービスアカウントとして操作が可能になります.その代わりに,必要に応じて特定のサービスアカウントへのアクセスを許可するべきです. (拙訳: みー)
例えば,Cloud PubSub を使用して,Cloud Run にリクエストを送信するように Terraform で構成するケースで考えます.リクエストの流れはこのようになります.
PubSub Topic a
→ PubSub Subscription a
→ Cloud Run target
以下のような tf ファイルが考えられますが,過剰な権限を付与しています.
resource "google_service_account" "sa" { account_id = "cloud-run-invoker" } resource "google_project_iam_member" "sa-token" { project = var.project role = "roles/iam.serviceAccountTokenCreator" member = "serviceAccount:${google_service_account.sa.email}" } resource "google_cloud_run_service" "target" { name = "target" template { spec { service_account_name = google_service_account.sa.email } } resource "google_pubsub_topic" "a" { name = "topic-a" } resource "google_pubsub_subscription" "a" { name = "subscription-a" topic = google_pubsub_topic.a.name push_config { push_endpoint = "${google_cloud_run_service.target.status[0].url}/endpoint" oidc_token { audience = google_cloud_run_service.target.status[0].url service_account_email = google_service_account.sa.email } } }
google_project_iam_member
で権限を付与するとプロジェクトレベルの権限となるため,代わりに google_service_account_iam_member
を使用し,権限の範囲を絞ります.この時に,google_service_account_iam_member
の元になるサービスアカウントが必要になります.先程はプロジェクトレベルの権限を付与していたため気にしなくてもよかったのですが,PubSub が動作するデフォルトのサービスアカウントを取得する必要があります.これは google_project_service_identity
を使用すれば解決できます.
resource "google_project_service_identity" "pubsub" { project = var.project provider = google-beta service = "pubsub.googleapis.com" } resource "google_service_account_iam_member" "sa-token" { service_account_id = google_service_account.sa.name role = "roles/iam.serviceAccountUser" member = "serviceAccount:${google_project_service_identity.pubsub.email}" }
tfsec を実行して,google-iam-no-project-level-service-account-impersonation を指摘されなくなりましたので,修正完了です.
参考
- https://aquasecurity.github.io/tfsec/v1.28.1/checks/google/iam/no-project-level-service-account-impersonation/
- https://cloud.google.com/pubsub/docs/push#properties_of_a_push_subscription
- https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountUser
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam#google_service_account_iam_member
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_service_identity