投影策略¶
本主题介绍如何使用投影策略允许或阻止在 SQL 查询结果输出中投影列。
概述¶
投影策略是第一类架构级对象,用于定义是否可以在 SQL 查询结果输出中投影列。分配了投影策略的列称为 投影约束 列。
在 安全共享数据 时,可以使用投影策略来约束对象的标识符列(例如名称、电话号码)。例如,假设有两家公司希望成为解决方案合作伙伴,并希望在开发集成解决方案之前确定一组共同客户。提供商可以将投影策略分配给共享中的标识符列,这对使用者识别敏感信息是必要的。使用者可以使用共享数据根据先前商定的列(这些列是解决方案所必需的)执行匹配,但不能从这些列返回值。
在此示例中使用投影策略的好处包括:
使用者可以根据特定值匹配记录,但无法查看该值。
不会在 SQL 查询结果中输出敏感的提供商信息。有关更多详细信息,请参阅 注意事项 部分(本主题内容)。
创建投影策略后,策略管理员可以将投影策略分配给列。在任何时候,只能为一列分配一个投影策略。只有当用户的活动角色符合允许投影列的投影策略条件时,用户才能投影列。
请注意,投影约束列也可以受掩码策略保护,并且包含投影约束列的表可以受行访问策略保护。有关更多详细信息,请参阅 掩码和行访问策略 (本主题内容)。
列使用情况¶
Snowflake 会跟踪列的使用情况。当对列设置了投影策略时,对列的间接引用(例如视图定义、UDF [在本主题中] 和常用表表达式)会影响列的投影。
当如果在列上设置了投影策略,但列无法被投影,则该列:
不包含在查询结果的输出中。
不能插入到其他表。
不能作为外部函数或存储过程的参数。
限制¶
- UDFs:
有关用户定义的函数的限制 (UDFs),请参阅 用户定义的函数 (UDFs) (本主题内容)。
- 策略:
投影策略不能应用于:
标签,并且该标签不能分配给表或列(即“基于标签的投影策略”)。
虚拟列或外部表中的 VALUE 列。
解决方法是创建一个视图,并为不应投影的每一列分配投影策略。
投影策略
body
不能引用受掩码策略保护的列或受行访问策略保护的表。有关更多详细信息,请参阅 掩码和行访问策略 (本主题内容)。
注意事项¶
当用例要求查询敏感列而不直接向分析师或类似角色公开列值时,可使用投影策略。与屏蔽值或标记化值相比,可以更灵活地分析投影约束列内的列值。但是,在对列设置投影策略之前,请考虑以下事项:
预测策略不会阻止针对个人的操作。
例如,即使
name
列受投影约束,用户仍然可以筛选包含该列,且该列与特定个人对应的行。但是,用户无法运行 SELECT 语句查看表中个人的姓名。当投影约束列在将受保护表中的数据与未受保护表中的数据合并在一起的查询中用作联接键时,没有任何限制会阻止用户在未受保护表中投影该列的值。因此,如果未受保护表中的值与受保护列的值匹配,用户可以通过从未受保护表中投影来获取该值。
假设已为
t_protected
表的email
列分配了投影策略。用户仍然可以通过执行以下操作确定t_protected.email
列中的值:SELECT t_unprotected.email FROM t_unprotected JOIN t_protected ON t_unprotected.email = t_protected.email;
投影约束不能保证恶意行为者无法通过故意查询来从投影约束列中获取可能敏感的数据。投影策略最适合用于已有一定信任度的合作伙伴和客户。此外,提供商应警惕可能存在的数据滥用(例如,查看提供商列表的访问历史记录)。
创建投影策略¶
投影策略包含一个调用内部 PROJECTION_CONSTRAINT 函数的 body
,以确定是否对列进行投影。
CREATE OR REPLACE PROJECTION POLICY <name> AS () RETURNS PROJECTION_CONSTRAINT -> <body>其中:
name
指定策略的名称。
AS () RETURNS PROJECTION_CONSTRAINT
是策略的签名和返回类型。签名不接受任何实参,返回类型为 PROJECTION_CONSTRAINT,这是一种内部数据类型。所有投影策略都具有相同的签名和返回类型。
body
是确定是否对列进行投影的 SQL 表达式。该表达式调用内部函数 PROJECTION_CONSTRAINT 来允许或阻止列投影:
PROJECTION_CONSTRAINT(ALLOW => true)
允许投影列。
PROJECTION_CONSTRAINT(ALLOW => false)
不允许投影列。
策略示例¶
最简单的投影策略直接调用 PROJECTION_CONSTRAINT 函数:
- 允许列投影
CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => true)
- 防止列投影
CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => false)
可以编写更复杂的 SQL 表达式来调用 PROJECTION_CONSTRAINT 函数。表达式可以使用 条件表达式函数 和 上下文函数 来引入逻辑,允许具有特定角色的某些用户投影列,并阻止所有其他用户投影列。
小技巧
在条件策略中使用上下文函数时,可以使用以下策略:
上下文函数返回字符串,因此使用它们进行比较时区分大小写。如果想进行不区分大小写的比较,可以使用 LOWER 将字符串转换为全部小写。
当上下文函数返回某个值时,POLICY_CONTEXT 函数可以帮助您评估策略正文是否返回正确的值。POLICY_CONTEXT 函数根据一个或多个上下文函数的指定值模拟查询结果。
以下示例包括一个 CASE 表达式和 CURRENT_ROLE 上下文函数,用于创建一个条件策略,该策略仅允许具有 analyst
自定义角色的用户投影列:
CREATE OR REPLACE PROJECTION POLICY mypolicy AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN CURRENT_ROLE() = 'ANALYST' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
以下示例使用 SYSTEM$GET_TAG_ON_CURRENT_COLUMN 函数,这样分配给列的标记就可以确定是否可以投影该列。在这种情况下,当策略分配给一列时,该列上的 tags.accounting_col
标记值必须为 public
,才能投影该列。
CREATE PROJECTION POLICY mypolicy
AS () RETURNS PROJECTION_CONSTRAINT ->
CASE
WHEN SYSTEM$GET_TAG_ON_CURRENT_COLUMN('tags.accounting_col') = 'public'
THEN PROJECTION_CONSTRAINT(ALLOW => true)
ELSE PROJECTION_CONSTRAINT(ALLOW => false)
END;
对于数据共享用例,提供商可以编写投影策略,使用 CURRENT_ACCOUNT 上下文函数限制所有使用者账户的列投影,或使用 INVOKER_SHARE 上下文函数有选择地限制特定共享中的列投影。例如:
- 限制所有使用者账户
在此示例中,
provider.account
是账户名称格式的 账户标识符:CREATE OR REPLACE PROJECTION POLICY restrict_consumer_accounts AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN CURRENT_ACCOUNT() = 'provider.account' THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
- 限制到特定共享
假设有一个数据共享提供商账户,它在安全视图的一列上设置了投影策略。有两个不同的共享(
SHARE1
和SHARE2
)可以访问安全视图,以支持两个不同的数据共享使用者。如果数据共享使用者账户中的用户尝试通过任一共享方式进行列投影,则他们可以投影该列;否则无法进行投影。
CREATE OR REPLACE PROJECTION POLICY projection_share AS () RETURNS PROJECTION_CONSTRAINT -> CASE WHEN INVOKER_SHARE() IN ('SHARE1', 'SHARE2') THEN PROJECTION_CONSTRAINT(ALLOW => true) ELSE PROJECTION_CONSTRAINT(ALLOW => false) END;
分配投影策略¶
使用 ALTER TABLE ...ALTER COLUMN 命令可将投影策略应用于表列,使用 ALTER VIEW 命令可将投影策略应用于视图列。每列仅支持一个投影策略。
ALTER { TABLE | VIEW } <name> { ALTER | MODIFY } COLUMN <col1_name> SET PROJECTION POLICY <policy_name> [ FORCE ] [ , <col2_name> SET PROJECTION POLICY <policy_name> [ FORCE ] ... ]
其中:
name
指定表或视图的名称。col1_name
指定表或视图中列的名称。col2_name
指定表或视图中附加列的名称。policy_name
指定在列上设置的投影策略的名称。FORCE
是一个可选参数,该参数允许命令将投影策略分配给已分配了投影策略的列。新的投影策略会以原子方式替换现有的投影策略。
例如,在表的 account_number
列上设置投影策略 proj_policy_acctnumber
:
ALTER TABLE finance.accounting.customers MODIFY COLUMN account_number SET PROJECTION POLICY proj_policy_acctnumber;
您还可以使用 CREATE TABLE 和 CREATE VIEW 命令的 WITH 子句,在创建表或视图时为列分配投影策略。例如,要将策略 my_proj_policy
分配给新表的 account_number
列,请执行:
CREATE TABLE t1 (account_number NUMBER WITH PROJECTION POLICY my_proj_policy);
在现有表中添加新列时,也可以使用 WITH 子句。例如,要将策略 my_proj_policy
分配给 zipcode
列(该列正在添加到现有表 customers
中),请执行:
ALTER TABLE customers ADD COLUMN account_number NUMBER WITH PROJECTION POLICY my_proj_policy;
替换投影策略¶
替换投影策略的推荐方法是使用 FORCE
参数分离现有投影策略,并在一条命令中分配新投影策略。这使您能够以原子方式替换旧策略,而不会留下任何保护漏洞。
例如,为已受投影约束的列分配新的投影策略:
ALTER TABLE finance.accounting.customers
MODIFY COLUMN account_number
SET PROJECTION POLICY proj_policy2 FORCE;
您也可以在一条语句 (...UNSET PROJECTION POLICY) 中分离列的投影策略,然后在另一条语句 (...SET PROJECTION POLICY <name>) 中为列设置新策略。如果选择此方法,在分离一个策略和分配另一个策略之间,列不受投影策略的保护。在此期间,查询可能会访问敏感数据。
分离投影策略¶
使用 ALTER TABLE 或 ALTER VIEW 命令中的 UNSET PROJECTION POLICY 子句可以从表或视图的列中分离投影策略。投影策略的名称不是必需的,因为一列不能附加多个投影策略。
ALTER { TABLE | VIEW } <name> { ALTER | MODIFY } COLUMN <col1_name> UNSET PROJECTION POLICY [ , <col2_name> UNSET PROJECTION POLICY ... ]
其中:
name
指定表或视图的名称。col1_name
指定表或视图中列的名称。col2_name
指定表或视图中附加列的名称。
例如,移除 account_number
列中的投影策略:
ALTER TABLE finance.accounting.customers MODIFY COLUMN account_number UNSET PROJECTION POLICY;
使用 SQL 监控投影策略¶
实用做法是,考虑采用两种通用方法来确定如何监控投影策略的使用情况。
了解投影策略¶
您可以使用 PROJECTION_POLICIES 在共享的 Account Usage 架构中查看 SNOWFLAKE 数据库。此视图是 Snowflake 账户中所有投影策略的 目录。例如:
SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.PROJECTION_POLICIES ORDER BY POLICY_NAME;
识别投影策略引用¶
POLICY_REFERENCES Information Schema 表函数可以识别投影策略引用。有两种不同的语法选项:
为在列上设置了指定投影策略的每个对象(即表或视图)返回一行:
USE DATABASE my_db; SELECT policy_name, policy_kind, ref_entity_name, ref_entity_domain, ref_column_name, ref_arg_column_names, policy_status FROM TABLE(information_schema.policy_references(policy_name => 'my_db.my_schema.projpolicy'));
为分配给名为
my_table
的表的每个策略返回一行:USE DATABASE my_db; USE SCHEMA information_schema; SELECT policy_name, policy_kind, ref_entity_name, ref_entity_domain, ref_column_name, ref_arg_column_names, policy_status FROM TABLE(information_schema.policy_references(ref_entity_name => 'my_db.my_schema.my_table', ref_entity_domain => 'table'));
扩展示例¶
创建投影策略并为列分配投影策略的一般步骤与创建和分配其他策略(如掩码策略和行访问策略)的步骤相同:
对于集中式管理方法,可创建自定义角色(例如
proj_policy_admin
)来管理策略。授予此角色创建和分配投影策略的权限。
创建投影策略。
将投影策略分配给列。
根据此通用程序,完成以下步骤为列分配投影策略:
创建自定义角色以管理投影策略:
USE ROLE useradmin; CREATE ROLE proj_policy_admin;
授予
proj_policy_admin
自定义角色在架构中创建投影策略并将投影策略分配给 Snowflake 账户中的任何表或视图列的权限。此步骤假定投影策略将存储在名为
privacy.projpolicies
的数据库和架构中,并且此数据库和架构已存在:GRANT USAGE ON DATABASE privacy TO ROLE proj_policy_admin; GRANT USAGE ON SCHEMA privacy.projpolicies TO ROLE proj_policy_admin; GRANT CREATE PROJECTION POLICY ON SCHEMA privacy.projpolicies TO ROLE proj_policy_admin; GRANT APPLY PROJECTION POLICY ON ACCOUNT TO ROLE proj_policy_admin;
有关详细信息,请参阅 权限和命令 (本主题内容)。
创建投影策略以阻止列投影:
USE ROLE proj_policy_admin; USE SCHEMA privacy.projpolicies; CREATE OR REPLACE PROJECTION POLICY proj_policy_false AS () RETURNS PROJECTION_CONSTRAINT -> PROJECTION_CONSTRAINT(ALLOW => false);
将投影策略分配给表列:
ALTER TABLE customers MODIFY COLUMN active SET PROJECTION POLICY privacy.projpolicies.proj_policy_false;
投影策略与 Snowflake 功能¶
以下小节简要总结了投影策略如何与各种 Snowflake 功能和服务交互。
掩码和行访问策略¶
- 多种策略:
一列可以同时具有掩码策略和投影策略,并且包含此列的表可以受行访问策略的保护。如果这三个策略都存在,Snowflake 将按如下方式处理表和策略:
根据行访问策略应用行筛选器。
确定查询是否正在尝试投影受投影策略限制的任何列,如果是,则拒绝查询。
根据掩码策略应用列掩码。
受掩码策略保护的列也可以受到投影约束。例如,在包含账户的列上设置的掩码策略可能具有一个条件,允许具有
finance_admin
自定义角色的用户查看账户,还有另一个条件是将账户替换为所有其他角色的哈希。投影策略可以进一步限制列,使具有
analyst
自定义角色的用户无法投影列。请注意,具有analyst
自定义角色仍可通过对哈希进行分组或联接这些哈希来分析列。Snowflake 建议策略管理员与内部合规性和监管官员合作,确定应对哪些列进行投影约束。
- 策略评估:
在以下情况下,掩码策略或行访问策略无法引用投影约束列:
为表分配行访问策略。
在 条件掩码策略 中枚举一个或多个列。
执行映射表查找。
如 限制 (本主题内容)中所述,投影策略
body
不能引用受掩码策略保护的列或受行访问策略保护的表。
采用其他投影策略的依赖对象¶
请考虑以下一系列对象:
base_table
»v1
»v2
其中:
v1
是基于名为base_table
的表创建的视图。
v2
是基于v1
构建的视图。
如果对视图中受投影约束的某个列进行查询,而该列又依赖于 base_table
中受投影约束的列,则只有当 两个 投影策都允许对该列进行投影时,才会对视图列进行投影。
Snowflake 会检查列沿袭(一直到基表),以确保对列的任何引用都不受投影约束。如果沿袭链中的任何列受投影约束,并且不允许投影该列,则 Snowflake 将阻止查询。
视图和物化视图¶
视图列上的投影策略约束的是视图列,而不是基础表列。
关于引用,约束表列的投影策略将延续到引用受约束表列的视图。
流和任务¶
表中列的投影策略会延续到同一个表上的流。请注意,不能在流上设置投影策略。
同样,当任务引用受约束的列时,受投影约束的列仍受约束。
UNPIVOT¶
UNPIVOT 结构的结果取决于列最初是否受投影策略的约束。注意:
执行 UNPIVOT 之前和之后,受约束的列仍受投影约束。
name_column
始终显示在查询结果中。如果
column_list
中的任何列受投影约束,那么value_column
也受投影约束。
克隆对象¶
以下方法有助于保护数据,防止拥有 SELECT 权限的用户访问存储在克隆数据库或架构中的克隆表或视图:
不支持克隆单个投影策略对象。
克隆架构会导致克隆该架构中的所有投影策略。
克隆的表会映射到与源表相同的投影策略。
当表在其父架构克隆的上下文中进行克隆时,如果源表引用了同一父架构中投影策略(即本地引用),则克隆的表将引用克隆的投影策略。
如果源表引用了不同架构中的投影策略(即外部引用),则克隆表会保留外部引用。
有关更多信息,请参阅 CREATE <object> ... CLONE。
复制¶
可以使用数据库复制和复制组来复制投影策略及其分配。
对于 数据库复制,如果满足以下任一条件,则复制操作会失败:
主数据库位于企业账户(或更高版本)中,包含策略,但批准复制的一个或多个账户的版本较低。
主数据库中包含的表或视图可以 悬空引用 到其他数据库中的投影策略。
在 复制组 中复制多个数据库时,可避免数据库复制的悬空引用行为。
用户定义的函数 (UDFs)¶
请注意以下有关投影约束和 UDFs 的内容:
- Scalar SQL UDFs:
Snowflake 会评估 UDF,然后将投影策略应用于投影约束列。
如果 SELECT 语句中的一列是从派生自投影约束列的 UDF 过渡派生的,则 Snowflake 会阻止查询。换言之:
pc_column
» UDF » 列(在 SELECT 语句中)其中:
pc_column
指投影约束列。
因为 SELECT 语句中的列可追溯到投影约束列,因此 Snowflake 会阻止查询。
- SQL UDTFs:
SQL 用户定义的表函数 (UDTF) 遵循与 SQL UDFs 相同的行为,但由于在函数输出中会返回行,因此 Snowflake 会独立评估表中的每一列,以决定是否在函数输出中投影该列。
- 其他 UDFs:
以下内容适用于 Java UDFs 简介、JavaScript UDFs 简介 和 Python UDFs 简介:
投影约束列在 UDTF 输出中受到约束。
- 日志记录和事件表:
当 UDF、UDTF 或 JavaScript UDF 具有投影约束实参时,Snowflake 不会在相应的事件表中捕获日志记录和事件详细信息。但是,Snowflake 允许 UDF/UDTF 执行并且不会由于日志记录原因导致调用 UDF/UDTF 的语句失败。
权限和命令¶
以下各小节提供有助于管理投影策略的信息。
投影策略权限¶
Snowflake 支持对投影策略对象的以下权限。
请注意,对架构中的对象进行操作还需要对父数据库和架构具有 USAGE 权限。
权限 |
用途 |
---|---|
APPLY |
允许在列上对投影策略执行设置和设置操作。 |
OWNERSHIP |
转移投影策略的所有权,从而授予对投影策略的完全控制权。更改投影策略的大多数属性时需要此权限。 |
有关详细信息,请参阅 DDL 命令、操作和权限总结 (本主题内容)。
投影策略 DDL 参考¶
Snowflake 支持通过以下 DDL 创建和管理投影策略。
DDL 命令、操作和权限总结¶
下表总结了投影策略权限和 DDL 操作之间的关系。
请注意,对架构中的对象进行操作还需要对父数据库和架构具有 USAGE 权限。
操作 |
需要权限 |
---|---|
创建投影策略。 |
在同一架构中具有 CREATE PROJECTION POLICY 权限的角色。 |
更改投影策略。 |
具有投影策略的 OWNERSHIP 权限的角色。 |
描述投影策略 |
以下其中一项:
|
弃用投影策略。 |
具有投影策略的 OWNERSHIP 权限的角色。 |
显示投影策略。 |
以下其中一项:
|
在列上设置或取消设置投影策略。 |
以下其中一项:
|
Snowflake 支持不同的权限,以创建和设置对象的投影策略。
对于集中式投影策略管理方法,即
projection_policy_admin
自定义角色在 所有 列中创建和设置投影策略时采用的方法,需要以下权限:USE ROLE securityadmin; GRANT USAGE ON DATABASE mydb TO ROLE projection_policy_admin; GRANT USAGE ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT CREATE PROJECTION POLICY ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT APPLY ON PROJECTION POLICY ON ACCOUNT TO ROLE projection_policy_admin;
在混合管理方法中,单个角色具有 CREATE PROJECTION POLICY 权限,以确保投影策略的命名一致,并且各个团队或角色具有特定投影策略的 APPLY 权限。
例如,可以向自定义角色
finance_role
授予在角色拥有的表和视图上设置投影策略cost_center
的权限(即该角色具有表或视图的 OWNERSHIP 权限):USE ROLE securityadmin; GRANT CREATE PROJECTION POLICY ON SCHEMA mydb.schema TO ROLE projection_policy_admin; GRANT APPLY ON PROJECTION POLICY cost_center TO ROLE finance_role;