Google IAMのメンバー設定を記述していて、いちいち resource
を繰り返し定義するのがバカらしくなったので調べてみました。
やりたいこと
2つのサービスアカウント、3つのロールについて、 google_project_iam_member を設定する
サービスアカウント
compute-engine@hogehoge.iam.gserviceaccount.com
cloud-functions@hogehoge.iam.gserviceaccount.com
ロール
roles/bigquery.jobUser
roles/bigquery.dataViewer
roles/bigquery.dataEditor
愚直に書くと…
resource "google_project_iam_member" "computeEngine-bigquery_jobUser" {
role = "roles/bigquery.jobUser"
member = "serviceAccount:compute-engine@hogehoge.iam.gserviceaccount.com"
}
面倒くさいこと
- これを2 * 3 = 6回書かなければならない
- もし 3 * 4 になると12回も書かなければならない
- それぞれユニークに名付ける
- 抜け漏れ確認
- 対象ロールやサービスアカウントが増えたらまたコピペ地獄
ループしちゃえ
サービスアカウント、ロールの配列を定義
locals {
# サービスアカウント、ロールの配列を定義
service_accounts = [
"compute-engine@hogehoge.iam.gserviceaccount.com",
"cloud-functions@hogehoge.iam.gserviceaccount.com"
]
roles = [
"roles/bigquery.jobUser",
"roles/bigquery.dataViewer",
"roles/bigquery.dataEditor",
]
# setproduct で総当りの組み合わせをループしながらtupleを作る(ついでにmemberを加工)
iam_members = [
for pair in setproduct(local.roles, local.service_accounts) : {
role = pair[0]
member = "serviceAccount:${pair[1]}"
}
]
}
この時点で output
で確認してみるとこのようになります。
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
Plan: 0 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ iam_members = [
+ {
+ member = "serviceAccount:compute-engine@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.jobUser"
},
+ {
+ member = "serviceAccount:cloud-functions@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.jobUser"
},
+ {
+ member = "serviceAccount:compute-engine@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.dataViewer"
},
+ {
+ member = "serviceAccount:cloud-functions@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.dataViewer"
},
+ {
+ member = "serviceAccount:compute-engine@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.dataEditor"
},
+ {
+ member = "serviceAccount:cloud-functions@hogehoge.iam.gserviceaccount.com"
+ role = "roles/bigquery.dataEditor"
},
]
ちゃんと6つの要素ができています。
resource
で利用する
# "${item.member}__${item.role}" はリソースの名前になるため、ユニークなキーにしなければならない
resource "google_project_iam_member" "iam_members" {
for_each = { for item in local.iam_members : "${item.member}__${item.role}" => item }
# each.key は "${item.member}__${item.role}"
role = each.value.role
member = each.value.member
}
もちろん、 locals.iam_members
を定義せず、 resource
内でインライン利用することもできます。
locals
にロジックを書きたくない場合はこちらもアリかもですね。
resource "google_project_iam_member" "iam_members" {
for_each = {
for item in [
for pair in setproduct(local.roles, local.service_accounts) : {
role = pair[0]
member = "serviceAccount:${pair[1]}"
}
] : "${item.member}__${item.role}" => item
}
role = each.value.role
member = each.value.member
}
参考