3. 基于角色的访问控制(RBAC)核心
Snowflake 的访问控制体系以 RBAC(Role-Based Access Control,基于角色的访问控制)为核心。理解 RBAC 的关键,不是记住“角色”这个词,而是理解 Snowflake 中权限的授予对象是角色,用户通过被授予角色来间接获得权限。也就是说,权限不直接挂在用户身上,而是挂在角色上,用户与权限之间通过角色解耦。这一设计使得权限管理可以按“职责”而不是按“个人”来组织。
一、角色层次结构:权限沿继承链向下流动
Snowflake 的角色不是平铺的,而是构成一棵有向的层次树。角色可以被授予给另一个角色,形成“父角色—子角色”的继承关系。继承的方向是:父角色自动拥有其所有子角色的权限。换句话说,权限从子角色向父角色“向上汇聚”,而使用父角色的用户则“向下”获得整棵子树的权限。
系统内置的最高角色是 ACCOUNTADMIN,它位于层次结构顶端,拥有账户级管理能力。其下是 SECURITYADMIN(负责用户与角色管理)和 SYSADMIN(负责数据库对象管理),再往下是 USERADMIN(负责用户与角色创建)以及 PUBLIC(默认授予所有用户的公共角色)。自定义角色通常挂在 SYSADMIN 之下,形成业务职责分支。
需要特别注意的是,ACCOUNTADMIN 虽然位于顶端,但它并不自动继承 SYSADMIN 下的所有自定义角色——除非显式授予。因此,最佳实践是:日常对象管理使用 SYSADMIN,安全与权限管理使用 SECURITYADMIN,ACCOUNTADMIN 仅用于账户级紧急操作,避免日常使用。
二、系统角色与自定义角色
系统角色由 Snowflake 预定义,不可删除,其权限范围固定。它们承担的是“平台管理”职责,而不是“业务数据访问”职责。自定义角色则由用户按业务需要创建,用于承载具体的数据访问权限。两者的分工可以概括为:系统角色管平台,自定义角色管数据。
创建自定义角色的典型语句如下:
-- 使用 USERADMIN 创建角色
USE ROLE USERADMIN;
CREATE ROLE IF NOT EXISTS analyst_ro COMMENT = '只读分析角色';
CREATE ROLE IF NOT EXISTS etl_rw COMMENT = 'ETL 读写角色';
-- 将自定义角色授予 SYSADMIN,纳入对象管理树
USE ROLE SECURITYADMIN;
GRANT ROLE analyst_ro TO ROLE sysadmin;
GRANT ROLE etl_rw TO ROLE sysadmin;
-- 将角色授予用户
GRANT ROLE analyst_ro TO USER alice;
GRANT ROLE etl_rw TO USER bob;
这里有一个容易被忽略的细节:创建角色后,必须把角色授予 SYSADMIN(或其它父角色),否则该角色会游离在层次结构之外,导致 SYSADMIN 无法管理其下的对象权限。这是 Snowflake RBAC 中非常关键的一步。
三、角色授权与继承:权限如何真正生效
角色授权分为两类:一是把对象权限授予角色,二是把角色授予用户或另一个角色。对象权限包括 SELECT、INSERT、UPDATE、DELETE、USAGE、CREATE 等,作用对象可以是数据库、模式、表、视图、仓库等。
-- 授予仓库使用权限
GRANT USAGE ON WAREHOUSE compute_wh TO ROLE analyst_ro;
-- 授予数据库与模式使用权限
GRANT USAGE ON DATABASE sales_db TO ROLE analyst_ro;
GRANT USAGE ON SCHEMA sales_db.public TO ROLE analyst_ro;
-- 授予表查询权限
GRANT SELECT ON TABLE sales_db.public.orders TO ROLE analyst_ro;
-- 授予未来表权限(关键:避免逐表授权)
GRANT SELECT ON FUTURE TABLES IN SCHEMA sales_db.public TO ROLE analyst_ro;
继承关系决定了权限的可见范围。当用户 alice 被授予 analyst_ro 后,她不仅拥有 analyst_ro 的直接权限,还拥有其所有子角色的权限。如果 analyst_ro 被授予了 reporting_ro,那么 alice 同时获得 reporting_ro 的权限。这种“一次授予、多层生效”的机制,正是 RBAC 降低管理成本的核心。
验证权限是否生效,可以使用以下命令:
-- 查看当前角色
SELECT CURRENT_ROLE();
-- 查看角色继承关系
SHOW GRANTS TO ROLE analyst_ro;
-- 查看用户被授予的角色
SHOW GRANTS TO USER alice;
-- 以指定角色执行查询,验证权限
USE ROLE analyst_ro;
SELECT COUNT(*) FROM sales_db.public.orders;
如果查询返回结果,说明权限链完整;如果报“Insufficient privileges”,则需要沿继承链逐层检查:用户是否被授予角色、角色是否被授予父角色、对象权限是否授予角色、仓库与数据库的 USAGE 是否齐备。
四、最佳实践
- 按职责而非按人建角色。角色应对应岗位或业务职能,如
analyst_ro、etl_rw、finance_rw,而不是alice_role。人员变动时只调整角色授予,不重建权限。 - 保持层次结构清晰。自定义角色统一挂在
SYSADMIN下,安全相关角色挂在SECURITYADMIN下,避免角色游离或形成环状继承。 - 优先使用 FUTURE GRANTS。对模式中未来创建的表、视图使用
ON FUTURE授权,避免新对象上线后权限缺失。 - 最小权限原则。只授予完成工作所必需的最小权限,读多写少的场景优先使用只读角色,写权限单独建角色。
- 限制 ACCOUNTADMIN 使用。日常操作使用
SYSADMIN或自定义角色,ACCOUNTADMIN仅用于账户级配置与紧急恢复。 - 定期审计。使用
SHOW GRANTS与ACCOUNT_USAGE.GRANTS_TO_ROLES定期检查权限授予情况,清理不再使用的角色与授权。
总结来说,Snowflake RBAC 的核心在于:角色是权限的载体,继承是权限的放大器,层次结构是管理的骨架。掌握角色层次、系统角色与自定义角色的分工、授权与继承的生效路径,再配合最小权限与定期审计,才能构建出既安全又易维护的访问控制体系。