Zenn

Snowflake × Terraform:依存関係の罠とその解決策

2025/03/18に公開
1

はじめに

ナウキャストでは、自社のデータプロダクト基盤をSnowflake上に構築し、Terraformによるリソース管理を行っています。また社外のクライアント様とのプロジェクトにおいても、Snowflakeを活用したデータ基盤の設計・構築を支援しています。本記事では、SnowflakeリソースをTerraformで管理する際に発生する依存関係の問題とその解決策について解説します。

具体的なケース

Terraformはリソース間の依存関係を解析し、適切な順序でリソースを作成・更新します。しかし、Terraformが自動的に認識することができない依存関係が存在するケースもあります。そのような場合はTerraformが正しい順序でリソースを作成できるよう、depends_onを引数として与えて明示的に依存関係を指定することができます。ここではdepends_onによる明示的な依存関係の指定が必要となる具体的なケースを解説します。

テーブルに対する操作権限の付与

Snowflakeのロールに対して、スキーマ内のテーブルに対する操作権限(SELECT, INSERT, UPDATE, DELETEなど)を付与する際、そのスキーマに対するUsage権限を持っている必要があります。また、スキーマに対するUsageを付与するためには、そのスキーマが属するデータベースに対するUsageが付与されていなければなりません。しかし、Terraformはこれらの依存関係を認識することができず、自動的に解決することができません。つまり、あるロールに対して「データベースに対するUsageの付与」「スキーマに対するUsageの付与」「テーブルに対する操作権限の付与」をそれぞれ定義するだけではこれらの依存関係をTerraformが解決することができず、apply実行時にエラーとなります。このようなケースでは、以下のようにdepends_onによって明示的に依存関係を指定することで適切な順序でロールへの権限付与が実行されるようになります。

1. データベースに対するUsageを付与

resource "snowflake_grant_privileges_to_database_role" "usage_database_to_my_role" {
  privileges         = ["USAGE"]
  database_role_name = snowflake_database_role.my_role.fully_qualified_name
  on_database        = snowflake_database_role.my_role.database
}

2. スキーマに対するUsageを付与

resource "snowflake_grant_privileges_to_database_role" "usage_schema_to_my_role" {
  privileges         = ["USAGE"]
  database_role_name = snowflake_database_role.select_table.fully_qualified_name
  on_schema {
    schema_name = snowflake_schema.my_schema.fully_qualified_name
  }

  # データベースに対するUsageを付与した後に実行されるように設定
  depends_on = [
    snowflake_grant_privileges_to_database_role.usage_database_to_my_role
  ]
}

3. テーブルの操作権限を付与

resource "snowflake_grant_privileges_to_database_role" "select_all_table_to_my_role" {
  privileges         = ["SELECT"]
  database_role_name = snowflake_database_role.my_role.fully_qualified_name
  on_schema_object {
    all {
      object_type_plural = "TABLES"
      in_schema          = snowflake_schema.my_schema.fully_qualified_name
    }
  }

  # スキーマに対するUsageを付与した後に実行されるように設定
  depends_on = [
    snowflake_grant_privileges_to_database_role.usage_schema_to_my_role
  ]
}

Shareオブジェクトに対する権限付与

Snowflakeには Share という機能があります。Shareとは、データを物理的にコピーすることなく、他のSnowflakeアカウントとデータを共有するための機能です。Shareオブジェクトにテーブルやビューなどの権限を付与し、これらの権限を通じて共有対象のSnowflakeアカウントからデータにアクセスできるように設定します。ここでも前節で解説したものと同様の依存関係が存在します。Shareオブジェクトに対して権限を付与する際も「データベースに対するUsageの付与」「スキーマに対するUsageの付与」「テーブルに対する操作権限の付与」を正しい順序で実行する必要があります。

1. データベースに対するUsageを付与

resource "snowflake_grant_privileges_to_share" "usage_database_to_share" {
  to_share    = snowflake_share.main.name
  privileges  = ["USAGE"]
  on_database = var.database_name
}

2. スキーマに対するUsageを付与

