以下の内容はhttps://christina04.hatenablog.com/entry/snowflake-wif-with-google-cloudより取得しました。


Google Cloud → Snowflake の Workload Identity Federation を構築する

概要

Google Cloud上でAtlantisというterraformのGitOpsツールを導入している状態で、Snowflakeもterraform管理したいと考えました。

タイミング良く Snowflake Provider で v2.10.0 からWorkload Identity Federation が正式サポートされたので、これを使って実現します。

環境

  • Terraform v1.13.4
  • snowflakedb/snowflake provider v2.11.0
  • hashicorp/google provider v7.9

コンポーネント図

準備

前提として

  • Google Cloud上でAtlantis環境が整っている
  • Atlantisの実行用サービスアカウントがIAMにある

とします。

Google Cloud

Snowflakeとの連携で必要になるため、サービスアカウントのメールアドレスからIDを確認しておきます。

gcloud iam service-accounts describe "<GSA_EMAIL>" --format="value(uniqueId)"

21 桁の数字のIDが出てくるので、それを使います。

Snowflake

Terraform用ロール作成

まずは専用のロールを作成します。

-- 1. Terraform用ロールを作成
USE ROLE ACCOUNTADMIN;

CREATE ROLE IF NOT EXISTS TERRAFORM_ADMIN_ROLE
  COMMENT = 'Role for Terraform automation (aggregates required privileges)';

-- SYSADMIN: Database/Warehouse/Stage作成
-- ACCOUNTADMIN: Storage Integration作成
-- SECURITYADMIN: Grant操作
GRANT ROLE SYSADMIN     TO ROLE TERRAFORM_ADMIN_ROLE;
GRANT ROLE ACCOUNTADMIN TO ROLE TERRAFORM_ADMIN_ROLE;
GRANT ROLE SECURITYADMIN TO ROLE TERRAFORM_ADMIN_ROLE;

非常に大きな権限を付与しますが、Terraformというインフラ環境構築ツールの用途上権限が不足しているとUXが下がりますし、今回はWorkload Identity Federationによって鍵が不要でセキュリティも担保できるのでこうしています。

Terraform用ユーザ作成

次にユーザを作成します。
先ほどのGoogleCloudのサービスアカウントIDを使います。

-- 2. Terraform用ユーザを作成
USE ROLE SECURITYADMIN;

CREATE USER IF NOT EXISTS TERRAFORM_SVC
    TYPE = SERVICE
    WORKLOAD_IDENTITY = (
      TYPE = GCP
      SUBJECT = '<SERVICE_ACCOUNT_ID>'
    )
    COMMENT = 'Terraform automation service account with Workload Identity Federation';

先ほど作ったロールを付与します。

GRANT ROLE TERRAFORM_ADMIN_ROLE TO USER TERRAFORM_SVC;

専用ウェアハウスの作成

-- 3. Terraform用ウェアハウスを作成
USE ROLE SYSADMIN;

CREATE WAREHOUSE IF NOT EXISTS TERRAFORM_SVC_WH
    WAREHOUSE_SIZE = XSMALL
    AUTO_RESUME = TRUE
    AUTO_SUSPEND = 60
    INITIALLY_SUSPENDED = TRUE
    STATEMENT_TIMEOUT_IN_SECONDS = 300
    COMMENT = 'For terraform automation only';

権限を専用ロールに付与します。

USE ROLE SECURITYADMIN;
GRANT USAGE ON WAREHOUSE TERRAFORM_SVC_WH TO ROLE TERRAFORM_ADMIN_ROLE;

デフォルトロール・デフォルトウェアハウスの設定

最後にデフォルト値の設定をしておきます。

ALTER USER TERRAFORM_SVC SET
  DEFAULT_ROLE = TERRAFORM_ADMIN_ROLE,
  DEFAULT_WAREHOUSE = TERRAFORM_SVC_WH;

Terraform

Snowflakeの設定が終わったら次はTerraformの書き方です。

versions.tf

Terraform, Providerのバージョン指定です。

terraform {
  required_providers {
    snowflake = {
      source  = "snowflakedb/snowflake"
      version = "~> 2.11.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 7.9"
    }
  }
  required_version = ">= 1.13.4"
}

