弊社ではGCPをterraformで管理し始めました。知見が溜まってきているのでここにまとめておこうと思います。
MOCHI.incでは組織アカウントの管理も全てterraformとcloud identityを経由して管理しています。
MOCHI.incでやりたかったことは
ということでした。
data "google_iam_policy" "admin_project" {
binding {
role = "roles/viewer"
members = var.leader_control_group
}
binding {
role = "roles/storage.admin"
members = var.leader_control_group
}
}
resource "google_project_iam_policy" "project" {
project = var.admin_project_id
policy_data = data.google_iam_policy.admin_project.policy_data
}
data "google_iam_policy" "admin_project_service_account_owner" {
binding {
role = "roles/iam.serviceAccountUser"
members = var.owner_control_group
}
}
resource "google_service_account_iam_policy" "terraform" {
service_account_id = var.terraform_service_account.name
policy_data = data.google_iam_policy.admin_project_service_account_owner.policy_data
}
resource "google_organization_iam_binding" "billing" {
org_id = var.organization_id
role = "roles/billing.user"
members = var.leader_control_group
}
data "google_iam_policy" "service_folder_policy" {
binding {
role = "roles/resourcemanager.projectCreator"
members = var.leader_control_group
}
binding {
role = "roles/owner"
members = var.owner_control_group
}
}
resource "google_folder_iam_policy" "project_folder" {
folder = "folders/${var.project_folder_id}"
policy_data = data.google_iam_policy.service_folder_policy.policy_data
}
実際に以上のことを実現するために書かれたterraformのコードになります。
Cloud IdentityのアカウントはG Suiteと連携しているので、terraformでdestroyする時には十分注意してください。terraformでGCPのリソースをいじれるようにするために課金を有効にする必要がありますが、この課金アカウントだけはorganizationにiamを登録する必要があります。
ここでgoogleorganizationiambindingを誤って、googleorganization_iam resourceで書いてしまって実行すると、既存のアカウントを全て作り直してしまって、組織全員のiamが吹きとんでしまうという大事故が起きるのでapply前の確認を怠らないようにしましょう。
また、organization_iamに限らず、GCPのterraformのresource内のbindingの記述はリソースを作り直してしまうのでbindingの追加はgoogle_~_binding
または、google_~_member
のようにbindingを紐づけるだけのAPIを利用しましょう。
(追記: binding系のAPIはroleに対して未定義のresourceの権限を奪ってしまうようです。memberやserviceアカウントにroleを紐づける場合はgoogle_project_iam_member等のAPIを利用しましょう。)
MOCHIのインフラはprojectを複数に分割しています。
GCPのブログ を参考にしました。
この仕組みに加えて、最初のgcsはローカル上のterraformで作るようにしてあります。
terraform-adminアカウントにmembershipを用いて、
gcloud auth application-default login
を利用することでTerraformのサービスアカウントを利用せずにTerraformを実行できるようになります。 注意点は
gcloud config set project $project_id
によって現在の操作対象のGCPプロジェクトを変更した場合、
gcloud auth application-default login
を実行し直す必要が生じます。
また、利用しているGCPプロジェクトを削除すると、このプロジェクトにログインしているアカウントに紐づいているロールが仮に他のGCPプロジェクトに対するロールを保持しているユーザーでログインした場合でも、他のプロジェクトにログインし直すまで、GCPプロジェクトを対象にした操作ができなくなるようです。
このためdev環境を削除したりリソースをコマンド経由で操作するためにプロジェクトを切り替えていることを忘れると、プロジェクトへのterraform apply
が通らなくて焦ったりするわけですが、adminアカウントに切り替えることできちんとapplyが通るようになりました。
サービスアカウントの検索などでは
--labels="cloudidentity.googleapis.com/groups.discussion_forum"
というフラグが必須になっていたりします。これは、Googleがこのタグをサービスアカウントの識別に利用しているためで、このタグにはvalueをつけるように設定できるような仕様になっていますが、このタグは、valueなしのタグとして設定されているため、サービスアカウントを検索する場合はタグ名だけを指定するという仕様になっています。
これは非常に分かりづらい仕様なので、おそらくbetaたる所以なのかなと思いますが、このAPIからサービスアカウトの情報や情報を取得するケースが非常に多かったので、覚えておくと良いかもしれません。
gcloud beta identity groups search --labels="cloudidentity.googleapis.com/groups.discussion_forum" --organization='${organization name}'