resource "snowflake_grant_privileges_to_share" "usage_schema_to_share" {
  for_each   = toset(local.target_schemas) # 共有対象スキーマのリスト
  to_share   = snowflake_share.main.name
  privileges = ["USAGE"]
  on_schema  = each.key

  # データベースに対するUsageを付与した後に実行されるように設定
  depends_on = [
    snowflake_grant_privileges_to_share.usage_database_to_share,
  ]
}

3. テーブルの操作権限を付与

resource "snowflake_grant_privileges_to_share" "select_table_to_share" {
  for_each   = toset(var.target_tables) # 共有対象テーブルのリスト
  to_share   = snowflake_share.main.name
  privileges = ["SELECT"]
  on_schema  = each.key

  # スキーマに対するUsageを付与した後に実行されるように設定
  depends_on = [
    snowflake_grant_privileges_to_share.usage_schema_to_share,
  ]
}

Managed Access Schema の Ownership 変更

Snowflakeには Managed Access Schema という機能があります。このオプションが有効化されたスキーマでは、そのスキーマの所有者(OWNERSHIP権限を持つロール)だけが、そのスキーマ内のオブジェクト(テーブルやビューなど)に対する権限の操作を行うことができます。Managed Access Schema をTerraformで管理する際には依存関係に注意しなければならないケースがあります。それはスキーマの所有者を変更する場合です。

Terraformでスキーマを作成する場合、Terraformの実行ロールがそのスキーマのOWNERSHIP権限を持つことになりますが、権限管理の方針等によりOWNERSHIPを別のロールに移譲したい場合があります。しかし、Managed Access Schemaにおいて、そのスキーマ内のオブジェクトに対するOWNERSHIPFUTURE GRANTSが設定されている場合、スキーマのOWNERSHIP移譲が失敗する場合があります。

例えば、Managed Access Schemaにおいて、スキーマのOWNERSHIPを持つownership_schemaロールと、スキーマ内のテーブルのOWNERSHIPを持つownership_tableロールをそれぞれ分けて管理する場合を考えます。スキーマについては、Terraform実行ロールからownership_schemaロールにOWNERSHIPを移譲します。一方、スキーマ内のテーブルについては、将来作成されるものも含めた全てのテーブルに対するOWNERSHIPownership_tableロールに付与します。この時「ownership_schemaロールに対してスキーマのOWNERSHIPを移譲」した後に「ownership_tableロールに対してテーブルのOWNERSHIPFUTURE GRANTSを実行」するという順序でなければTerraformのapply実行時にエラーが発生します。このようなケースでは、以下のようにdepends_onを設定することで依存関係の問題を回避します。

1. ownership_schema にスキーマの OWNERSHIP を移譲

resource "snowflake_grant_ownership" "grant_ownership_schema" {
  database_role_name  = snowflake_database_role.ownership_schema.fully_qualified_name
  outbound_privileges = "COPY"
  on {
    object_type = "SCHEMA"
    object_name = snowflake_schema.my_schema.fully_qualified_name
  }
}

2. ownership_table にテーブルの OWNERSHIP の FUTURE GRANTS を実行

resource "snowflake_grant_ownership" "grant_ownership_future_table" {
  database_role_name  = snowflake_database_role.ownership_table.fully_qualified_name
  outbound_privileges = "COPY"
  on {
    future {
      object_type_plural = "TABLES"
      in_schema          = snowflake_schema.my_schema.fully_qualified_name
    }
  }

  # ownership_schemaにスキーマのOWNERSHIPを移譲してから実行
  depends_on = [
    snowflake_grant_ownership.grant_ownership_schema
  ]
}

終わりに

TerraformでSnowflakeリソースを構築する際、Terraformが自動的に認識することができない依存関係によりエラーが発生するケースがあります。本記事ではそのような依存関係が問題となる具体的なケースを紹介し、適切な依存関係の指定について解説しました。

とはいえ、すべての開発者が毎回これらの依存関係を意識してTerraformを書くのは大変です。そのため、ナウキャストでは、標準的なリソース構成を定めた上で共通のモジュールを開発し、チーム全体として一貫性を保ちつつ、開発の効率化を図っています。

本記事の内容が、TerraformとSnowflakeを活用する皆さまの参考になれば幸いです。

1
Finatext Tech Blog

Discussion

ログインするとコメントできます