Snowflake Role Setup
Create a least-privilege Snowflake role for the Snowplane operator. Never use ACCOUNTADMIN in production.
Create a Dedicated Role
USE ROLE ACCOUNTADMIN;
CREATE ROLE IF NOT EXISTS SNOWPLANE_ROLE
COMMENT = 'Role for Snowplane Kubernetes operator';
Create a Snowplane User
For key-pair authentication:
CREATE USER IF NOT EXISTS SNOWPLANE_USER
DEFAULT_ROLE = SNOWPLANE_ROLE
MUST_CHANGE_PASSWORD = FALSE
TYPE = SERVICE
COMMENT = 'Service user for Snowplane operator';
For Workload Identity Federation (WIF):
CREATE USER IF NOT EXISTS SNOWPLANE_WIF_USER
DEFAULT_ROLE = SNOWPLANE_ROLE
TYPE = SERVICE
COMMENT = 'Service user for Snowplane WIF';
Grant Role to User
GRANT ROLE SNOWPLANE_ROLE TO USER SNOWPLANE_USER;
Grant Privileges per Resource Type
Account-Level Privileges
GRANT CREATE DATABASE ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE WAREHOUSE ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE USER ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE ROLE ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE NETWORK POLICY ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE RESOURCE MONITOR ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE INTEGRATION ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
MANAGE GRANTSis a powerful privilege. Only grant it if using the Grant, GrantOwnership, or RoleAssignment CRDs:GRANT MANAGE GRANTS ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
Database-Level Privileges
For pre-existing databases not managed by Snowplane:
GRANT CREATE SCHEMA ON DATABASE <database_name> TO ROLE SNOWPLANE_ROLE;
Schema-Level Privileges
GRANT CREATE TABLE ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE VIEW ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE STAGE ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE TASK ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT EXECUTE TASK ON ACCOUNT TO ROLE SNOWPLANE_ROLE;
GRANT CREATE STREAM ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE TAG ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE MASKING POLICY ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE ROW ACCESS POLICY ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE FILE FORMAT ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE PIPE ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
GRANT CREATE DYNAMIC TABLE ON SCHEMA <db>.<schema> TO ROLE SNOWPLANE_ROLE;
Privilege Summary
| Privilege | Required For | Scope |
|---|---|---|
CREATE DATABASE ON ACCOUNT |
Database CRD | Account |
CREATE WAREHOUSE ON ACCOUNT |
Warehouse CRD | Account |
CREATE USER ON ACCOUNT |
User CRD | Account |
CREATE ROLE ON ACCOUNT |
AccountRole CRD | Account |
MANAGE GRANTS ON ACCOUNT |
Grant, GrantOwnership, AccountRoleAssignment, DatabaseRoleAssignment CRDs | Account (optional) |
CREATE SCHEMA ON DATABASE |
Schema CRD | Per-database |
CREATE TABLE ON SCHEMA |
Table CRD | Per-schema |
CREATE VIEW ON SCHEMA |
View CRD | Per-schema |
CREATE STAGE ON SCHEMA |
InternalStage, ExternalStage CRDs | Per-schema |
CREATE TASK ON SCHEMA |
Task CRD | Per-schema |
EXECUTE TASK ON ACCOUNT |
Task CRD (resume) | Account |
CREATE STREAM ON SCHEMA |
Stream CRD | Per-schema |
CREATE TAG ON SCHEMA |
Tag CRD | Per-schema |
CREATE NETWORK POLICY ON ACCOUNT |
NetworkPolicy CRD | Account |
CREATE RESOURCE MONITOR ON ACCOUNT |
ResourceMonitor CRD | Account |
CREATE MASKING POLICY ON SCHEMA |
MaskingPolicy CRD | Per-schema |
CREATE ROW ACCESS POLICY ON SCHEMA |
RowAccessPolicy CRD | Per-schema |
CREATE INTEGRATION ON ACCOUNT |
StorageIntegrationAWS, StorageIntegrationGCS, StorageIntegrationAzure CRDs | Account |
CREATE INTEGRATION ON ACCOUNT |
ExternalOAuthIntegration, SAML2Integration, SCIMIntegration CRDs | Account |
CREATE INTEGRATION ON ACCOUNT |
EmailNotificationIntegration, QueueNotificationIntegration, WebhookNotificationIntegration CRDs | Account |
CREATE PASSWORD POLICY ON SCHEMA |
PasswordPolicy CRD | Per-schema |
CREATE NETWORK RULE ON SCHEMA |
NetworkRule CRD | Per-schema |
CREATE FILE FORMAT ON SCHEMA |
FileFormat CRD | Per-schema |
CREATE PIPE ON SCHEMA |
Pipe CRD | Per-schema |
CREATE DYNAMIC TABLE ON SCHEMA |
DynamicTable CRD | Per-schema |
RSA Key Setup (Key-Pair Auth)
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out snowplane_key.p8 -nocrypt
openssl rsa -in snowplane_key.p8 -pubout -out snowplane_key.pub
ALTER USER SNOWPLANE_USER SET RSA_PUBLIC_KEY = '<your-public-key>';
kubectl create secret generic snowflake-credentials \
--from-file=private-key=snowplane_key.p8 \
-n snowplane-system
Workload Identity Federation Setup
For WIF, create a security integration in Snowflake:
CREATE SECURITY INTEGRATION IF NOT EXISTS SNOWPLANE_WIF_INTEGRATION
TYPE = EXTERNAL_OAUTH
ENABLED = TRUE
EXTERNAL_OAUTH_TYPE = CUSTOM
EXTERNAL_OAUTH_ISSUER = '<your-oidc-issuer-url>'
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'sub'
EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'LOGIN_NAME'
EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE'
EXTERNAL_OAUTH_AUDIENCE_LIST = ('<your-audience>')
EXTERNAL_OAUTH_JWS_KEYS_URL = '<your-oidc-jwks-url>';
See Workload Identity Guide for cloud-specific setup.
Using useRole for Role Switching
The spec.useRole field lets you specify a different Snowflake role for USE ROLE — without extra ProviderConfigs or MANAGE GRANTS.
Setup
-
Grant the target role to the service user:
GRANT ROLE ENGINEER TO USER SNOWPLANE_USER; -
Ensure the target role has the necessary privileges:
GRANT CREATE DATABASE ON ACCOUNT TO ROLE ENGINEER; -
Set
useRoleon the resource spec:apiVersion: snowplane.hupe1980.github.io/v1alpha1 kind: Database metadata: name: analytics-db spec: providerRef: name: default-pc useRole: ENGINEER name: ANALYTICS_DB
useRoleis immutable after creation. No MANAGE GRANTS needed. The service user must have the target role directly granted.
Security Recommendations
- Never use ACCOUNTADMIN — run with
SNOWPLANE_ROLEonly - Use SERVICE user type — prevents interactive login
- Rotate keys regularly — Snowplane auto-reconnects on Secret updates
- Separate roles per environment —
SNOWPLANE_ROLE_DEV,SNOWPLANE_ROLE_PROD - Audit regularly — use
SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY - Restrict with AllowedNamespaces —
spec.allowedNamespaceson ProviderConfig