はじめに
TerraformでSnowflakeを構築する手順としては、Snowflakeが出しているチュートリアルを参考にすると分かりやすいです。
しかしチュートリアル通りにやっても上手くいかずハマったポイントがあったので、自分なりに手順をまとめました。
環境
- macOS Ventura 13.1
- Homebrew 4.0.11
概要
この記事ではチュートリアルを参考にしつつ自分なりに少し修正し、最終的にTerraformを用いて以下リソースをSnowflake上に作成する手順を紹介します。
- データベース
- スキーマ
- ステージ
- ウェアハウス
- ユーザー
- ロール
- 諸々の権限付与
1. Terraformインストール
ローカルで開発を進めるにはTerraformをインストールする必要があるので、まだしていない場合はインストールしておきましょう。
tfenvをインストール
$ brew install tfenv
バージョン確認
$ tfenv --version
インストール可能なTerraformバージョン確認
$ tfenv list-remote
2023/04/09時点では最新はv1.4.4なのでそれをインストール
$ tfenv install 1.4.4
インストールしたバージョンのTerraformを使用するように指定
$ tfenv use 1.4.4
2. Snowflake準備
Snowflakeは無料で30日間のトライアルアカウントを作成できるので、まだない場合はアカウントを作成しておきます。
画面の指示通りに項目を記入していけば簡単にアカウントが作成できます。
私はEditionはスタンダード
、クラウドプロバイダーはAWS
、リージョンはAsia Pacific (Tokyo)
を選択しました。
アカウントを作成するとメールが届くので、アカウントを有効化してログインしておきましょう。
3. 接続準備
以下を実行し、接続に使うための鍵を作成してクリップボードにコピーしておきます。
$ cd ~/.ssh
$ openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out snowflake_tf_snow_key.p8 -nocrypt
$ openssl rsa -in snowflake_tf_snow_key.p8 -pubout -out snowflake_tf_snow_key.pub
$ cat snowflake_tf_snow_key.pub | pbcopy
次にSnowflake上で以下を実行します。
やってることはTerraformで使用するSnowflakeユーザーの作成と、そのユーザーへのロール付与です。
CREATE USER "tf-snow"
RSA_PUBLIC_KEY='${生成した公開鍵}'
DEFAULT_ROLE=PUBLIC
MUST_CHANGE_PASSWORD=FALSE;
GRANT ROLE SYSADMIN TO USER "tf-snow";
GRANT ROLE SECURITYADMIN TO USER "tf-snow";
※公開鍵をペーストした際に前後に-----BEGIN PUBLIC KEY-----
, -----END PUBLIC KEY----—
も入ると思うので、それは忘れずに消しておいてください。
作成したユーザーに2つのロールを使用できるようにしていますが、以下のように使い分けます。
-
SYSADMIN
: データベースやスキーマ、ウェアハウスなどのオブジェクト作成 -
SECURITYADMIN
: ユーザーとロールの作成、権限付与
そして環境変数を設定するためにローカルで以下を実行します。
$ export SNOWFLAKE_USER="tf-snow"
$ export SNOWFLAKE_PRIVATE_KEY_PATH="~/.ssh/snowflake_tf_snow_key.p8"
$ export SNOWFLAKE_ACCOUNT="${アカウントLocator}"
$ export SNOWFLAKE_REGION="${リージョンID}"
アカウントLocator
はURLに含まれるxy12345
のような文字列です。
リージョンID
は、私はアカウント作成時にAWSのAsia Pacific (Tokyo)
を選択したので、ap-northeast-1.aws
になります。
これらの情報はSnowfalke上で以下を実行することでも確認できます。
SELECT
current_account() as YOUR_ACCOUNT_LOCATOR,
current_region() as YOUR_SNOWFLAKE_REGION_ID;
※リージョンID
に関しては、ドキュメントを参考に対応するクラウド地域IDに変換する必要があります(必要ならクラウドプロバイダー名も加える)。
環境変数はターミナルを立ち上げる度に入力しないといけないので、snow.env
などのファイルを用意しそこに記載しておくと次回以降入力が楽です。
(Gitでコード管理する場合はsnow.env
を.gitignore
へ追加するのを忘れずに)
4. Terraform実装
プロジェクトのベースディレクトリにmain.tf
を作り、以下を貼り付けてください。
terraform {
required_providers {
snowflake = {
source = "Snowflake-Labs/snowflake"
version = "0.42.1"
}
}
}
provider "snowflake" {
role = "SYSADMIN"
}
resource "snowflake_database" "db" {
name = "TF_DEMO_DB"
}
resource "snowflake_warehouse" "warehouse" {
name = "TF_DEMO_WH"
warehouse_size = "large"
auto_suspend = 60
}
Providerのバージョンを0.42.1に固定しています。
チュートリアルでは0.35
以上の最新のバージョンを使用するようにしていますが、比較的新しいバージョンだと、スタンダードエディションではエラーが出てしまします。
ウェアハウス作成時にスタンダードディションでは利用できないパラメータが自動で追加されてしまうことが原因で起こるエラーで、2023/04/09時点で最新のバージョン0.61.0
でも解決はしていないようです。
そのため問題なく使える0.42.1
あたりを使用するのが妥当だと思います。
5. Terraform実行
プロジェクトのディレクトリで以下を実行します。
Terraformの実行に必要な依存関係や、状態を保持するファイルがローカルにダウンロードされます。
$ terraform init
Gitでコード管理している場合、作成された状態ファイルなどはpushしてしまわないように.gitignore
に追加しておきましょう。
*.terraform*
*.tfstate
*.tfstate.*
次に以下を実行し、Terraformを実行した場合の変更内容を確認します。
$ terraform plan
データベースとウェアハウスを作成するという変更内容になっていると思います。
リソースの変更内容に問題がなければ、以下を実行します。
$ terraform apply
再度変更内容が表示され適用して良いか聞かれると思うので、問題なければyes
と入力してください。
成功するとSnowfalke上でデータベースとウェアハウスが作成されます。
6. リソースの追加
最後にその他のリソースを作っていきましょう。
main.tf
に以下を追加してください。
// SECURITYADMINロールで操作できるように
provider "snowflake" {
alias = "security_admin"
role = "SECURITYADMIN"
}
// ロール作成
resource "snowflake_role" "role" {
provider = snowflake.security_admin
name = "TF_DEMO_ROLE"
}
// データベースへの権限付与
resource "snowflake_database_grant" "grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
privilege = "USAGE"
roles = [snowflake_role.role.name]
with_grant_option = false
}
// スキーマ作成
resource "snowflake_schema" "schema" {
database = snowflake_database.db.name
name = "TF_DEMO_SCHEMA"
}
// デフォルトスキーマへの権限付与
resource "snowflake_schema_grant" "schema_default_grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
schema_name = snowflake_schema.schema.name
privilege = "USAGE"
roles = [snowflake_role.role.name]
with_grant_option = false
}
// スキーマへの権限付与(今後作成されるものも含む)
resource "snowflake_schema_grant" "schema_grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
privilege = "USAGE"
roles = [snowflake_role.role.name]
with_grant_option = false
on_future = true
}
// テーブルへの権限付与(今後作成されるものも含む)
resource "snowflake_table_grant" "table_grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
privilege = "SELECT"
roles = [snowflake_role.role.name]
on_future = true
}
// ビューへの権限付与(今後作成されるものも含む)
resource "snowflake_view_grant" "view_grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
privilege = "SELECT"
roles = [snowflake_role.role.name]
on_future = true
}
// ステージ作成
resource "snowflake_stage" "stage" {
name = "TF_DEMO_STAGE"
database = snowflake_database.db.name
schema = snowflake_schema.schema.name
}
// ステージへの権限付与
resource "snowflake_stage_grant" "stage_grant" {
provider = snowflake.security_admin
database_name = snowflake_database.db.name
schema_name = snowflake_schema.schema.name
stage_name = snowflake_stage.stage.name
privilege = "READ"
roles = [snowflake_role.role.name]
depends_on = [snowflake_stage.stage]
}
// ユーザー作成
resource "snowflake_user" "user" {
provider = snowflake.security_admin
name = "TF_DEMO_USER"
password = "password"
default_role = ""
}
それぞれやっていることはコメントに書いてある通りです。
コード追加後、planで変更を確認し問題がなければapplyします。
$ terraform plan
$ terraform apply
Snowflake上で確認すると、TF_DEMO_ROLE
というロールが作成され、TF_DEMO_DB.TF_DEMO_SCHEMA
の操作権限を持っていることが分かります。
その後TF_DEMO_DB
に別のスキーマやテーブルを作成すると、ON_FUTURE
が効いていることによりTF_DEMO_ROLE
に権限が与えられることも確認できます。
他の作成したリソースに関しても意図した通りに作成されていると思います。
その他設定できるリソースやパラメータなどはTerraformのProviderページを参考にしてください。
まとめ
Terraformで基本的なリソースを作成する手順を紹介しました。
今回作成したコードは以下にアップしています。
実際に運用する際には、ファイル分割や状態ファイルの保管方法、リソースが増えた場合の処理の共通化など、まだまだ考慮する観点があります。
これらに関してはまた記事を書こうと思います。