高级列级安全主题¶
本主题介绍与列级安全掩码策略相关的两个高级概念:
角色层次结构。
使用多个 上下文函数。
上下文函数和角色层次结构¶
列级安全性支持在掩码策略正文的条件中使用 上下文函数 来强制执行用户是否拥有查看数据的授权。若要确定用户是否可以查看给定 SQL 语句中的数据,请考虑以下因素:
- 当前会话:
使用 CURRENT_ROLE 的掩码策略条件以当前会话所使用的角色为目标。
- 数据库和架构:
如果在掩码或行访问策略的正文中指定 CURRENT_DATABASE 或 CURRENT_SCHEMA 函数,该函数会返回包含受保护表的数据库或架构,而不是用于会话的数据库或架构。
- 执行角色:
使用 INVOKER_ROLE 的掩码策略条件以 SQL 语句中的执行角色为目标。
- 角色层次结构:
如果策略条件中需要角色层次结构,请使用 IS_ROLE_IN_SESSION。
确定掩码策略条件中的指定角色(例如
analyst
自定义角色)是否是 CURRENT_ROLE 或 INVOKER_ROLE 角色层次结构中的较低权限角色。如果是这样,则 CURRENT_ROLE 或 INVOKER_ROLE 函数返回的角色将继承指定角色的权限。有关角色层次结构和权限继承的更多信息,请参阅:
下表显示了以会话、执行角色和角色层次结构为目标的掩码策略中的常见上下文函数。
上下文函数 |
描述 |
---|---|
返回当前会话所使用的角色名称。 |
|
在策略正文中,返回包含受掩码策略保护的表的数据库。 |
|
在策略正文中,返回包含受掩码策略保护的表的架构。 |
|
如果用户在会话中的当前角色(即 CURRENT_ROLE 返回的角色)继承了指定角色的权限,则返回 TRUE。 |
|
返回执行角色的名称。 |
|
如果 INVOKER_ROLE 函数返回的角色根据调用函数的上下文继承实参中指定角色的权限,则返回 TRUE。 |
|
返回共享的名称,该共享直接访问了调用 INVOKER_SHARE 函数的表或视图。 |
使用 CURRENT_ROLE 和 IS_ROLE_IN_SESSION¶
使用 CURRENT_ROLE 的掩码策略条件以当前会话为目标,不受 SQL 语句的执行上下文影响。
如果策略条件需要角色激活和角色层次结构,请使用 IS_ROLE_IN_SESSION。
请考虑以下掩码策略正文:
CREATE OR REPLACE MASKING POLICY mask_string AS (val string) RETURNS string -> CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '********' END;
要确定给定用户是否获得授权查看设置了此掩码策略的列中的数据,请完成以下步骤:
评估掩码策略条件。
确定指定的角色是否在 CURRENT_ROLE 层次结构中。
运行测试查询进行验证。
第 1 步:评估掩码策略条件¶
下表总结了掩码策略正文条件的后果。
上下文 |
查看未掩码数据 |
查看掩码数据 |
---|---|---|
CURRENT_ROLE = ANALYST 自定义角色。 |
✔ |
|
CURRENT_ROLE 位于 层次结构中的 ANALYST 自定义角色中。 |
✔ |
|
CURRENT_ROLE 不在 ANALYST 自定义角色层次结构中。 |
✔ |
接下来,评估角色层次结构。
第 2 步:确定指定的角色是否在 CURRENT_ROLE 层次结构中¶
假设 CURRENT_ROLE 不是 ANALYST 自定义角色,请确定 CURRENT_ROLE 是否继承授予 ANALYST 自定义角色的权限。
执行以下语句:
SELECT IS_ROLE_IN_SESSION('ANALYST');+-------------------------------+ | IS_ROLE_IN_SESSION('ANALYST') | +-------------------------------+ | FALSE | +-------------------------------+
由于 Snowflake 返回 FALSE,因此 CURRENT_ROLE 不会继承授予 ANALYST 自定义角色的权限。因此,基于此示例中的掩码策略正文,用户应看到固定的掩码值。
第 3 步:运行测试查询进行验证¶
对已将此示例中的掩码策略应用于该列的列执行查询,以验证用户是否看到固定的掩码值。
USE ROLE analyst;
SELECT * FROM mydb.mysch.mytable;
使用 INVOKER_ROLE¶
使用 INVOKER_ROLE 的掩码策略条件以 SQL 语句的执行上下文为目标。
下表总结了 INVOKER_ROLE 在掩码策略条件中返回的执行上下文和值:
上下文 |
评估的角色 |
---|---|
用户 |
|
表 |
CURRENT_ROLE。 |
视图 |
查看所有者角色。 |
UDF |
UDF 所有者角色。 |
拥有调用方权限的存储过程 |
CURRENT_ROLE。 |
拥有所有者权限的存储过程 |
存储过程所有者角色。 |
任务 |
任务所有者角色。 |
流 |
查询给定 流 的角色。 |
请考虑以下应用于表中单个视图的掩码策略正文:
CREATE OR REPLACE MASKING POLICY mask_string AS (val string) RETURNS string -> CASE WHEN INVOKER_ROLE() IN ('ANALYST') THEN val ELSE '********' END;
要确定对列运行查询的给定用户是否拥有查看数据的授权,请完成以下步骤:
评估掩码策略条件。
确定指定的角色是否拥有视图。
运行测试查询进行验证。
第 1 步:评估掩码策略条件¶
下表汇总了应用于视图列的掩码策略正文条件的后果。
上下文 |
查看未掩码数据 |
查看掩码数据 |
---|---|---|
|
✔ |
|
|
✔ |
接下来,确定 ANALYST 自定义角色是否拥有视图。
第 2 步:确定 ANALYST 角色是否拥有视图¶
若要确定 ANALYST 自定义角色是否拥有视图,请执行以下语句:
SHOW GRANTS OF ROLE analyst;
如果 analyst
自定义角色拥有视图,则对视图列的查询应生成未掩码数据。
如果 analyst
自定义角色未拥有视图,则应看到掩码数据。
第 3 步:运行测试查询进行验证¶
对视图列执行查询,以确定 ANALYST 自定义角色是看到掩码数据还是未掩码数据。
USE ROLE analyst;
SELECT * FROM mydb.mysch.myview;
使用 IS_GRANTED_TO_INVOKER_ROLE¶
此 IS_GRANTED_TO_INVOKER_ROLE 函数可以作为条件的一部分传递到掩码策略正文中。当函数的计算结果为 TRUE 时,函数实参中的角色位于 INVOKER_ROLE 层次结构中。
请考虑以下应用于社会安全号码 (SSNs) 视图列的掩码策略正文:
CREATE OR REPLACE MASKING POLICY mask_string AS
(val string) RETURNS string ->
CASE
WHEN IS_GRANTED_TO_INVOKER_ROLE('PAYROLL') THEN val
WHEN IS_GRANTED_TO_INVOKER_ROLE('ANALYST') THEN REGEXP_REPLACE(val, '[0-9]', '*', 7)
ELSE '*******'
END;
要确定对视图列运行查询的给定用户是否拥有查看数据的授权,请完成以下步骤:
评估掩码策略条件。
确定指定的角色是否位于调用方角色层次结构中。例如,如果在视图上设置了策略,则指定的角色必须位于返回 TRUE 的视图所有者角色层次结构中。有关详细信息,请参阅 使用说明。
运行测试查询进行验证。
第 1 步:评估掩码策略条件¶
下表汇总了应用于视图列的掩码策略正文条件和在视图列中查看数据的结果。
上下文 |
未掩码数据 |
部分掩码数据 |
掩码数据 |
---|---|---|---|
|
✔ |
||
|
✔ |
||
|
✔ |
第 2 步:确定指定的角色是否在视图所有者角色层次结构中¶
如果 payroll
或 analyst
自定义角色位于视图所有者层次结构中,则对视图所有者角色执行 SHOW GRANTS 命令可以验证角色层次结构。例如:
SHOW GRANTS TO ROLE view_owner_role;
此 SQL 语句的输出将说明是否已向 payroll
或 analyst
自定义角色授予视图所有者角色。
第 3 步:运行测试查询进行验证¶
对已将此示例中的掩码策略应用于该列的列执行查询,以验证用户如何查看视图列中的数据。
USE ROLE payroll;
SELECT * FROM mydb.mysch.myview;
USE ROLE analyst;
SELECT * FROM mydb.mysch.myview;
合并 CURRENT_ROLE 和 INVOKER_ROLE 掩码策略¶
Snowflake 支持创建单个掩码策略,以区分执行查询(即 CURRENT_ROLE)的会话所使用的角色和执行查询的对象所有者(如视图所有者 INVOKER_ROLE)。相比简单地确定一组要掩码的值和确定可以看到未掩码值的相对较小受众(例如拥有 analyst
自定义角色的用户),这种类型的用例通常更复杂。
掩码策略中的哈希、密码和加密函数¶
哈希 和 加密/校验 可用于掩码策略,以对敏感数据进行掩码处理。
在 掩码策略 中实施任何这些函数之前,请务必考虑这些函数的用例是否涉及 JOIN 操作。实施某些掩码策略时,涉及表和视图的创意 JOIN 操作可能会导致基于以下限制将掩码值反向工程为其真实值:
可能会发生冲突,因为实际值(即输入)和基于要转换的值总数(即输出、值范围)的哈希值、加密值或校验和值可能没有 1:1 的比例表示。
在输入值的总数达到要转换的输出值的平方根之前,更有可能发生 1:1 比例表示。
例如,如果哈希的输出值为 144,则可以合理地预期前 12 个值(即 144^(1/2) – 144 的平方根)是唯一的,并且其余 132 个值可能会发生冲突。由于此限制及其后果是可能的,因此建议永远不要在其值可能用于 JOIN 操作的掩码策略中使用哈希、加密或校验和函数。
小技巧
如果掩码策略用例优先考虑避免冲突以增强安全性,请实施 External Tokenization。令牌化不会导致冲突,因为输入和输出值始终以 1:1 的比例表示。
如果无法进行令牌化,一种可能的解决方法是实施掩码策略,以区分执行查询的会话角色(即 CURRENT_ROLE)和执行查询的对象所有者(即 INVOKER_ROLE)。
例如,以下掩码策略采用两个不同的自定义角色 CSR_EMPL_INFO 和 DBA_EMPL_INFO 来规范对员工信息的访问。
CREATE OR REPLACE MASKING POLICY mask_string AS (val string) RETURNS string -> CASE WHEN CURRENT_ROLE() IN ('CSR_EMPL_INFO') THEN HASH(val) WHEN INVOKER_ROLE() IN ('DBA_EMPL_INFO') THEN val ELSE null END;
如果将策略应用于表,策略将继承到创建自表的任何视图。如果自定义角色 dba_empl_info
拥有创建自此表的视图(即对视图拥有 OWNERSHIP 权限),则在查询视图时,只有拥有此自定义角色的用户才能查看实际值。拥有 csr_empl_info
自定义角色的用户无论是在表上还是在视图上进行查询,始终都会看到哈希值。所有其他用户都会看到 NULL
。