It's been four months since Snowflake released Workload Identity Federation (WIF) in August 2025, enabling secure, secretless authentication for applications and services. So if you're still using passwords or key-pairs for your CI/CD pipelines, it's time to upgrade. Here's how to set up OIDC with GitHub Actions as a modern, secure way to authenticate.
Why OIDC over traditional credentials?
Before diving into the technical details, here's a refresher on why this matters.
| Approach | Credential Lifecycle | Risk | Rotation Burden |
|---|---|---|---|
| Passwords/Key-pairs | Long-lived, stored in secrets | Full access if revoked | Manual rotation required |
| OIDC | Short-lived, never stored | Expires quickly, scope-limited | None as tokens are ephemeral |
With OIDC, GitHub Actions requests a short-lived token at runtime. Snowflake validates this token against the issuer (GitHub), and if the claims match, authentication succeeds. No secrets to leak, rotate or manage.
A reminder on least privilege
Using ACCOUNTADMIN for any workflow is obviously an egregious example, but it illustrates the importance of least privilege.
| Aspect | ❌ ACCOUNTADMIN | ✅ Custom Role |
|---|---|---|
| Permissions | Full control over your entire Snowflake account | Only the specific permissions needed |
| Security Risk | A compromised workflow could drop databases, users, or access billing | Blast radius is limited to the granted scope |
| Principle | Violates least privilege principle | Follows security best practices |
| Auditability | Audit logs are harder to interpret | Clear accountability for actions |
Step 1: Create a least-privilege role
Before creating service users, define roles scoped to each environment's database. This ensures your CI/CD pipelines can only affect their intended environment. The below example creates a test OIDC role and user which can never touch prod.
CREATE ROLE TEST_CICD_ROLE;
GRANT CREATE SCHEMA ON DATABASE TEST_DATABASE TO ROLE TEST_CICD_ROLE;
Step 2: Create a Snowflake service user
Create a service user with a workload identity tied to your repository. The SUBJECT must match our GitHub repository and environment exactly (this is case-sensitive).
For a GitHub organisation called MechRock, a repository named snowflake-infrastructure and a GitHub environment called test:
CREATE USER TEST_SVC_INFRA_GITHUB
DEFAULT_ROLE = TEST_CICD_ROLE
TYPE = SERVICE
COMMENT = 'GitHub Actions service user for TEST infrastructure deployments'
WORKLOAD_IDENTITY = (
TYPE = OIDC
ISSUER = 'https://token.actions.githubusercontent.com'
SUBJECT = 'repo:MechRock/snowflake-infrastructure:environment:test'
);
-- Don't forget to grant the role to the user!
GRANT ROLE TEST_CICD_ROLE TO USER TEST_SVC_INFRA_GITHUB;
Step 3: Configure a GitHub Actions workflow
Deploy the following workflow to validate your Snowflake OIDC authentication. The id-token: write permission is required for GitHub to issue the OIDC token, and the environment: test must match the subject claim you configured in Snowflake.
name: Snowflake OIDC
on: workflow_dispatch
permissions:
id-token: write
contents: read
jobs:
oidc-job:
runs-on: ubuntu-latest
environment: test
steps:
- name: Set up Snowflake CLI
uses: snowflakedb/snowflake-cli-action@v2.0
with:
use-oidc: true
cli-version: "3.14.0"
- name: test connection
env:
SNOWFLAKE_ACCOUNT: A1234567890-MECHROCK
run: snow connection test -x
Trigger the workflow manually to confirm everything is wired up correctly. If authentication fails, verify that your SUBJECT claim matches exactly and that the GitHub environment exists.
Bonus Step: Using schemachange with OIDC
Once Snowflake OIDC is working, you can integrate it with database migration tools like schemachange.
Here's a complete workflow that verifies schemachange directory on push to main:
name: schemachange Deploy
on:
workflow_dispatch:
push:
branches:
- main
permissions:
id-token: write
contents: read
jobs:
schemachange-deploy:
runs-on: ubuntu-latest
environment: test
env:
SNOWFLAKE_ACCOUNT: A1234567890-MECHROCK
steps:
- uses: actions/checkout@v5
- name: Setup Snowflake CLI for OIDC
uses: snowflakedb/snowflake-cli-action@v2.0
with:
use-oidc: true
cli-version: "3.14.0"
- name: setup Python
uses: actions/setup-python@v6
with:
python-version: 3.13
- run: pip install schemachange
- name: Schemachange verify
run: schemachange verify --schemachange-root-folder deploy
Remember to
- Always use a least-privilege custom role, never ACCOUNTADMIN
- Match your
SUBJECTclaim exactly to your repository and environment (it's case-sensitive!) - Leverage GitHub environment protection rules for additional security
This pattern extends beyond simple deployments. Once you've got OIDC working, consider applying it to dbt, Terraform, or any tool that integrates with the Snowflake CLI.
Wrapping up
With Workload Identity Federation, you've eliminated long-lived credentials from your CI/CD pipeline. No more rotating keys, no more secrets sprawl. You now have a more secure, auditable, ephemeral authentication.
If you're looking to empower your data stack, consider dbt Projects on Snowflake - check out Maciej Tarsa's blog here for more info.
Feel free to reach out to Mechanical Rock for anything data related!