Eng (なりたい)

はやく エンジニア になりたい

Terraform で GCP のサービスアカウントを管理する

なぜ書いたか

Terraform Google Provider のIAM周りのリソースはたくさんある。

  • google_project_iam_policy
  • google_project_iam_binding
  • google_project_iam_member
  • google_service_account_iam_policy
  • google_service_account_iam_binding
  • google_service_account_iam_member
  • google_cloud_run_service_iam_policy
  • ...

たくさんある。

「手動でぽちぽちサービスアカウントを作るのも嫌だけど、Terraform のIAMも怖いし…」という気持ちになったので、これを機に整理してみます。もし間違いなどがありましたら、指摘していただけるととても喜びます。

やりたいこと

Terraform で任意の権限を付与した GCP のサービスアカウントを作成(管理)したい。

tl;dr

特定サービス(の全リソース)に対する権限を付与したい

例として、 sample というサービスアカウントに Cloud Run管理者(roles/run.admin) の権限を付与します。

resource "google_service_account" "sample" {
  project      = "<YOUR_PROJECT_ID>"
  account_id   = "sample"
  display_name = "Sample Service Account"
}

resource "google_project_iam_member" "sample" {
  project = "<YOUR_PROJECT_ID>"
  role    = "roles/run.admin"
  member  = "serviceAccount:${google_service_account.sample.email}"
}

https://i.gyazo.com/41d97cb5b368e823e84b48f0ba6e8301.png

想定通りのサービスアカウントができました。

このように 特定サービスの全リソースに対する権限を付与したい場合は google_project_iam_member を使います。

特定サービスの特定リソースに対しての権限を付与したい

例として、 sample というサービスアカウントに sample-bucket-kaito2 というバケットの管理者権限を付与します。

resource "google_storage_bucket" "sample" {
  project = "<YOUR_PROJECT_ID>"
  name    = "sample-bucket-kaito2"
}

resource "google_service_account" "sample" {
  project      = "<YOUR_PROJECT_ID>"
  account_id   = "sample"
  display_name = "Sample Service Account"
}

resource "google_storage_bucket_iam_member" "sample" {
  bucket = google_storage_bucket.sample.name
  role   = "roles/storage.admin"
  member = "serviceAccount:${google_service_account.sample.email}"
}

コンソールから INFO PANEL を確認すると sample-bucket-kaito2 バケットのみに対して想定通りの権限が付与されています。

Image from Gyazo

このようにサービス内の特定のリソースに対してのみ権限を付与したい場合は、 google_*_iam_member を使用します。

今回は GCS のため、 google_storage_bucket_iam_member でした。

まとめ

おまけ

google_service_account_iam_member がややこしい

google_service_account_iam_member特定サービスの特定リソースに対しての権限を付与したい で説明した google_*_iam_member に該当します。つまり、「特定のサービスアカウントに対しての権限を別のサービスアカウントに付与する」という目的で使います。ややこしいので注意してください。

なぜ *_iam_member を使うのか

IAM policy for projectsIAM policy for Cloud Storage Bucketを見ると、権限を付与するためのリソースとして、

  • *_iam_policy
  • *_iam_binding
  • *_iam_member

のバリエーションがあります。

その中で *_iam_member 以外のリソースは "Authoritative" と記載されており、これらは明示的に設定していないものをApply時に削除するという動作をします。

実際にドキュメントにも以下のような記述があるため 、 "Non-Authoritative" な *_iam_member を使うほうが安全です。

Authoritative. Sets the IAM policy for the project and replaces any existing policy already attached.

参考

Terraform(google provider) で Service Account に Role をバインドするときの罠 - Qiita

Terraform x GCP で、IAM権限を全削除してしまった - Qiita

Terraform Registry