この記事は NewsPicks Advent Calendar 2025 の17日目の記事です。
こんにちは。 ソーシャル経済メディア「NewsPicks」のQA/SET チームで開発をしている海老澤です。
2025年8月にSnowflake に新しい認証方式 Workload Identity Federation が追加され、 OIDC(OpenID Connect) を利用して、パスワードや API キーといった長期的な認証情報を管理することなく Snowflake に接続できるようになりました。
この記事では GitHub Actions から Snowflake に OIDC 認証で接続する方法と、実際に詰まったポイントを整理します。
Snowflake × OIDC
OIDC / Workload Identity Federation とは
OIDC(OpenID Connect) は OAuth 2.0 を拡張した認証プロトコルで、
「誰が実行しているか」を 署名付きの ID トークン(JWT) で証明します。
GitHub Actions は、ジョブ実行時に以下の情報を含む ID トークンを発行できます。
- issuer(発行元)
- subject(どのリポジトリ・イベントか)
- audience(誰向けのトークンか)
Snowflake の Workload Identity Federation は、この ID トークンを検証することで、
パスワードや鍵を使わずに Snowflake への接続を可能にします。
なぜ OIDC / Workload Identity Federation を使うのか
長期的な認証情報を持たなくてよい
パスワードや秘密鍵を Secrets に保存する必要がありません。CI/CD と相性が良い
短命な実行環境でも、安全に認証できます。実行元を明示的に制限できる
リポジトリやイベント単位でアクセスを制御できます。Secret 管理・ローテーションが不要
運用コストと漏洩リスクを同時に下げられます。
Snowflake 側の設定
設計方針
- CI/CD 専用のユーザーを作成する
- パスワードや秘密鍵は持たせない
- OIDC トークンの内容でアクセスを制御する
Snowflake でのユーザー作成
以下のクエリで認証用のUSERを作成します。
CREATE USER SERVICE_GITHUB_ACTIONS SET WORKLOAD_IDENTITY = ( TYPE = OIDC ISSUER = 'https://token.actions.githubusercontent.com' SUBJECT = 'repo:{組織名}/{repository名}:pull_request' -- ※1 OIDC_AUDIENCE_LIST = ('https://github.com/{組織名}') );
※1 SUBJECT にワイルドカードを使ったところ下記エラーが発生しました。 repo:{組織名}/{repository名}:* のような指定は不可のようで 'repo:{組織名}/{repository名}:pull_request' や 'repo:{組織名}/{repository名}:ref:refs/heads/{ブランチ名}' のように指定しないとダメなようです。
Failed to authenticate the JWT with issuer
'https://token.actions.githubusercontent.com' and subject
'repo:{組織名}/{リポジトリ名}:pull_request'
GitHub Actions 側の設定
workflow.yml
- name: SQL from Github Actions env: SNOWFLAKE_AUDIENCE: "https://github.com/${{ github.repository_owner }}" --audience は Snowflake cli のオプションにない SF_ENABLE_EXPERIMENTAL_AUTHENTICATION: true run: | snow sql -f execute-query.sql \ --account ${{ vars.SNOWFLAKE_ACCOUNT }} \ --user ${{ vars.SNOWFLAKE_USER }} \ --authenticator WORKLOAD_IDENTITY \ --workload-identity-provider OIDC \ --database ${{ vars.SNOWFLAKE_DATABASE }} \ --schema ${{ vars.SNOWFLAKE_SCHEMA }} \ --warehouse ${{ vars.SNOWFLAKE_WAREHOUSE }} \ --role ${{ vars.SNOWFLAKE_ROLE }} \ --temporary-connection
- account: SNOWFLAKE ページの左下ユーザーアイコン > Account > Account identifier
- user: 認証用のユーザー 上記の例では SERVICE_GITHUB_ACTIONS
各種設定は vars 保存しています。
env: SNOWFLAKE_ACCOUNT: {アカウント名} SNOWFLAKE_USER: {ユーザー名} ...
環境変数を使って以下のように書くこともできます。
- name: SQL from Github Actions env: SNOWFLAKE_ACCOUNT: ${{ vars.SNOWFLAKE_ACCOUNT }} SNOWFLAKE_USER: ${{ vars.SNOWFLAKE_USER }} SNOWFLAKE_AUTHENTICATOR: WORKLOAD_IDENTITY SNOWFLAKE_WORKLOAD_IDENTITY_PROVIDER: OIDC SNOWFLAKE_AUDIENCE: "https://github.com/${{ github.repository_owner }}" SF_ENABLE_EXPERIMENTAL_AUTHENTICATION: true SNOWFLAKE_DATABASE: ${{ vars.SNOWFLAKE_DATABASE }} SNOWFLAKE_SCHEMA: ${{ vars.SNOWFLAKE_SCHEMA }} SNOWFLAKE_WAREHOUSE: ${{ vars.SNOWFLAKE_WAREHOUSE }} SNOWFLAKE_ROLE: ${{ vars.SNOWFLAKE_ROLE }} run: | snow sql -f execute-query.sql \ --temporary-connection
詰まったところ
Snowflake CLI で snow sql --temporary-connection を使う場合、 自分で取得した OIDC トークンは使われません。
たとえ GitHub Actions でaudience を指定して ID トークンを発行し --token や SNOWFLAKE_CONNECTIONS_OIDC_TOKEN で渡していても Snowflake CLI は内部で 別の ID トークンを自動取得 します。
このとき使われるトークンの audience はデフォルトで snowflakecomputing.com になります。
そのため、
- Snowflake 側の OIDC_AUDIENCE_LIST が https://github.com/... のみ
- Snowflake CLI が取得したトークンの aud が snowflakecomputing.com
という状態だと、audience 不一致で認証エラーになります。
対策
Snowflake CLI が取得する ID トークンの audience を合わせる必要があります。
つまり、 --temporary-connection では Snowflake CLI がトークンを自動取得し、 --token は無視されるため、audience は SNOWFLAKE_AUDIENCE で制御する
OIDC 自体ではなく、Snowflake CLI の自動認証挙動が原因なので、 ここを理解していないと非常にハマりやすいポイントです。
まとめ
- Snowflake の Workload Identity Federation により、CI/CD からの接続が安全かつシンプルになった
- SUBJECT の指定や Snowflake CLI の挙動には注意が必要
- それでも 長期認証情報を持たないメリットは非常に大きい