Snowflake から Google Cloud への接続を Workload Identity Federation(OIDC)で実現する方法
Snowflake が OIDC プロバイダとして機能する新機能「Outbound WIF」を GA 化し、静的キーを使わずに外部サービス(Google Cloud など)への安全な接続を実現した。
キーポイント
Snowflake Outbound WIF の概要と目的
2026 年 7 月 1 日に GA された新機能で、Snowflake 内のワークロードが外部サービスに対して静的キー(シークレット)を保持・管理することなく、OIDC ベースの ID トークン発行により認証可能にする。
Inbound WIF との明確な違い
既存の Inbound WIF が「外部から Snowflake へアクセスする」ための機能であるのに対し、Outbound WIF は「Snowflake から外部(Google Cloud など)へアクセスする」ための逆方向の認証フローを担う。
トークン発行と検証の仕組み
DESC SECRET コマンドで識別子と発行者 URL を取得し、JWT 形式の ID トークンを発行。外部サービス側はこのトークンの aud クレームを検証することで、Snowflake からのアクセスを承認する。
Google Cloud 連携の実装フロー
Workload Identity プールとプロバイダの作成、サービスアカウントへのインパーソネーション権限付与、Snowflake でのトークン発行、STS を介した Token exchange、最終的なアクセストークンの取得という 5 ステップで接続を確立する。
Snowflake Outbound WIF の仕組みと利点
Snowflake が OIDC プロバイダとして動作し、外部サービス(Google Cloud)へ ID トークンを発行することで、シークレットキーを管理する必要なく安全に接続できる。
CLI と Snowpark での実装アプローチ
CLI では STS を介したトークン交換フローで直接アクセスし、Snowpark では google-auth ライブラリのカスタム SubjectTokenSupplier を実装して外部アクセス統合を可能にする。
運用上のセキュリティと監査特性
ID トークンの有効期限は 15 分に固定され、発行はプライマリアカウントのみ許可されるほか、すべてのトークン発行がクエリ履歴および監査ログで追跡可能である。
影響分析・編集コメントを表示
影響分析
この機能は、データウェアハウスから外部クラウドサービスへのアクセス制御において、従来の秘密鍵管理という脆弱性を排除し、ゼロトラストアーキテクチャの実現に寄与します。特に大規模なマルチクラウド環境や、機密データを扱うワークロードにおいて、認証情報の漏洩リスクを根本的に低減する画期的な進展です。
編集コメント
Snowflake が自社のワークロードを外部 OIDC プロバイダとして振る舞えるようになり、クラウド間の認証フローがさらに標準化・自動化される流れです。静的キーの不要化はセキュリティベストプラクティスへの大きな一歩と言えます。
こんにちは。バクラク事業部 BizOps データグループの @civitaspo です。2026 年 7 月 1 日、Snowflake の新機能 Workload identity federation for Snowflake workloads that access external services が GA(一般提供)になりました。一言でいうと「Snowflake 自身が OIDC プロバイダーとなり、Snowflake 内のワークロードが外部サービスに対して、静的キー不要で認証できる」機能です。機能名が長いので、本記事では「Snowflake Outbound WIF」と表記します。
本記事では、実際に Snowflake アカウントと Google Cloud プロジェクトを使って動作検証した内容をもとに、この機能の仕組みと使い方を解説します。なお、本記事に記載している SQL・gcloud・curl のコマンドはすべて実際に動作確認したものですが、アカウント名や Google Cloud プロジェクト ID などの識別子はダミーに置き換えているため、お手元で試す際はご自身の保有するアカウント等の識別子に変更してください。
- Snowflake Outbound WIF によって何が解決されるのか
- Snowflake Outbound WIF 機能とは
Snowflake Inbound WIF との違い
- Snowflake Outbound WIF で ID トークンを発行するまでの 3 ステップ
- Snowflake Outbound WIF Deep Dive
トークンフローの全体像
- DESC SECRET コマンドで得られる識別子と Issuer URL の構造
- 発行される JWT の Claim
- aud claim は外部サービス側のトークン検証で使われる
外部サービス側での検証
- Snowflake 側で制御できること
- Snowflake から Google Cloud へ Workload Identity Federation を使って接続する(CLI 編)
① Workload Identity プールとプロバイダの作成
- ② サービスアカウントへの Impersonation 権限付与
- ③ Snowflake で ID トークンを発行
- ④ STS で Token exchange
- ⑤ サービスアカウントのアクセストークンを取得
- Snowflake から Google Cloud へ Workload Identity Federation を使って接続する(Snowpark 編)
get_generic_secret_string では読めない
- google-auth のカスタム SubjectTokenSupplier
- External Access Integration の要件
- 運用上の注意
ID Tokenの有効期限は15分固定
- トークン発行はプライマリアカウントのみ
- issuer / subject は Trust Relationship 設定用の識別情報
- sf_rnm claim で外部サービス側の認証条件を最小化できる
- トークン発行はクエリ履歴と監査ログで追える
- まとめ
Snowflake Outbound WIF によって何が解決されるのか
Snowflake から外部サービス(BigQuery、GCS、各種 API など)にアクセスするワークロードを組むとき、これまで利用可能だった認証方法は「サービスアカウントキーなどの静的なクレデンシャルを Snowflake のシークレットに保存して使用する」方法でした。たとえば Google Cloud のサービスアカウントキー JSON を GENERIC_STRING 型のシークレットに入れ、ストアドプロシージャや外部関数から読み出す構成です。
この構成には以下のような問題があります。
- ローテーションの運用負荷: キーの有効期限管理と定期ローテーションを人間(または別の仕組み)が回し続ける必要がある
- 漏洩リスク: 静的キーはコピーできてしまう。Snowflake の外に持ち出されても本人性の検証ができない
- 監査の難しさ: キーがどこで使われたのかをキー自体からは追えない
クラウド間の認証ではこの問題を解決する手法として Workload Identity Federation(WIF)が普及してきました。GitHub Actions から Google Cloud に OIDC で認証する構成や AWS/Google Cloud 間で OIDC 認証する構成などで使用される方法です。昨今では、静的な Credentials を Cloud Provider の認証で使用するケースの方が少ないのではないでしょうか。
今回の新機能は、このOIDC プロバイダ(トークン発行側)の役割を Snowflake 自身が担えるようにするものです。静的キーを一切保存せず、有効期限15分の短命トークンだけで外部サービスに認証できるようになります。
Snowflake Outbound WIF 機能 #とは
Snowflake Inbound WIF との違い
Snowflake には、2025年に一般提供(GA)された「Workload identity federation(Inbound)」という機能が既に存在します。これは AWS や Google Cloud 上の外部ワークロードから Snowflake に対して認証を行うための機能であり、Snowflake はトークンの検証側(Relying Party)として機能します。
今回紹介する Snowflake Outbound WIF はその逆方向の機能です。Snowflake 内のワークロードが外部サービスに認証を行う「Workload identity federation(Outbound)」であり、Snowflake がトークンの発行側(OIDC プロバイダ)となります。
Snowflake Inbound WIF (2025 GA)
Snowflake Outbound WIF (2026-07-01 GA)
方向:外部 → Snowflake / Snowflake → 外部
Snowflake の役割:トークン検証側 (Relying Party) / トークン発行側 (OIDC Provider)
置き換わるもの:Snowflake ユーザーのパスワード/キーペア / 外部サービスの静的クレデンシャル
Snowflake Outbound WIF で ID Token を発行するまでの3ステップ
Snowflake Outbound WIF では、Snowflake が OIDC プロバイダとして Snowflake 上のワークロードに ID トークン(JWT)を発行し、外部サービスがそのトークンを検証してアクセスを許可します。
セットアップから実行時のトークン発行まで、流れは次の3ステップに分かれます。
- Snowflake 側でワークロードを登録する(シークレットの作成)
WORKLOAD_IDENTITY_FEDERATION 型のシークレットを作成します。シークレットを作成すると、Snowflake が ID トークンの発行元(OIDC プロバイダ)となり、そのワークロードがトークンを受け取る主体(OIDC クライアント)として登録されます。1 つのワークロードに対してシークレットは 1 つ(1:1)ですが、同じシークレットから複数の外部サービス向けにトークンを発行できます。
- 外部サービス側と信頼関係(Trust Relationship)を結ぶ(発行者 URL とサブジェクトの共有)
DESC SECRET コマンドで発行者 URL(workload_identity_federation_issuer)とサブジェクト(workload_identity_federation_subject)を取得し、認証先の外部サービス側に渡します。外部サービスは、受け取った ID トークンの iss / sub クレームがこの値と一致するかによって、「Snowflake が発行したトークンか」を判断します。
- 認証時に ID トークンを発行する(システム関数の呼び出し)
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールド (technical_terms 等) は一切追加しないこと — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:
{"translation": "Snowflake には、2025年に一般提供(GA)された「Workload identity federation(Inbound)」という機能が既に存在します。これは AWS や Google Cloud 上の外部ワークロードから Snowflake に対して認証を行うための機能であり、Snowflake はトークンの検証側(Relying Party)として機能します。
今回紹介する Snowflake Outbound WIF はその逆方向の機能です。Snowflake 内のワークロードが外部サービスに認証を行う「Workload identity federation(Outbound)」であり、Snowflake がトークンの発行側(OIDC プロバイダ)となります。
Snowflake Inbound WIF (2025 GA)
Snowflake Outbound WIF (2026-07-01 GA)
方向:外部 → Snowflake / Snowflake → 外部
Snowflake の役割:トークン検証側 (Relying Party) / トークン発行側 (OIDC Provider)
置き換わるもの:Snowflake ユーザーのパスワード/キーペア / 外部サービスの静的クレデンシャル
Snowflake Outbound WIF で ID Token を発行するまでの3ステップ
Snowflake Outbound WIF では、Snowflake が OIDC プロバイダとして Snowflake 上のワークロードに ID トークン(JWT)を発行し、外部サービスがそのトークンを検証してアクセスを許可します。
セットアップから実行時のトークン発行まで、流れは次の3ステップに分かれます。
- Snowflake 側でワークロードを登録する(シークレットの作成)
WORKLOAD_IDENTITY_FEDERATION 型のシークレットを作成します。シークレットを作成すると、Snowflake が ID トークンの発行元(OIDC プロバイダ)となり、そのワークロードがトークンを受け取る主体(OIDC クライアント)として登録されます。1 つのワークロードに対してシークレットは 1 つ(1:1)ですが、同じシークレットから複数の外部サービス向けにトークンを発行できます。
- 外部サービス側と信頼関係(Trust Relationship)を結ぶ(発行者 URL とサブジェクトの共有)
DESC SECRET コマンドで発行者 URL(workload_identity_federation_issuer)とサブジェクト(workload_identity_federation_subject)を取得し、認証先の外部サービス側に渡します。外部サービスは、受け取った ID トークンの iss / sub クレームがこの値と一致するかによって、「Snowflake が発行したトークンか」を判断します。
- 認証時に ID トークンを発行する(システム関数の呼び出し)"}
ワークロードが外部サービスへアクセスするたびに、SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN を呼び出して短命の ID トークンを取得します。送信先の外部サービスは、トークン発行時の aud クレームで指定します。
シークレットの作成は型指定だけです。
CREATE SECRET my_db.auth.my_workload
TYPE = WORKLOAD_IDENTITY_FEDERATION;
このシークレットには API キーのような「保存された認証情報」は入りません。発行者 URL(issuer URL)とサブジェクトなど、Snowflake Outbound WIF に必要な登録情報がシークレットの属性として記録され、以降のトークン発行と外部サービス側の検証に使われます。
Snowflake Outbound WIF Deep Dive
トークンフローの全体像
Google Cloud を外部サービスとした場合のフローは次のようになります。
- Google Cloud API (BigQuery / GCS など)
- Google Cloud IAM Credentials (iamcredentials.googleapis.com)
- Google Cloud STS (sts.googleapis.com)
- Snowflake (OIDC プロバイダ)
- Snowflake ワークロード (プロシージャ等)
- issuer の jwks_uri から公開鍵を取得し署名・iss・sub・aud を検証
- SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(secret, aud) を呼び出し ID Token (RS256 JWT、有効期限15分) を取得
- トークン交換 (subjectToken = ID Token) を行い federated access token を取得
- generateAccessToken (Service Account Impersonation) を実行し Service Account Access Token (1時間) を生成
- Authorization: Bearer <Service Account Access Token> を使用
DESC SECRET で得られる identifier と issuer URL の構造
シークレットを作成したら DESC SECRET を実行します。
DESC SECRET my_db.auth.my_workload;
出力(16 カラム)のうち重要なのは次の 2 つです。
workload_identity_federation_issuer
例: https://identity.snowflake.com/oauth2/31303030/39393939/58593132333435
- ID Token の iss クレームになります。認証先の外部サービス側との Trust Relationship 設定で使います。
- workload_identity_federation_subject
例:identity_0123abcd...(identity + 64桁の 16 進数)
- ID トークンの sub Claim になります。認証先の外部サービス側との Trust Relationship 設定で利用します。
issuer URL をよく見ると、パスセグメントが 16 進エンコードされた ASCII 文字列になっていることに気づきます。試しにデコードしてみると…
$ echo 31303030 | xxd -r -p
1000
$ echo 58593132333435 | xxd -r -p
XY12345
最後のセグメントはアカウントロケータ(この例では XY12345)のエンコードでした。そのため、issuer URL はアカウントごとに一意になっています。また、この issuer URL は標準的な OIDC Discovery に対応しており、<issuer>/.well-known/openid-configuration を GET すると jwks_uri を含むメタデータが返ってきます。外部サービス(Google Cloud STS など)はこの jwks_uri から公開鍵を取得して JWT の署名を検証します。特別なプロトコルは何もなく、素直な OIDC 実装です。
発行される JWT の Claim
トークン発行はシステム関数を呼ぶだけです。aud は JSON 形式で指定します。
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "https://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider"}'
);
返ってくるのは RS256 署名の JWT です。デコードすると次の Claim が確認できました。
Claim | 内容
---|---
iss | シークレットの issuer URL
sub | シークレットの subject (identity_...)
aud | 関数呼び出し時に指定した値がそのまま入る
iat / nbf / exp | 発行時刻・有効開始・有効期限。exp - iat は 900 秒(15 分)
jti | トークン毎に一意な ID
sf_onm | Snowflake の組織名(例:MYORG)
sf_anm | アカウント名(例:MYACCOUNT)
sf_rnm | この関数を呼び出したロール名
sf_aid / sf_oid | アカウント/組織の不透明な内部 ID
注目すべきは Snowflake 独自の sf_* Claim、特に sf_rnm です。トークンを発行した Snowflake ロールの名前が Claim として埋め込まれるため、受け取り側(Google Cloud など)で「特定のロールから発行されたトークンだけを Trust する」という属性条件を組めます。そのため、subject 単位より細かいアクセス制御が可能となります。
aud クレームは外部サービス側のトークン検証で使用される
SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN 関数の第2引数で指定する aud は、発行される ID トークンの audience クレームとなります。1 つの Secret から複数の外部サービス向けにトークンを発行する場合、送信先ごとに aud を変更します。
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "example-cloud-service.com"}');
Snowflake は、指定された aud をトークンに埋め込むだけです。値が外部サービス側で登録済みかどうかは確認しません。
外部サービス側での検証
外部サービスはトークンを受け取ったとき、iss や sub とあわせて aud も検証します。Google Cloud Workload Identity プールプロバイダでは、登録した audience と一致しない aud のトークンを Security Token Service(STS)に送ると、次のエラーで拒否されました。
invalid_grant: The audience in ID Token [...] does not match the expected audience
aud の検証は外部サービス側の設定次第です。プロバイダに audience を登録しておけば、想定外の aud のトークンはここで弾かれます。
Snowflake 側で制御できること
Snowflake 側で制御できるのは、トークンを発行できる主体の限定です。Secret の OWNERSHIP 権限 もしくは USAGE 権限によって、誰が SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN を呼び出せるかを決定します。
iss / sub / aud が正しいかどうかの判断は、外部サービス側のトークン検証に委ねられています。aud はその検証で使われるクレームの一つで、Snowflake 側で audience を絞り込む仕組みはありません。audience の制限が必要な場合は、外部サービス側のプロバイダ設定(issuer・subject・audience・属性条件など)で行います。
ここからは CLI を使って「Snowflake が発行した ID トークンを使用して、Google Cloud の Service Account へ Impersonation し、アクセストークンを取得する」方法を理解します。
前提として、Google Cloud プロジェクト my-google-cloud-project(プロジェクト番号 000000000000)、Snowflake 側は前述のシークレット my_db.auth.my_workload が作成済みで、DESC SECRET の issuer / subject を取得できている、とします。
① Workload Identity プールとプロバイダの作成
gcloud iam workload-identity-pools create snowflake-pool \
--project=my-google-cloud-project \
--location=global
gcloud iam workload-identity-pools providers create-oidc snowflake-provider \
--project=my-google-cloud-project \
--location=global \
--workload-identity-pool=snowflake-pool \
--issuer-uri="https://identity.snowflake.com/oauth2/31303030/39393939/58593132333435" \
--attribute-mapping="google.subject=assertion.sub" \
--attribute-condition="assertion.sub == 'identity_0123abcd...'"
--issuer-uri と --attribute-condition の subject には、DESC SECRET で得た値をそのまま使います。—-attribute-condition で subject を固定しておくことで、同じ Snowflake アカウントの別シークレット(別ワークロード)からのトークンを弾けます。また sf_rnm を使用することで、別のロールからのアクセスも弾くことができます。
② サービスアカウントへのImpersonation権限付与
gcloud iam service-accounts add-iam-policy-binding \
my-sa@my-google-cloud-project.iam.gserviceaccount.com \
--project=my-google-cloud-project \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/subject/identity_0123abcd..."
DESC SECRET で取得した subject を使用して、サービスアカウント my-sa@my-google-cloud-project.iam.gserviceaccount.com に対する Impersonation(なりすまし)を許可します。
③ Snowflake で ID トークンを発行
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールド (technical_terms 等) は一切追加しないこと — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:
{"translation": "前提として、Google Cloud プロジェクト my-google-cloud-project(プロジェクト番号 000000000000)、Snowflake 側は前述のシークレット my_db.auth.my_workload が作成済みで、DESC SECRET の issuer / subject を取得できている、とします。
① Workload Identity プールとプロバイダの作成
gcloud iam workload-identity-pools create snowflake-pool \
--project=my-google-cloud-project \
--location=global
gcloud iam workload-identity-pools providers create-oidc snowflake-provider \
--project=my-google-cloud-project \
--location=global \
--workload-identity-pool=snowflake-pool \
--issuer-uri="https://identity.snowflake.com/oauth2/31303030/39393939/58593132333435" \
--attribute-mapping="google.subject=assertion.sub" \
--attribute-condition="assertion.sub == 'identity_0123abcd...'"
--issuer-uri と --attribute-condition の subject には、DESC SECRET で得た値をそのまま使います。—-attribute-condition で subject を固定しておくことで、同じ Snowflake アカウントの別シークレット(別ワークロード)からのトークンを弾けます。また sf_rnm を使用することで、別のロールからのアクセスも弾くことができます。
② サービスアカウントへの Impersonation 権限付与
gcloud iam service-accounts add-iam-policy-binding \
my-sa@my-google-cloud-project.iam.gserviceaccount.com \
--project=my-google-cloud-project \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/subject/identity_0123abcd..."
DESC SECRET で取得した subject を使用して、サービスアカウント my-sa@my-google-cloud-project.iam.gserviceaccount.com に対する Impersonation(なりすまし)を許可します。
③ Snowflake で ID トークンを発行"}
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "https://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider"}'
);
先ほど説明したとおり、ここで指定する aud claim はアクセス先の外部サービスによって検証されます。Google Cloud の Workload Identity Pool Provider の場合は allowedAudiences というパラメータに指定された値に応じて検証します。
本記事の構成では allowedAudiences を未設定にしているため、JWT の aud は provider の canonical resource name と一致させる必要があります。以下のどちらでも構いません。
- https://iam.googleapis.com/projects/.../providers/...
- //iam.googleapis.com/projects/.../providers/...
慣習的には、手順④の STS リクエストで使う provider 名と同じ文字列を aud に入れることが多いですが、JWT の aud と STS の audience は別フィールドです。手順4の audience は「どの provider に token exchange するか」を指定するもので、JWT の aud の検証条件とは無関係です。値が似ているため混同しやすいので、手順③ではあくまで Google Cloud の OIDC provider 設定に従って aud を決めてください。
④ STS で Token exchange
curl -s https://sts.googleapis.com/v1/token \
-H "Content-Type: application/json" \
-d '{
"grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
"audience": "//iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
"subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
"subjectToken": "<手順3で得たIDトークン>"
}'
audience には、トークン交換の宛先となる Workload Identity Pool Provider の完全なリソース名を指定します。
形式は //iam.googleapis.com/projects/.../providers/... です。これは手順③で JWT に含めた aud(認可対象)とは異なるフィールドであり、値を揃える必要はありません。subjectToken に含まれる JWT の aud は、手順2で設定した provider の allowedAudiences に従って別途検証されます。
成功すると、連合アクセストークンが返されます。レスポンスの expires_in は、発行されたアクセストークンの有効秒数です。トークン交換では、出力トークンの有効期限が入力トークンの期限の影響を受ける場合があります1。今回の検証では、JWT 発行から STS 交換まで数十秒経過した時点で、約831秒が返されました。
⑤ サービスアカウントのアクセストークンを取得
<path d="M318-120q-82 0-140-58t-58-140q0-40 15-76t43-64l134-133 56 56-134 134q-17 17-25.5 38.5T200-318q0 49 34.5 83.5T318-200q23 0 45-8.5t39-25.5l133-134 57 57-134 133q-28 28-64 43t-76 15Zm79-220-57-57 223-223 57 57-223 223Zm251-28-56-57 134-133q17-17 25-38t8-44q0-50-34-85t-84-35q-23 0-44.5 8.5T558-726L425-5
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールド (technical_terms 等) は一切追加しないこと — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:
{"translation": "翻訳全文"}
原文を表示
こんにちは。バクラク事業部 BizOps部 データグループの@civitaspoです。2026年7月1日、Snowflake の新機能 Workload identity federation for Snowflake workloads that access external services が GA になりました。一言でいうと「Snowflake 自身が OIDC Providerとなり、Snowflake 内のワークロードが外部サービスに対して、静的キー不要で認証できる」機能です。機能名が長いので、本記事では「Snowflake Outbound WIF」と表記します。
本記事では、実際に Snowflake アカウントと Google Cloud プロジェクトを使って動作検証した内容をもとに、この機能の仕組みと使い方を解説します。なお、本記事に記載している SQL・gcloud・curl のコマンドはすべて実際に動作確認したものですが、アカウント名や Google Cloud プロジェクト ID などの識別子はダミーに置き換えているため、お手元で試す際はご自身の保有するアカウント等の識別子に変更してください。
- Snowflake Outbound WIF によって何が解決されるのか
- Snowflake Outbound WIF 機能 #とは
Snowflake Inbound WIF との違い
- Snowflake Outbound WIF で ID Token を発行するまでの3ステップ
- Snowflake Outbound WIF Deep Dive
トークンフローの全体像
- DESC SECRET で得られる identifer と issuer URL の構造
- 発行される JWT の Claim
- aud claim は外部サービス側の token 検証で使われる
外部サービス側での検証
- Snowflake 側で制御できること
- Snowflake から Google Cloud へ Workload Identity Federation を使って接続する(CLI編)
① Workload Identity プールとプロバイダの作成
- ② サービスアカウントへのImpersonation権限付与
- ③ Snowflake で ID トークンを発行
- ④ STS で Token exchange
- ⑤ サービスアカウントのアクセストークンを取得
- Snowflake から Google Cloud へ Workload Identity Federation を使って接続する(Snowpark編)
get_generic_secret_string では読めない
- google-auth のカスタム SubjectTokenSupplier
- External Access Integration の要件
- 運用上の注意
ID Tokenの有効期限は15分固定
- トークン発行はプライマリアカウントのみ
- issuer / subject は Trust Relationship 設定用の識別情報
- sf_rnm claim で外部サービス側の認証条件を最小化できる
- トークン発行はクエリ履歴と監査ログで追える
- まとめ
Snowflake Outbound WIF によって何が解決されるのか
Snowflake から外部サービス(BigQuery、GCS、各種 API など)にアクセスするワークロードを組むとき、これまで利用可能だった認証方法は「サービスアカウントキーなどの静的なクレデンシャルを Snowflake のシークレットに保存して使用する」方法でした。たとえば Google Cloud のサービスアカウントキー JSON を GENERIC_STRING 型のシークレットに入れ、ストアドプロシージャや外部関数から読み出す構成です。
この構成には以下のような問題があります。
- ローテーションの運用負荷: キーの有効期限管理と定期ローテーションを人間(または別の仕組み)が回し続ける必要がある
- 漏洩リスク: 静的キーはコピーできてしまう。Snowflake の外に持ち出されても本人性の検証ができない
- 監査の難しさ: キーがどこで使われたのかをキー自体からは追えない
クラウド間の認証ではこの問題を解決する手法として Workload Identity Federation(WIF)が普及してきました。GitHub Actions から Google Cloud に OIDC で認証する構成や AWS/Google Cloud 間で OIDC 認証する構成などで使用される方法です。昨今では、静的な Credentials を Cloud Provider の認証で使用するケースの方が少ないのではないでしょうか。
今回の新機能は、このOIDC プロバイダ(トークン発行側)の役割を Snowflake 自身が担えるようにするものです。静的キーを一切保存せず、有効期限15分の短命トークンだけで外部サービスに認証できるようになります。
Snowflake Outbound WIF 機能 #とは
Snowflake Inbound WIF との違い
Snowflake には2025年に GA した「Workload identity federation(Inbound)」がすでにあります。これは AWS や Google Cloud 上の外部ワークロードから Snowflake に対して認証するための機能で、Snowflake はトークンの検証側でした。
今回紹介する Snowflake Outbound WIF は逆方向です。Snowflake 内のワークロードが外部サービスに認証する、「Workload identity federation(Outbound)」 であり、Snowflake がトークンの発行側(OIDC プロバイダ)になります。
Snowflake Inbound WIF (2025 GA)
Snowflake Outbound WIF (2026-07-01 GA)
方向
外部 → Snowflake
Snowflake → 外部
Snowflake の役割
トークン検証側 (Relying Party)
トークン発行側 (OIDC Provider)
置き換わるもの
Snowflake ユーザーのパスワード/キーペア
外部サービスの静的クレデンシャル
Snowflake Outbound WIF で ID Token を発行するまでの3ステップ
Snowflake Outbound WIF では、Snowflake が OIDC Provider として Snowflake 上の workload に ID Token(JWT) を発行し、外部サービスがその token を検証してアクセスを許可します。
セットアップから実行時の Token 発行まで、流れは次の3ステップに分かれます。
- Snowflake 側で workload を登録する(Secret の作成)
WORKLOAD_IDENTITY_FEDERATION 型の Secret を作成します。Secret を作ると、Snowflake が ID token の発行元(OIDC Provider)になり、その workload が token を受け取る主体(OIDC client)として登録されます。1 つの workload に対して Secret は 1 つ(1:1)ですが、同じ Secret から複数の外部サービス向けに token を発行できます。
- 外部サービス側と Trust Relationship を結ぶ(issuer URL と subject の共有)
DESC SECRET で issuer URL(workload_identity_federation_issuer)と subject(workload_identity_federation_subject)を取得し、認証先の外部サービス側に渡します。外部サービスは、受け取った ID token の iss / sub claim がこの値と一致するかで、「Snowflake が発行した token か」を判断します。
- 認証時に ID token を発行する(システム関数の呼び出し)
workload が外部サービスへアクセスするたびに、SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN を呼び出して短命の ID token を取得します。送信先の外部サービスは、token 発行時の aud claim で指定します。
Secret の作成は型指定だけです。
CREATE SECRET my_db.auth.my_workload
TYPE = WORKLOAD_IDENTITY_FEDERATION;
この Secret には API キーのような「保存された認証情報」は入りません。issuer URL と subject など、Snowflake Outbound WIF に必要な登録情報が Secret の属性として記録され、以降の token 発行と外部サービス側の検証に使われます。
Snowflake Outbound WIF Deep Dive
トークンフローの全体像
Google Cloud を外部サービスとした場合のフローは次のようになります。
Google Cloud API(BigQuery / GCSなど)Google Cloud IAM Credentials(iamcredentials.googleapis.com)Google Cloud STS(sts.googleapis.com)Snowflake(OIDCプロバイダ)Snowflakeワークロード(プロシージャ等)Google Cloud API(BigQuery / GCSなど)Google Cloud IAM Credentials(iamcredentials.googleapis.com)Google Cloud STS(sts.googleapis.com)Snowflake(OIDCプロバイダ)Snowflakeワークロード(プロシージャ等)issuer の jwks_uri から公開鍵を取得し署名・iss・sub・aud を検証SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(secret, aud)ID Token (RS256 JWT, 有効期限15分)token-exchange (subjectToken = ID Token)federated access tokengenerateAccessToken (Service Account Impersonation)Service Account Access Token (1時間)Authorization: Bearer <Service Account Access Token>DESC SECRET で得られる identifer と issuer URL の構造
シークレットを作成したら DESC SECRET を実行します。
DESC SECRET my_db.auth.my_workload;
出力(16カラム)のうち重要なのは次の2つです。
- workload_identity_federation_issuer
例: https://identity.snowflake.com/oauth2/31303030/39393939/58593132333435
- ID Token の iss Claim になる。認証先の外部サービス側との Trust Relationship 設定で使う。
- workload_identity_federation_subject
例: identity_0123abcd...(identity_ + 64桁の16進数)
- ID Token の sub Claim になる。認証先の外部サービス側との Trust Relationship 設定で使う。
issuer URL をよく見ると、パスセグメントが 16 進エンコードされた ASCII 文字列になっていることに気づきます。試しにデコードしてみると…
$ echo 31303030 | xxd -r -p
1000
$ echo 58593132333435 | xxd -r -p
XY12345最後のセグメントはアカウントロケータ(この例では XY12345)のエンコードでした。そのため、issuer URL はアカウントごとに一意になっています。また、この issuer URL は標準的な OIDC Discovery に対応しており、<issuer>/.well-known/openid-configuration を GET すると jwks_uri を含むメタデータが返ってきます。外部サービス(Google Cloud STS など)はこの jwks_uri から公開鍵を取得して JWT の署名を検証します。特別なプロトコルは何もなく、素直な OIDC 実装です。
発行される JWT の Claim
トークン発行はシステム関数を呼ぶだけです。aud は JSON 形式で指定します。
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "https://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider"}'
);
返ってくるのは RS256 署名の JWT です。デコードすると次の Claim が確認できました。
Claim
内容
iss
シークレットの issuer URL
sub
シークレットの subject (identity_...)
aud
関数呼び出し時に指定した値がそのまま入る
iat / nbf / exp
発行時刻・有効開始・有効期限。exp - iat は900秒(15分)
jti
トークン毎に一意な ID
sf_onm
Snowflake の組織名(例: MYORG)
sf_anm
アカウント名(例: MYACCOUNT)
sf_rnm
この関数を呼び出したロール名
sf_aid / sf_oid
アカウント/組織の不透明な内部 ID
注目すべきは Snowflake 独自の sf_* Claim、特に sf_rnm です。トークンを発行した Snowflake ロールの名前が Claim として埋め込まれるため、受け取り側(Google Cloud など)で「特定のロールから発行されたトークンだけを Trust する」という属性条件を組めます。そのため、subject 単位より細かいアクセス制御が可能となります。
aud claim は外部サービス側の token 検証で使われる
SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN の第2引数で指定する aud は、発行される ID token の audience claim になります。1 つの Secret から複数の外部サービス向けに token を発行する場合、送信先ごとに aud を変えます。
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "example-cloud-service.com"}');
Snowflake は、指定された aud を token に埋め込むだけです。値が外部サービス側で登録済みかどうかは確認しません。
外部サービス側での検証
外部サービスは token を受け取ったとき、iss や sub とあわせて aud も検証します。Google Cloud Workload Identity プールプロバイダでは、登録した audience と一致しない aud の token を Security Token Service(STS)に送ると、次のエラーで拒否されました。
invalid_grant: The audience in ID Token [...] does not match the expected audienceaud の検証は外部サービス側の設定次第です。プロバイダに audience を登録しておけば、想定外の aud の token はここで弾かれます。
Snowflake 側で制御できること
Snowflake 側で制御できるのは、token を発行できる主体の限定です。Secret の OWNERSHIP 権限 もしくは USAGE 権限によって、誰が SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN を呼び出せるかを決定します。
iss / sub / aud が正しいかどうかの判断は、外部サービス側の token 検証に委ねられています。aud はその検証で使われる claim の一つで、Snowflake 側で audience を絞り込む仕組みはありません。audience の制限が必要な場合は、外部サービス側のプロバイダ設定(issuer・subject・audience・属性条件など)で行います。
ここからは CLI を使って「Snowflake が発行した ID Token を使用して、Google Cloud の Service Account へ Impersonation し、アクセストークンを取得する」方法を理解します。
前提として、Google Cloud プロジェクト my-google-cloud-project(プロジェクト番号 000000000000)、Snowflake 側は前述のシークレット my_db.auth.my_workload が作成済みで、DESC SECRET の issuer / subject を取得できている、とします。
① Workload Identity プールとプロバイダの作成
gcloud iam workload-identity-pools create snowflake-pool \
--project=my-google-cloud-project \
--location=global
gcloud iam workload-identity-pools providers create-oidc snowflake-provider \
--project=my-google-cloud-project \
--location=global \
--workload-identity-pool=snowflake-pool \
--issuer-uri="https://identity.snowflake.com/oauth2/31303030/39393939/58593132333435" \
--attribute-mapping="google.subject=assertion.sub" \
--attribute-condition="assertion.sub == 'identity_0123abcd...'"--issuer-uri と --attribute-condition の subject には、DESC SECRET で得た値をそのまま使います。 —-attribute-condition で subject を固定しておくことで、同じ Snowflake アカウントの別シークレット(別ワークロード)からのトークンを弾けます。また sf_rnm を使用することで、別のロールからのアクセスも弾くことができます。
② サービスアカウントへのImpersonation権限付与
gcloud iam service-accounts add-iam-policy-binding \
my-sa@my-google-cloud-project.iam.gserviceaccount.com \
--project=my-google-cloud-project \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/subject/identity_0123abcd..."DESC SECRET で取得した subject を使用して、サービスアカウント my-sa@my-google-cloud-project.iam.gserviceaccount.com に対する Impersonation を許可します。
③ Snowflake で ID トークンを発行
SELECT SYSTEM$ISSUE_WORKLOAD_IDENTITY_FEDERATION_TOKEN(
'my_db.auth.my_workload',
'{"aud": "https://iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider"}'
);
先ほど説明したとおり、ここで指定する aud claim はアクセス先の外部サービスによって検証されます。Google Cloud の Workload Identity Pool Provider の場合は allowedAudiences というパラメータに指定された値に応じて検証します。
本記事の構成では allowedAudiences を未設定にしているため、JWT の aud は provider の canonical resource name と一致させる必要があります。以下のどちらでも構いません。
- https://iam.googleapis.com/projects/.../providers/...
- //iam.googleapis.com/projects/.../providers/...
慣習的には、手順④の STS リクエストで使う provider 名と同じ文字列を aud に入れることが多いですが、JWT の aud と STS の audience は別フィールドです。手順4の audience は「どの provider に token exchange するか」を指定するもので、JWT の aud の検証条件とは無関係です。値が似ているため混同しやすいので、手順③ではあくまで Google Cloud の OIDC provider 設定に従って aud を決めてください。
④ STS で Token exchange
curl -s https://sts.googleapis.com/v1/token \
-H "Content-Type: application/json" \
-d '{
"grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
"audience": "//iam.googleapis.com/projects/000000000000/locations/global/workloadIdentityPools/snowflake-pool/providers/snowflake-provider",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
"subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
"subjectToken": "<手順3で得たIDトークン>"
}'audience には、token exchange の宛先となる Workload Identity Pool Provider の full resource name を指定します。
形式は //iam.googleapis.com/projects/.../providers/... です。これは手順③で JWT に入れた aud とは別のフィールドで、値を揃える必要はありません。subjectToken に含まれる JWT の aud は、手順2で設定した provider の allowedAudiences に従って別途検証されます。
成功すると federated access token が返ります。レスポンスの expires_in は、発行された access token の有効秒数です。Token exchange では、出力トークンの有効期限が入力トークンの期限の影響を受ける場合があります1。今回の検証では、JWT 発行から STS 交換まで数十秒経過した時点で、約831秒が返りました。
⑤ サービスアカウントのアクセストークンを取得
<path d="M318-120q-82 0-140-58t-58-140q0-40 15-76t43-64l134-133 56 56-134 134q-17 17-25.5 38.5T200-318q0 49 34.5 83.5T318-200q23 0 45-8.5t39-25.5l133-134 57 57-134 133q-28 28-64 43t-76 15Zm79-220-57-57 223-223 57 57-223 223Zm251-28-56-57 134-133q17-17 25-38t8-44q0-50-34-85t-84-35q-23 0-44.5 8.5T558-726L425-5
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み