【Snowflake × Terraform】Cortex Analyst 用の Account Role を作る方法
はじめに
こんにちは、ナウキャストで LLM エンジニアをしている Ryotaro です。
最近 Cortex Analyst を検証として使う機会が増えてきました。PoC 段階で使う分には sandbox 環境などがあれば、強い権限ですぐに使えますが、本番環境に移行する際には適切な権限管理が必要になってきます。
そこで今回初めて Snowflake の Cortex Analyst を使うための Account Role を Terraform で作ってみて、いろいろ勉強になったので記事にしてみました。
想定する読者
- Snowflake Cortex Analyst を使う Role が Public 以外に欲しい人
- Snowflake Cortex Analyst を system user から利用したい人
前提
- Snowflake のリソースを Terraform で管理していること
- Snowflake Terraform Provider のバージョンは 2.5.0
必要な権限
公式ドキュメントでは、Cortex Analyst を使うためには以下の権限が必要と記載されています。
| 権限 | オブジェクト |
|---|---|
| READ または WRITE | Semantic Model の YAML ファイルを含むステージ |
| USAGE | Semantic Model で言及されている Cortex Search Service |
| SELECT | Semantic Model で言及されているテーブル |
なのですが、Cortex Analyst を使うのは Semantic Model の他、最近新しく出てきた Semantic View も使うことができます。
Semantic View とはデータベースに保存されている物理的なデータに対し、ビジネス上の意味(セマンティクス)を直接定義するための新しいオブジェクトです。中身は従来の Semantic Model と同じですが、それを Snowsight 上から作成・編集したりすることができます。
このとき Semantic Model は Stage に保存する必要があったので Cortex Analyst を使うためには、Stage に対して READ または WRITE の権限が必要だったのですが、Semantic View を使う場合は Semantic View に対する SELECT と REFERENCE の権限が必要となります。ここが一つのポイントです。
作成するオブジェクトの関係性
作成するオブジェクトの全体像を図にしてみました。基本的に database role を一つ作って、その role に対して DB の Object に対する権限を付与します。その後、account role にその database role と Cortex AI を使うための role を紐付けて作成します。
Terraform で作成する
では実際に Terraform で書いていきましょう
Database Object
まず、Cortex Analyst が対象とする DB などのオブジェクトを作ります。
- Database
- Schema
- Stage
################################################################################
# Database Object
################################################################################
resource "snowflake_database" "zenn_db" {
name = "ZENN_DB"
}
resource "snowflake_schema" "zenn_schema" {
database = snowflake_database.zenn_db.name
name = "ZENN_SCHEMA"
is_transient = false
with_managed_access = false
}
### semantic model を利用する場合は stage も用意する
resource "snowflake_stage" "zenn_semantic_model" {
database = snowflake_database.zenn_db.name
schema = snowflake_schema.zenn_schema.name
name = "ZENN_STAGE"
directory = "ENABLE = true"
}
Account Object / Database Role
次に、上記 DB リソースを利用するための Database role を作成します。下記では READ 権限を付与するための role を作成しています。
基本的に Cortex Analyst を使う場合は DB に対して書き込む操作を想定していないので、READ 権限のみを付与する role を作成します。
################################################################################
# Database role
################################################################################
# Read database role
resource "snowflake_database_role" "zenn_read_role" {
database = snowflake_database.zenn_db.name
name = "${snowflake_database.zenn_db.name}_DB_READ_ROLE"
}
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_database" {
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_database = snowflake_database.zenn_db.fully_qualified_name
privileges = [
"MONITOR",
"USAGE",
]
with_grant_option = false
}
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_schema" {
privileges = ["USAGE"]
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_schema {
all_schemas_in_database = snowflake_database.zenn_db.fully_qualified_name
}
with_grant_option = false
}
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_schema_all_tables_zenn_schema" {
privileges = ["SELECT"]
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_schema_object {
all {
object_type_plural = "TABLES"
in_schema = snowflake_schema.zenn_schema.fully_qualified_name
}
}
with_grant_option = false
}
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_schema_future_tables_zenn_schema" {
privileges = ["SELECT"]
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_schema_object {
future {
object_type_plural = "TABLES"
in_schema = snowflake_schema.zenn_schema.fully_qualified_name
}
}
with_grant_option = false
}
### semantic model を利用する場合は stage に対して READ 権限を付与する
resource "snowflake_grant_privileges_to_database_role" "zenn_read_on_semantic_stage" {
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
privileges = ["READ"]
on_schema_object {
object_type = "STAGE"
object_name = snowflake_stage.zenn_semantic_model.fully_qualified_name
}
}
Semantic View を利用する場合は、Semantic View に対する REFERENCES もしくは SELECT の権限が必要となるので、Semantic View に対して REFERENCES 権限を付与するための role を作成します。
# Grant REFERENCES privilege on all current semantic views in RFP_APP schema
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_schema_all_semantic_views_zenn_schema" {
privileges = ["REFERENCES", "SELECT"]
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_schema_object {
all {
object_type_plural = "SEMANTIC VIEWS"
in_schema = snowflake_schema.zenn_schema.fully_qualified_name
}
}
with_grant_option = false
}
# Grant REFERENCES privilege on all future semantic views in RFP_APP schema
resource "snowflake_grant_privileges_to_database_role" "zenn_read_db_role_on_schema_future_semantic_views_zenn_schema" {
privileges = ["REFERENCES", "SELECT"]
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
on_schema_object {
future {
object_type_plural = "SEMANTIC VIEWS"
in_schema = snowflake_schema.zenn_schema.fully_qualified_name
}
}
with_grant_option = false
}
ただ、Snowflake Terraform Provider のバージョンが 2.5.0 では、Semantic View を object type に指定することができず、terraform 上では Semantic View に対して権限を付与することができません。
そのため代替案として、
- semantic view だけ snowsight から手動でやる
- snowflake_execute を使って自分で書く
- semantic view ではなく、semantic model を使う
の 3 つの方法があります。
snowflake_execute を使って自分で書く場合は、以下のようになります。
# Grant REFERENCES and SELECT privileges on all current semantic views in RFP_APP schema using SQL execution
resource "snowflake_execute" "grant_references_select_on_all_semantic_views" {
execute = "GRANT REFERENCES, SELECT ON ALL SEMANTIC VIEWS IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} TO DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
revert = "REVOKE REFERENCES, SELECT ON ALL SEMANTIC VIEWS IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} FROM DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
}
# Grant REFERENCES and SELECT privileges on all future semantic views in RFP_APP schema using SQL execution
resource "snowflake_execute" "grant_references_select_on_future_semantic_views" {
execute = "GRANT REFERENCES, SELECT ON FUTURE SEMANTIC VIEWS IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} TO DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
revert = "REVOKE REFERENCES, SELECT ON FUTURE SEMANTIC VIEWS IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} FROM DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
}
Account Object / Account Role
これで、Semantic View に対して REFERENCES と SELECT の権限が付与されます。
最後に Cortex Analyst を使うための Account role を作成します。
ここでのポイントは SNOWFLAKE.CORTEX_USER という role を account role に紐付けている点です。 他にも Cortex Agents や Cortex Search などがありますが、Cortex AI 系の機能を使う時は必ずこの role が必要です。
################################################################################
# Account role
################################################################################
# Warehouse
resource "snowflake_warehouse" "zenn_warehouse" {
name = "ZENN_WH"
auto_resume = true
auto_suspend = 30
enable_query_acceleration = false
max_cluster_count = 1
max_concurrency_level = 8
min_cluster_count = 1
scaling_policy = "STANDARD"
statement_queued_timeout_in_seconds = 0
statement_timeout_in_seconds = 300
warehouse_size = "XSMALL"
warehouse_type = "STANDARD"
}
# Account role (for Cortex / semantic model)
resource "snowflake_account_role" "zenn_cortex_role" {
name = "ZENN_CORTEX_ROLE"
}
# Grant USAGE privilege on warehouse
resource "snowflake_grant_privileges_to_account_role" "zenn_cortex_role_on_warehouse" {
privileges = ["USAGE"]
account_role_name = snowflake_account_role.zenn_cortex_role.name
on_account_object {
object_type = "WAREHOUSE"
object_name = snowflake_warehouse.zenn_warehouse.fully_qualified_name
}
}
# Grant SNOWFLAKE.CORTEX_USER to account role
resource "snowflake_grant_database_role" "zenn_grant_cortex_user" {
database_role_name = "SNOWFLAKE.CORTEX_USER"
parent_role_name = snowflake_account_role.zenn_cortex_role.name
}
# Grant database role to account role
resource "snowflake_grant_database_role" "zenn_cortex_role_grant_db_read_role" {
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
parent_role_name = snowflake_account_role.zenn_cortex_role.name
}
これで、Cortex Analyst を使うための role が作成されました。
まとめ
Snowflake の Cortex Analyst を使うための Account Role を作る方法を紹介しました。ポイントは以下の 2 点でした。
-
SNOWFLAKE.CORTEX_USERという role を account role に紐付けている点 - Semantic View を利用する場合は
REFERENCESもしくはSELECTの権限が必要で、Terraform では対応されていないので、以下の 3 つの方法で対応する必要がある点- snowflake_execute を使う
- semantic view だけ snowsight から手動でやる
- semantic model を使う
というの 2 点でした。
Semantic View の権限付与に関しては、issue が起票されているので、今後のバージョンアップで対応されると思います。対応されれば、grant_privileges_to_database_role を使って Terraform で権限付与する形で記載できるようになると思います。
Snowflake の Terraform 実装は今回が初でしたが role 周りも色々と勉強になりました。弊社メンバーの方々にも色々と相談しながら作成しました。よかったらそちらの記事も見てみてください!
おまけ
Cortex Analyst から Cortex Search を使う場合も同様に Database role に対して Search Service の USAGE 権限を付与する必要があります。
resource "snowflake_grant_privileges_to_database_role" "zenn_usage_on_all_cortex_search_zenn_db" {
database_role_name = snowflake_database_role.zenn_read_role.fully_qualified_name
privileges = ["USAGE"]
on_schema_object {
all {
object_type_plural = "SEARCH_SERVICES"
in_schema = snowflake_schema.zenn_schema.fully_qualified_name
}
}
}
ただこれもまだ Terraform では対応されていないなので、snowflake_execute を使って自分で書く必要があります。
# Grant USAGE privilege on all current search services in RFP_APP schema using SQL execution
resource "snowflake_execute" "grant_usage_on_all_cortex_search" {
execute = "GRANT USAGE ON ALL SEARCH SERVICES IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} TO DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
revert = "REVOKE USAGE ON ALL SEARCH SERVICES IN SCHEMA ${snowflake_database.zenn_db.name}.${snowflake_schema.zenn_schema.name} FROM DATABASE ROLE ${snowflake_database_role.zenn_read_role.fully_qualified_name}"
}
We are Hiring!
この件についてもっと詳しく知りたい、議論したい、はたまたナウキャストという会社に興味を持ったという方は、カジュアル面談フォームから連絡ください。
Discussion