概要
TerraformでGoogle CloudのIAM設定をする際に、ロールとプリンシパルの組み合わせを変数で管理する方法について書きます。
TerraformでIAMの設定をする際には、google_*_iam_member
やgoogle_*_iam_binding
といったリソースで定義します1。
しかし、1ロールの設定毎に1リソースで定義すると、割り当てるロールやプリンシパルや種類が増える場合にリソース数が増え、命名が複雑化し、管理もしづらくなります。
そこで、IAMロールとプリンシパルの組み合わせをローカル変数(mapのlist)で定義し、IAM権限の設定を1リソースで定義します。
リソースはgoogle_*_iam_binding
を使ってますが、google_*_iam_member
などでも同様に読み替え可能かと思います。ただし、併用はできないのでご注意ください。
前提
Providerは以下を想定します。
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.50.0"
}
}
}
以降の例では、以下の要件を満たすようなGCSバケットのIAM設定を想定します。
- メンテナー(Googleグループ)は、バケット設定を編集できるようにしたい
- アプリ(サービスアカウント)は、オブジェクトの更新をできるようにしたい
- 誰でもオブジェクトを閲覧できるよう公開したい
ローカル変数の定義
ローカル変数を以下のように定義します。
# GCSにアクセスするプリンシパル
locals {
maintainer_principal = "group:<Googleグループのメールアドレス>
app_sa_principal = "serviceAccount:<サービスアカウントのメールアドレス>
}
locals {
# ロールとプリンシパルの組み合わせで変数を定義
storage_iam = [
{
# メンテナーの手動操作でバケットの設定変更を許可する
role = "roles/storage.admin",
members = [
local.maintainer_principal,
]
},
{
# アプリからの操作と、メンテナーによる手動操作でオブジェクトの更新を許可する
role = "roles/storage.objectAdmin",
members = [
local.maintainer_principal,
local.app_sa_principal,
]
},
{
# GCSバケットはインターネットに公開する
role = "roles/storage.objectViewer",
members = [
"allUsers",
]
}
]
バケット内のオブジェクトをインターネットに公開する設定については公式ドキュメントを参照しました。
GCSバケットの設定
バケットを定義し、先ほど定義したローカル変数を用いてIAM権限の設定をします。
for_eachのループによりそれぞれ設定されるので、個別にリソースを定義する必要がなくなります。
# バケットの定義は適当です。バケット名はグローバルで一意にする必要があります。
resource "google_storage_bucket" "hoge_fuga_storage" {
name = "hoge-fuga-storage"
location = "ASIA"
}
# ローカル変数を参照し、IAM権限を設定する。
resource "google_storage_bucket_iam_binding" "hoge_fuga_storage_iam_binding" {
for_each = { for i in local.storage_iam : i.role => i }
bucket = google_storage_bucket.hoge_fuga_storage.name
role = each.value.role
members = each.value.members
}
まとめ
IAMロールとプリンシパルの設定をmapのlistとしてまとめることで、IAM設定をシンプルにする方法について書きました。
TerraformはIAM設定を1つのリソースとして定義するため、権限変更が重なった場合にリソース名の命名規則を一定に保つことは個人的に難しいと感じました。そのため、IAM設定に関してはあらかじめ変数化しておき、柔軟に変更できるようにしておくのが、個人的にはいいのではないかと考えています。
また、複数の権限修正であっても1箇所に変更が集中するため、レビュー時に差分を比較しやすいというメリットも挙げられると思います。