💣
【GCP】Terraformでpolicyは弄ってはいけない
各プロバイダーの権限の仕組みの理解が疎かな状態でTerraformを書くと、スーパーユーザーじゃないと何もできない、terraform plan
さえも通らない、Web UIからも参照できないリソースができあがっちゃうので注意しよう という話です。
事例
やりたかったこと
外部公開したいデータを格納するため公開バケットを作成したい
誤ったコード
resource "google_storage_bucket" "oidc_keys" {
name = "hoge_bucket"
location = var.region
project = data.terraform_remote_state.project.outputs.project_id
storage_class = "STANDARD"
force_destroy = false
versioning {
enabled = true
}
uniform_bucket_level_access = true
}
data "google_iam_policy" "viewer" {
binding {
role = "roles/storage.objectViewer"
members = [
"allUsers",
]
}
}
resource "google_storage_bucket_iam_policy" "editor" {
bucket = "${google_storage_bucket.bucket.name}"
policy_data = "${data.google_iam_policy.viewer.policy_data}"
}
どうなるか
こんなバケットができちゃいます。
- terraform planさえ通らない
- gcloud CLIの参照系APIも通らない
- スーパー権限以外何もできない
- オブジェクト直指定での参照はできる(多分)
何がダメなのか
GCPの権限管理では、ポリシーとロールバインディングは下記のようなリソースになっています。
- ポリシー:ロールバインディングの集合
- ロールバインディング:メンバーと、そのメンバーに付与されたロールの紐付けを行うデータ
よって、ポリシーをterraformで定義すると、リソース作成時に自動的に作成されるデフォルトポリシーを破壊する可能性があります。
AWSを使っているとpolicyというワードでそのままリソースを作成したくなりますが、注意が必要です。
今回のコードも、既存のポリシーを上書きしたことで、全てのユーザーがオブジェクト参照しかできない状態になってしまいました。
正しい(期待通り動作する)コード
ロールバインディングを定義してあげれば期待通り、既存のポリシーへのバインディング追加になります。
# bucket定義は省略
resource "google_storage_bucket_iam_binding" "public_bucket_iam_binding" {
bucket = google_storage_bucket.hoge_bucket.name
role = "roles/storage.objectViewer"
members = [
"allUsers",
]
}
まとめ
リソースのアクセス権限を調整する際は、providerの権限管理をきちんと理解してから行うべきです。同じ用語でもproviderによって意味が全く異なっていたりするので注意です。
参考資料
Discussion