【Snowflake】terraform-provider-snowflakeのenable_multiple_grantsにはまった話

背景

TerraformでSnowflake基盤を管理する際に、権限系のリソースオプションであるenable_multiple_grantsにはまったときの話。

TL;DR

こだわりなければ、権限に関するリソースオプションのenable_multiple_grants=trueにしておいていいかもしれない。

terraform-provider-snowflakeの0.68以上のバージョンを利用していればsnowflake_grant_privileges_to_roleリソースを利用する方がよさそう。

そもそもenable_multiple_grantsオプションとは?

registry.terraform.io

(Boolean) When this is set to true, multiple grants of the same type can be created.

This will cause Terraform to not revoke grants applied to roles and objects outside Terraform.

公式のドキュメントをみると、どうやらTerraformで管理しているオブジェクトの権限に関して、Terraform外で設定された権限が存在する場合、剥奪するかどうかを決めることができるらしい。

  • true  → Terraform外で権限が設定されたとしてもなにもしない

  • false → Terraform外で設定した権限を剥奪するようになる

挙動については理解できたが、どうやら期待した動作と異なるケースがかなり見受けられる。

GithubIssuesを見ても、権限に関するバグに遭遇している人は多そう。

内容

enable_mltiple_grantsに関するバグは多そうなので、今回は自分が遭遇したバグを紹介しようと思う。

例えば以下のような構成で考える。

  • PROJECT_A_DBというDBが1つ
  • DBのフルアクセス権限(ALL PRIVILEGES)を持つアクセスロール
  • DBのRead-Only権限(READ)を持つアクセスロール

Snowflakeの構成

Terraformにおけるリソース定義は以下。

-- database
resource "snowflake_database" "project_a_db" {
  provider = snowflake.sys_admin
  name = upper("project_a_db")
}

-- access role for full access to a database
resource "snowflake_role" "project_a_db_full_access" {
  provider = snowflake.user_admin
  name = upper("project_a_db_full_access")
}

-- access role for read-only access to a database
resource "snowflake_role" "project_a_db_read_access" {
  provider = snowflake.user_admin
  name = upper("project_a_db_read_access")
}

-- grant full access role to a database
resource "snowflake_database_grant" "project_a_db_full_grants" {
  provider = snowflake.sys_admin
  database_name = snowflake_database.project_a_db.name 
  privilege = "ALL PRIVILEGES"
  roles = [
    snowflake_role.project_a_db_full_access.name
  ]
  enable_multiple_grants = false
}

-- grant read-only access role to a database
resource "snowflake_database_grant" "project_a_db_read_grants" {
  provider = snowflake.sys_admin
  database_name = snowflake_database.project_a_db.name 
  privilege = "USAGE"
  roles = [
    snowflake_role.project_a_db_read_access.name
  ]
  enable_multiple_grants = false
}

1回目のデプロイ

Snowflake上にPROJECT_DB_ABのDB権限に関しては、リソース定義通りに各ロールに対して権限が設定されていることがわかる。

2回目のデプロイ

問題はここ。

なにもリソースを更新していなくても、terraform planするとなぜか権限に関する差分がでてきてしまう。

さらに、terraform applyすると、PROJECT_A_DB_FULLに付与されていたUSAGE権限が剥奪されてしまう。

なぜ差分がでてくる?

はっきりとした原因はわかってないが、

  • DBのUSAGE権限が複数のロール(PROJECT_A_DB_FULL, PROJECT_A_DB_READ)に付与されている

  • その複数のロールが別々のリソースとして定義されている

を満たす場合、今回のようなバグに遭遇してしまう。

まとめ

結局のところenable_multiple_grants=trueにしておけば、今回の問題は解決されるみたいだけど、なんかモヤモヤ感がとれない。

enable_multiple_grantsに関してはバグが多く、はまることも多いが誰かの参考になればうれしいな。