注意としてsnowflake providerは2.10以降でないとWIF authenticatorをサポートしていません。

providers.tf

Providerの設定です。

provider "snowflake" {
  organization_name = var.snowflake_organization_name
  account_name      = var.snowflake_account_name
  user              = "TERRAFORM_SVC"

  authenticator              = "WORKLOAD_IDENTITY"
  workload_identity_provider = "GCP"
}

provider "google" {
  project = var.project_id
  region  = "asia-northeast1"
}

ポイント

  • userにSnowflakeで作ったユーザを指定
  • authenticatorWORKLOAD_IDENTITY
  • workload_identity_providerGCP

パラメータ上、ロールやウェアハウスを指定することもできますが、後述しますが逆に指定することでエラーになっていますので外しています。

動作確認

次のようなリソースを定義して、作成できることを確認します。

resource "snowflake_database" "tf_db" {
  name         = "TF_DEMO_DB"
  is_transient = false
}

resource "snowflake_warehouse" "tf_warehouse" {
  name                      = "TF_DEMO_WH"
  warehouse_type            = "STANDARD"
  warehouse_size            = "XSMALL"
  max_cluster_count         = 1
  min_cluster_count         = 1
  auto_suspend              = 60
  auto_resume               = true
  enable_query_acceleration = false
  initially_suspended       = true
}

トラブルシューティング

遭遇したエラーと対処方法をまとめます。

Error: open snowflake connection: 390101 (08004): User access disabled.

このエラーはSnowflake 側で対象ユーザーが「無効化 (DISABLED=TRUE)」状態になっています。

これは設定が不十分で認証に失敗していると、自動的に無効化されてしまうようです。なので再度有効化します。

USE ROLE ACCOUNTADMIN;
ALTER USER TERRAFORM_SVC SET DISABLED = FALSE;

Error: open snowflake connection: 390201 (08004): The requested warehouse does not exist or not authorized.

これは

  • ウェアハウスがない
  • 権限がない

のどちらかですが、様々な要因があります。

a. ロールに権限がない

権限を付与しましょう。

GRANT USAGE ON WAREHOUSE TERRAFORM_SVC_WH TO ROLE TERRAFORM_ADMIN_ROLE;

b. ロールに権限があるが、ユーザがそのロールやウェアハウスを使おうとしていない

Snowflakeユーザは、ロールやウェアハウスの指定をUSEで設定する方法と、デフォルト設定する方法の2つがあります。

今回のWorkload Identity Federationのように、裏で自動で処理する場合はUSEで指定できないのでデフォルト値の設定をしておくのが良いです。

USE ROLE SECURITYADMIN;
ALTER USER TERRAFORM_SVC SET
  DEFAULT_ROLE = TERRAFORM_ADMIN_ROLE,
  DEFAULT_WAREHOUSE = TERRAFORM_SVC_WH;

c. providerで指定するロール・ウェアハウスが悪影響

一番ハマったのですが、「↑のようにデフォルト値の設定をしていなくてもproviderでrole・warehouseを指定していれば大丈夫だろう」と考えていました。

provider "snowflake" {
  organization_name = var.snowflake_organization_name
  account_name      = var.snowflake_account_name
  user                       = "TERRAFORM_SVC"

  authenticator              = "WORKLOAD_IDENTITY"
  workload_identity_provider = "GCP"

  role      = "TERRAFORM_ADMIN_ROLE"
  warehouse = "TERRAFORM_SVC_WH"
}

しかしながらこのように指定した状態ではうまくいかず、またデフォルト値を設定したとしても通りませんでした。

Snowflakeユーザ
デフォルト設定あり
Snowflakeユーザ
デフォルト設定なし
provider指定あり エラー エラー
provider指定なし 成功 エラー

おそらくではありますが、provider 側で role / warehouse を明示したときの初期化の順序(またはログイン時パラメータの扱い)が、WIF と相性悪くてコケているのかもしれません。

まとめ

Google CloudのIAMをIdPとして、SnowflakeのTerraformの認証を Workload Identity Federation で実現しました。

参考




以上の内容はhttps://christina04.hatenablog.com/entry/snowflake-wif-with-google-cloudより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14