Atlas now manages Snowflake secrets, the schema-level objects that store credentials used by UDFs, procedures, and external access integrations.
A secret holds a credential: a password, an OAuth token, a generic string, or a key. An external access integration names the secrets its code may use. Atlas manages their full lifecycle with CREATE, ALTER, and DROP SECRET.
Declaring a Secret
The new secret block requires schema and type. The rest of its attributes depend on the type:
| Type | Attributes |
|---|---|
| OAUTH2 | api_authentication, comment, and either oauth_scopes or oauth_refresh_token with oauth_refresh_token_expiry_time. The two are mutually exclusive. |
| PASSWORD | username, password, comment. |
| GENERIC_STRING | secret_string, comment. |
| SYMMETRIC_KEY | algorithm, currently GENERIC, and comment. |
| CLOUD_PROVIDER_TOKEN | api_authentication, comment. Snowflake rejects api_authentication in ALTER SECRET, so it is applied on create and cannot be changed afterwards. |
| WORKLOAD_IDENTITY_FEDERATION | comment, nothing else beyond schema and type. |
One secret of each type:
secret "S_OAUTH" { schema = schema.PUBLIC type = OAUTH2 api_authentication = "ATLAS_SECRET_INT" oauth_scopes = ["scope_a", "scope_b"] comment = "client credentials flow"} secret "S_PASSWORD" { schema = schema.PUBLIC type = PASSWORD username = "your_user" password = "dummy-password" comment = "password secret"} secret "S_GENERIC" { schema = schema.PUBLIC type = GENERIC_STRING secret_string = "dummy-value" comment = "generic string secret"} secret "S_SYMMETRIC" { schema = schema.PUBLIC type = SYMMETRIC_KEY algorithm = GENERIC} secret "S_CLOUD" { schema = schema.PUBLIC type = CLOUD_PROVIDER_TOKEN api_authentication = "SEC_IN30"} secret "S_WIF" { schema = schema.PUBLIC type = WORKLOAD_IDENTITY_FEDERATION}
Planning and Applying Changes
atlas schema apply --env local --skip-lint Planning migration statements (6 in total): -- create secret "s_oauth": -> CREATE SECRET "PUBLIC"."S_OAUTH" TYPE = OAUTH2 API_AUTHENTICATION = ATLAS_SECRET_INT OAUTH_SCOPES = ('scope_a', 'scope_b') COMMENT = 'client credentials flow'; -- create secret "s_password": -- atlas:sensitive: -> CREATE SECRET (sensitive).(sensitive) TYPE = PASSWORD USERNAME = (sensitive) PASSWORD = (sensitive) COMMENT = (sensitive); -- create secret "s_generic": -- atlas:sensitive: -> CREATE SECRET (sensitive).(sensitive) TYPE = GENERIC_STRING SECRET_STRING = (sensitive) COMMENT = (sensitive); -- create secret "s_symmetric": -> CREATE SECRET "PUBLIC"."S_SYMMETRIC" TYPE = SYMMETRIC_KEY ALGORITHM = GENERIC; -- create secret "s_cloud": -> CREATE SECRET "PUBLIC"."S_CLOUD" TYPE = CLOUD_PROVIDER_TOKEN API_AUTHENTICATION = SEC_IN30; -- create secret "s_wif": -> CREATE SECRET "PUBLIC"."S_WIF" TYPE = WORKLOAD_IDENTITY_FEDERATION;
A statement that carries a password, a secret string, or a refresh token is printed with (sensitive) in their place. The real values are still used during execution.
Inspecting Applied Secrets
Atlas keeps credentials out of its output. Inspection writes <sensitive> in place of a password, a secret string, or a refresh token, and the api_authentication of a CLOUD_PROVIDER_TOKEN secret is not part of the inspected state:
secret "S_CLOUD" { schema = schema.PUBLIC type = CLOUD_PROVIDER_TOKEN}secret "S_GENERIC" { schema = schema.PUBLIC type = GENERIC_STRING secret_string = "<sensitive>" comment = "generic string secret"}secret "S_OAUTH" { schema = schema.PUBLIC type = OAUTH2 api_authentication = "ATLAS_SECRET_INT" oauth_scopes = ["scope_a", "scope_b"] comment = "client credentials flow"}secret "S_PASSWORD" { schema = schema.PUBLIC type = PASSWORD username = "your_user" password = "<sensitive>" comment = "password secret"}secret "S_SYMMETRIC" { schema = schema.PUBLIC type = SYMMETRIC_KEY algorithm = GENERIC}secret "S_WIF" { schema = schema.PUBLIC type = WORKLOAD_IDENTITY_FEDERATION}
Versioned and Declarative Workflows
To keep credentials safe, the versioned workflow does not support a secret that carries a password, a secret string, or a refresh token. Apply those in the declarative workflow with atlas schema apply --skip-lint. Secrets that carry none of those, SYMMETRIC_KEY, CLOUD_PROVIDER_TOKEN, WORKLOAD_IDENTITY_FEDERATION, and OAUTH2 with oauth_scopes, are unaffected.
Getting Started
Secrets are opt-in. Set secrets = true in the mode "snowflake" block of your env to manage them. Add sensitive = ALLOW only when Atlas should plan the sensitive information a secret carries, such as a password or a secret string:
env "local" { url = "snowflake://user:pass@account_identifier/database" dev = "snowflake://user:pass@dev_account_identifier/database" schema { src = "file://schema.hcl" mode "snowflake" { secrets = true sensitive = ALLOW } }}
The secret block is documented in the Snowflake HCL reference. Snowflake support is part of Atlas Pro. Run atlas login to get started.