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

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:

LayerExampleContains
Access roles
(object-scoped)
AR_METER_READS_READ, AR_CUSTOMER_PII_READ, AR_CUSTOMER_PII_WRITEActual GRANTs on tables/views/schemas
Functional roles
(job-scoped)
FR_ANALYST_CUSTOMER, FR_ENGINEER_METER, FR_EXEC_DASHBOARDOne 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?

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."