3. 基于角色的访问控制(RBAC)核心概念
Snowflake 的权限体系建立在“角色”这一核心抽象之上。理解 RBAC,本质上要回答四个问题:谁在操作(用户)、以什么身份操作(角色)、能操作什么(权限/对象)、这些身份之间如何继承(角色层次结构)。把这四件事串起来,才能写出正确的 GRANT 与 REVOKE 语句,并在排障时快速定位“为什么这个用户看不到这张表”。
一、四个基本对象
用户(User)是登录 Snowflake 的账号实体,它本身几乎不直接持有对象权限。用户通过被授予角色来获得能力。一个用户可以同时拥有多个角色,但在任意时刻只有一个“当前角色(current role)”在生效,这决定了本次会话能做什么。
角色(Role)是权限的容器,也是权限授予的中间层。Snowflake 预置了若干系统角色,最典型的是 SYSADMIN(管理数据库、仓库等对象)和 SECURITYADMIN(管理用户与角色授权),此外还有 ACCOUNTADMIN、USERADMIN、PUBLIC 等。自定义角色通常由 SECURITYADMIN 或具备 MANAGE GRANTS 权限的角色创建。
权限(Privilege)是对某个对象执行某类操作的许可,例如对数据库的 USAGE、对表的 SELECT/INSERT、对仓库的 USAGE/OPERATE、对模式的 CREATE TABLE 等。权限总是“对象 + 动作”的组合,授予时必须明确对象层级。
角色层次结构(Role Hierarchy)通过角色之间的授予关系形成继承链。若把角色 A 授予角色 B,则 B 自动继承 A 的全部权限。Snowflake 推荐把自定义角色挂在 SYSADMIN 之下,从而让 SYSADMIN 能够统一管理这些角色所拥有的对象。
二、角色层次结构如何工作
角色层次结构是一条单向的权限继承链。当执行 GRANT ROLE bi_role TO ROLE analyst_role; 时,analyst_role 就继承了 bi_role 的全部权限。此后把 bi_role 授予用户 alice,alice 切换到 analyst_role 后即可使用 bi_role 的能力。继承是“向下流动”的:上层角色拥有下层角色的权限,反之不成立。
Snowflake 官方推荐的最佳实践是:所有自定义角色最终都授予 SYSADMIN。这样 SYSADMIN 作为对象管理者的角色,能够看到并管理这些自定义角色所创建的对象,避免出现“对象存在但无人能管”的孤儿对象。系统角色之间的层次是固定的:ACCOUNTADMIN 位于最顶层,SECURITYADMIN 与 USERADMIN 负责安全与用户管理,SYSADMIN 负责对象管理,PUBLIC 是所有角色的默认继承角色。
三、权限授予与撤销的基本语法
授予角色给用户或角色,使用 GRANT ROLE:
-- 创建自定义角色
CREATE ROLE analyst_role;
CREATE ROLE bi_role;
-- 角色继承:bi_role 授予 analyst_role
GRANT ROLE bi_role TO ROLE analyst_role;
-- 角色授予用户
GRANT ROLE analyst_role TO USER alice;
-- 将自定义角色挂到 SYSADMIN 之下
GRANT ROLE analyst_role TO ROLE SYSADMIN;
授予对象权限,使用 GRANT <privilege> ON <object> TO ROLE:
-- 数据库与模式的使用权限
GRANT USAGE ON DATABASE sales_db TO ROLE bi_role;
GRANT USAGE ON SCHEMA sales_db.public TO ROLE bi_role;
-- 表的查询权限
GRANT SELECT ON TABLE sales_db.public.orders TO ROLE bi_role;
-- 仓库的使用权限
GRANT USAGE ON WAREHOUSE compute_wh TO ROLE bi_role;
-- 未来表的自动授权(对新建对象生效)
GRANT SELECT ON FUTURE TABLES IN SCHEMA sales_db.public TO ROLE bi_role;
撤销权限使用 REVOKE,语法与 GRANT 对称:
REVOKE SELECT ON TABLE sales_db.public.orders FROM ROLE bi_role;
REVOKE ROLE bi_role FROM ROLE analyst_role;
REVOKE ROLE analyst_role FROM USER alice;
四、当前角色与权限验证
用户登录后默认使用其默认角色。切换当前角色使用 USE ROLE,查看当前角色使用 SELECT CURRENT_ROLE()。验证权限是否生效,最直接的方式是切换到目标角色后尝试访问对象:
USE ROLE analyst_role;
SELECT CURRENT_ROLE(); -- 返回 ANALYST_ROLE
SELECT * FROM sales_db.public.orders LIMIT 10; -- 成功则权限生效
-- 查看某角色被授予的权限
SHOW GRANTS TO ROLE bi_role;
-- 查看某用户拥有的角色
SHOW GRANTS TO USER alice;
如果查询报错 “Insufficient privileges to operate on table”,通常说明当前角色缺少该表的 SELECT 权限,或缺少上层数据库/模式的 USAGE 权限。注意:Snowflake 的权限检查是逐层递进的——要访问一张表,必须同时拥有数据库的 USAGE、模式的 USAGE 以及表的 SELECT,缺一不可。这是排障时最容易被忽略的一点。
五、设计角色时的几个关键判断
- 按职能而非按人建角色:角色应对应岗位或职责(如 analyst、etl、report),而不是为每个用户单独建角色,否则角色数量会失控。
- 权限尽量授予基础角色:把对象权限授予最底层的功能角色,再通过角色继承向上组合,避免在多个角色上重复授权。
- 遵循最小权限原则:只授予完成工作所必需的权限,例如报表角色通常只需要 SELECT,不需要 INSERT 或 CREATE。
- 保持层次清晰:自定义角色统一挂到 SYSADMIN 下,安全相关角色由 SECURITYADMIN 管理,避免角色链交叉混乱。
掌握以上概念后,RBAC 的日常操作就归结为三类语句:CREATE ROLE 建角色、GRANT 授权(角色给用户、角色给角色、权限给角色)、REVOKE 回收。真正决定权限体系是否健康的,不是语句本身,而是角色层次的设计是否清晰、权限是否按最小必要原则分配。