雪花掩蔽策略:输入可以是常量字符串变量吗?
Snowflake masking policy: can the input be a constant string variable?
我正在尝试创建带有标记的屏蔽策略:
CREATE OR REPLACE MASKING POLICY TAGS_MASKING
AS (val VARCHAR, col_name STRING) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN ('ADMIN_ROLE') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SELECT SYSTEM$GET_TAG('TAG_NAME', col_name , 'COLUMN') = 'PUBLIC') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SELECT SYSTEM$GET_TAG('TAG_NAME', col_name , 'COLUMN') IN ('PROTECTED')) THEN '****MASKED****'
END;
这里,col_name 是一个字符串(例如 'mytable.col1'),这样我就可以将此屏蔽策略分配给任何我想要的列。但是当我使用下面的查询将它分配给一个 table 的一列时,它失败了:
ALTER TABLE IF EXISTS db.masking.mytable MODIFY COLUMN col1
SET MASKING POLICY TAGS_MASKING using (col1, 'mytable.col1');
错误信息是:
Syntax error: unexpected "mytable.col1"
我该如何解决这个问题?谢谢!
我还没有找到参数化列名的方法(将其作为可选的第二个参数传递),所以我使用了不同的方法。
它使用 Snowflake 脚本自动为每个列创建屏蔽策略。
设置:
CREATE OR REPLACE TAG TAG_NAME;
CREATE OR REPLACE TABLE mytable(col1 STRING);
ALTER TABLE mytable SET TAG TAG_NAME='PUBLIC';
INSERT INTO mytable(col1) VALUES ('Test');
SELECT * FROM mytable;
-- Test
程序:
CREATE OR REPLACE PROCEDURE test(schema_name STRING, tab_name STRING, col_name STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
sql_masking_policy STRING;
sql_alter_table STRING;
masking_policy_name STRING := CONCAT_WS('_', 'TAGS_MASKING_', SCHEMA_NAME, TAB_NAME, COL_NAME);
BEGIN
sql_masking_policy := '
CREATE OR REPLACE MASKING POLICY <masking_policy_name>
AS (val VARCHAR) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN (''ADMIN_ROLE'') THEN val
WHEN CURRENT_ROLE() IN (''ANALYST_ROLE'') AND (SYSTEM$GET_TAG(''TAG_NAME'', ''<col_name>'', ''COLUMN'') = ''PUBLIC'') THEN val
WHEN CURRENT_ROLE() IN (''ANALYST_ROLE'') AND (SYSTEM$GET_TAG(''TAG_NAME'', ''<col_name>'', ''COLUMN'') IN (''PROTECTED'')) THEN ''****MASKED****''
END;';
sql_alter_table := 'ALTER TABLE IF EXISTS <tab_name> MODIFY COLUMN <col_name>
SET MASKING POLICY <masking_policy_name>;';
sql_masking_policy := REPLACE(sql_masking_policy, '<masking_policy_name>', :masking_policy_name);
sql_masking_policy := REPLACE(sql_masking_policy, '<col_name>', CONCAT_WS('.', schema_name, tab_name, col_name));
sql_alter_table := REPLACE(sql_alter_table, '<masking_policy_name>', :masking_policy_name);
sql_alter_table := REPLACE(sql_alter_table, '<tab_name>', CONCAT_WS('.', schema_name, tab_name));
sql_alter_table := REPLACE(sql_alter_table, '<col_name>', col_name);
EXECUTE IMMEDIATE :sql_masking_policy;
EXECUTE IMMEDIATE :sql_alter_table;
RETURN sql_masking_policy || CHR(10) || sql_alter_table;
END;
$$;
通话:
CALL test('public', 'mytable', 'col1');
输出:
CREATE OR REPLACE MASKING POLICY TAGS_MASKING__public_mytable_col1
AS (val VARCHAR) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN ('ADMIN_ROLE') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SYSTEM$GET_TAG('TAG_NAME', 'public.mytable.col1', 'COLUMN') = 'PUBLIC') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SYSTEM$GET_TAG('TAG_NAME', 'public.mytable.col1', 'COLUMN') IN ('PROTECTED')) THEN '****MASKED****'
END;
ALTER TABLE IF EXISTS public.mytable MODIFY COLUMN col1 SET MASKING POLICY TAGS_MASKING__public_mytable_col1;
检查:
SHOW MASKING POLICIES;
输出:
使用POLICY_CONTEXT测试select:
execute using policy_context(current_role => 'PUBLIC')
AS
SELECT * FROM public.mytable;
-- NULL
execute using policy_context(current_role => 'ADMIN_ROLE')
AS
SELECT * FROM public.mytable;
-- Test
execute using policy_context(current_role => 'ANALYST_ROLE')
AS
SELECT * FROM public.mytable;
-- Test
ALTER TABLE mytable SET TAG TAG_NAME='PROTECTED';
execute using policy_context(current_role => 'ANALYST_ROLE')
AS
SELECT * FROM public.mytable;
-- ****MASKED****
我正在尝试创建带有标记的屏蔽策略:
CREATE OR REPLACE MASKING POLICY TAGS_MASKING
AS (val VARCHAR, col_name STRING) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN ('ADMIN_ROLE') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SELECT SYSTEM$GET_TAG('TAG_NAME', col_name , 'COLUMN') = 'PUBLIC') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SELECT SYSTEM$GET_TAG('TAG_NAME', col_name , 'COLUMN') IN ('PROTECTED')) THEN '****MASKED****'
END;
这里,col_name 是一个字符串(例如 'mytable.col1'),这样我就可以将此屏蔽策略分配给任何我想要的列。但是当我使用下面的查询将它分配给一个 table 的一列时,它失败了:
ALTER TABLE IF EXISTS db.masking.mytable MODIFY COLUMN col1
SET MASKING POLICY TAGS_MASKING using (col1, 'mytable.col1');
错误信息是:
Syntax error: unexpected "mytable.col1"
我该如何解决这个问题?谢谢!
我还没有找到参数化列名的方法(将其作为可选的第二个参数传递),所以我使用了不同的方法。
它使用 Snowflake 脚本自动为每个列创建屏蔽策略。
设置:
CREATE OR REPLACE TAG TAG_NAME;
CREATE OR REPLACE TABLE mytable(col1 STRING);
ALTER TABLE mytable SET TAG TAG_NAME='PUBLIC';
INSERT INTO mytable(col1) VALUES ('Test');
SELECT * FROM mytable;
-- Test
程序:
CREATE OR REPLACE PROCEDURE test(schema_name STRING, tab_name STRING, col_name STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
sql_masking_policy STRING;
sql_alter_table STRING;
masking_policy_name STRING := CONCAT_WS('_', 'TAGS_MASKING_', SCHEMA_NAME, TAB_NAME, COL_NAME);
BEGIN
sql_masking_policy := '
CREATE OR REPLACE MASKING POLICY <masking_policy_name>
AS (val VARCHAR) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN (''ADMIN_ROLE'') THEN val
WHEN CURRENT_ROLE() IN (''ANALYST_ROLE'') AND (SYSTEM$GET_TAG(''TAG_NAME'', ''<col_name>'', ''COLUMN'') = ''PUBLIC'') THEN val
WHEN CURRENT_ROLE() IN (''ANALYST_ROLE'') AND (SYSTEM$GET_TAG(''TAG_NAME'', ''<col_name>'', ''COLUMN'') IN (''PROTECTED'')) THEN ''****MASKED****''
END;';
sql_alter_table := 'ALTER TABLE IF EXISTS <tab_name> MODIFY COLUMN <col_name>
SET MASKING POLICY <masking_policy_name>;';
sql_masking_policy := REPLACE(sql_masking_policy, '<masking_policy_name>', :masking_policy_name);
sql_masking_policy := REPLACE(sql_masking_policy, '<col_name>', CONCAT_WS('.', schema_name, tab_name, col_name));
sql_alter_table := REPLACE(sql_alter_table, '<masking_policy_name>', :masking_policy_name);
sql_alter_table := REPLACE(sql_alter_table, '<tab_name>', CONCAT_WS('.', schema_name, tab_name));
sql_alter_table := REPLACE(sql_alter_table, '<col_name>', col_name);
EXECUTE IMMEDIATE :sql_masking_policy;
EXECUTE IMMEDIATE :sql_alter_table;
RETURN sql_masking_policy || CHR(10) || sql_alter_table;
END;
$$;
通话:
CALL test('public', 'mytable', 'col1');
输出:
CREATE OR REPLACE MASKING POLICY TAGS_MASKING__public_mytable_col1
AS (val VARCHAR) RETURNS VARCHAR ->
CASE
WHEN CURRENT_ROLE() IN ('ADMIN_ROLE') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SYSTEM$GET_TAG('TAG_NAME', 'public.mytable.col1', 'COLUMN') = 'PUBLIC') THEN val
WHEN CURRENT_ROLE() IN ('ANALYST_ROLE') AND (SYSTEM$GET_TAG('TAG_NAME', 'public.mytable.col1', 'COLUMN') IN ('PROTECTED')) THEN '****MASKED****'
END;
ALTER TABLE IF EXISTS public.mytable MODIFY COLUMN col1 SET MASKING POLICY TAGS_MASKING__public_mytable_col1;
检查:
SHOW MASKING POLICIES;
输出:
使用POLICY_CONTEXT测试select:
execute using policy_context(current_role => 'PUBLIC')
AS
SELECT * FROM public.mytable;
-- NULL
execute using policy_context(current_role => 'ADMIN_ROLE')
AS
SELECT * FROM public.mytable;
-- Test
execute using policy_context(current_role => 'ANALYST_ROLE')
AS
SELECT * FROM public.mytable;
-- Test
ALTER TABLE mytable SET TAG TAG_NAME='PROTECTED';
execute using policy_context(current_role => 'ANALYST_ROLE')
AS
SELECT * FROM public.mytable;
-- ****MASKED****