Lesson 7.1 โ RBAC, the Snowflake Way
You know RBAC in the abstract (K8s, IAM, LDAP groups). Snowflake's twist: privileges are granted to roles, roles are granted to roles OR users, and there's a built-in hierarchy you must understand before touching production.
The built-in role hierarchy
ACCOUNTADMIN โ god-mode. Avoid daily use.
/ \
SECURITYADMIN SYSADMIN โ security admin separation
(grants, users) (objects, warehouses)
โ โ
USERADMIN (custom roles)
(create users) / โ \
ANALYST ENGINEER PII_READER
/ \
Alice Bob โ users get roles, not privileges directly
The roles you'll see in every Snowflake account
- ACCOUNTADMIN โ everything. Use for setup only, never for regular work. Two people max should have it.
- SECURITYADMIN โ manages roles, grants, masking policies. Not the one that creates objects.
- USERADMIN โ creates users and roles. Inherits from SECURITYADMIN.
- SYSADMIN โ creates databases, warehouses, schemas, tables. This is the "root owner" of your data objects. Most custom roles are granted to SYSADMIN so it has visibility.
- PUBLIC โ default role. Everyone gets it. Grant nothing to it beyond trivial metadata.
Gotcha that's tested in interviews
SYSADMIN does not have visibility into objects created by ACCOUNTADMIN by default. If you create a database while logged in as ACCOUNTADMIN, SYSADMIN can't see it. Always: GRANT OWNERSHIP ON DATABASE x TO ROLE SYSADMIN; after creation. Better: log in as SYSADMIN to create objects in the first place.
The pattern enterprises actually use: Functional vs Access roles
Rather than grant privileges directly to "Alice," two layers are used:
| Layer | Example | Contains |
|---|---|---|
| Access roles (object-scoped) | AR_METER_READS_READ, AR_CUSTOMER_PII_READ, AR_CUSTOMER_PII_WRITE | Actual GRANTs on tables/views/schemas |
| Functional roles (job-scoped) | FR_ANALYST_CUSTOMER, FR_ENGINEER_METER, FR_EXEC_DASHBOARD | One or more access roles |
-- Access role: can read meter_reads
CREATE ROLE AR_METER_READS_READ;
GRANT USAGE ON DATABASE UTILITY_PROD TO ROLE AR_METER_READS_READ;
GRANT USAGE ON SCHEMA UTILITY_PROD.OPERATIONS TO ROLE AR_METER_READS_READ;
GRANT SELECT ON TABLE UTILITY_PROD.OPERATIONS.METER_READS TO ROLE AR_METER_READS_READ;
-- Functional role: "analyst who works on customer-facing dashboards"
CREATE ROLE FR_ANALYST_CUSTOMER;
GRANT ROLE AR_METER_READS_READ TO ROLE FR_ANALYST_CUSTOMER;
GRANT ROLE AR_CIS_READ TO ROLE FR_ANALYST_CUSTOMER;
-- User gets functional roles only
GRANT ROLE FR_ANALYST_CUSTOMER TO USER alice;
-- Functional roles roll up to SYSADMIN so sysadmin sees everything
GRANT ROLE FR_ANALYST_CUSTOMER TO ROLE SYSADMIN;
Why bother with two layers?
- Decoupled change: new table? Update access role. Alice's job changed? Change functional role. The two don't collide.
- Auditable: "who can read PII?" โ
SHOW GRANTS OF ROLE AR_CUSTOMER_PII_READ. Clean answer. - Standard across the industry: this is the pattern Snowflake Security Best Practices prescribes. Interviewers will ask specifically.
Active role vs secondary roles
A user has one active role at a time (the one they use to run a query) but can have many assigned. USE ROLE x; switches. "Secondary roles" (introduced 2022) allow combining grants โ useful for dashboards that touch multiple domains.
Auditing grants
SHOW GRANTS TO USER alice;
SHOW GRANTS TO ROLE FR_ANALYST_CUSTOMER;
SHOW GRANTS OF ROLE AR_METER_READS_READ;
SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.GRANTS_TO_USERS WHERE granted_to = 'ALICE';
The ACCOUNT_USAGE views are Snowflake's internal audit trail โ 365 days of grant history, query history, access history. Lean on them in compliance reviews.
The security story you can tell
"In Snowflake I'd set up separate functional roles (analyst, engineer, exec) and access roles (per-table, per-schema read/write) rolling up to SYSADMIN. User assignments hit functional roles only. The access layer evolves independently of the user layer. For PII, the access role uses a masking policy that only reveals real values to a named role, and row access policies scope rows by region or account status."