Snowflake is removing single-factor passwords in three phases. In the last one, rolled out account by account between August and October 2026, users that are not people can no longer sign in with a password at all, and the old LEGACY_SERVICE users become SERVICE users. A dbt project that runs on a schedule with a user and password stops working on the day the change reaches your account. Key-pair authentication is the usual replacement.

Copy and paste

1. Generate the keys. The first command asks for a passphrase that protects the private key:

openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 aes-256-cbc -inform PEM -out rsa_key.p8
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub

2. Copy the public key without its header and footer:

grep -v "PUBLIC KEY" rsa_key.pub | tr -d '\n'

3. Create the service user and attach the key (as a role that owns the user, for example USERADMIN):

create user if not exists DBT_SERVICE
  type = service
  default_role = TRANSFORMER
  default_warehouse = TRANSFORMING;

alter user DBT_SERVICE set rsa_public_key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...';

grant role TRANSFORMER to user DBT_SERVICE;

4. Point profiles.yml at the private key:

shop:
  target: prod
  outputs:
    prod:
      type: snowflake
      account: myorg-myaccount
      user: DBT_SERVICE
      role: TRANSFORMER
      private_key_path: /secure/keys/rsa_key.p8
      private_key_passphrase: "{{ env_var('DBT_ENV_SECRET_KEY_PASSPHRASE') }}"
      database: ANALYTICS
      warehouse: TRANSFORMING
      schema: ANALYTICS
      threads: 8

5. Test the connection:

export DBT_ENV_SECRET_KEY_PASSPHRASE='your passphrase'
dbt debug

The last line should read Connection test: [OK connection ok].

The key in a variable instead of a file

Where files are awkward, as in some CI systems, put the content of the private key in a secret and use private_key instead of private_key_path:

      private_key: "{{ env_var('DBT_ENV_SECRET_PRIVATE_KEY') }}"
      private_key_passphrase: "{{ env_var('DBT_ENV_SECRET_KEY_PASSPHRASE') }}"

Use one or the other: with both, dbt stops with Cannot specify both private_key and private_key_path. Variables whose name starts with DBT_ENV_SECRET_ are kept out of the logs; see how to use environment variables in profiles.yml.

Check the fingerprint

If Snowflake rejects the key, compare the fingerprint it stored with the one of your file:

desc user DBT_SERVICE
  ->> select substr((select "value" from $1 where "property" = 'RSA_PUBLIC_KEY_FP'), len('SHA256:') + 1) as key;
openssl rsa -pubin -in rsa_key.pub -outform DER | openssl dgst -sha256 -binary | openssl enc -base64

The two values must be identical.

Errors you may see

Things to know

Tested with dbt Core 1.12 and dbt-snowflake 1.12.4: dbt loaded the encrypted key and reached Snowflake’s login endpoint, and reported the error above for a wrong passphrase. The Snowflake SQL and the timeline come from Snowflake’s documentation.

References