使用安全对象控制数据访问¶
为确保共享数据库中的敏感数据不会暴露给使用者账户中的用户,Snowflake 强烈建议 共享 安全视图 和/或 安全 UDFs,而非直接共享表。
此外,为保证最佳性能,尤其是在超大表中共享数据时,我们建议在基表上为安全对象定义 <label-clustering-keys>` 群集密钥 :ref:`。
本主题介绍在基表中为共享安全对象使用群集密钥,并提供了与使用者账户共享安全视图的详细步骤说明。此外还提供了针对数据提供商和使用者的示例脚本。
备注
共享安全对象的说明与共享表的说明基本相同,只是增加了以下对象:
包含基表的“私有”架构和包含安全对象的“公共”架构。共享的只有公共架构和安全对象。
一个“映射表”(同样位于“私有”架构中),只有在您希望与多个使用者账户共享基表中的数据,以及与特定账户共享表中的特定行时,才需要此映射表。
本主题内容:
设置和任务示例¶
在这些示例说明中,我们假设数据提供商账户中有一个名为 mydb
的数据库,并且有两个架构,分别是 private
和 public
。如果数据库和架构不存在,则应先创建它们,然后再继续操作。
第 1 步:在私有架构中创建数据和映射表¶
在 mydb.private
架构中创建以下两个表,并为其填充数据。
sensitive_data
– 包含要共享的数据,以及用于按账户控制数据访问权限的 access_id
列。sharing_access
– 使用 access_id
列映射共享数据和可访问数据的账户。第 2 步:在公共架构中创建安全视图¶
在 mydb.public
架构中创建以下安全视图:
paid_sensitive_data
– 显示基于账户的数据。请注意,视图中不必包含基表 (sensitive_data
) 中的 access_id
列。
第 3 步:验证表和安全视图¶
验证表和安全视图,以确保按账户正确筛选数据。
为允许验证要与其他账户共享的安全视图,Snowflake 提供了一个会话参数,即 SIMULATED_DATA_SHARING_CONSUMER。将此会话参数设置为您想模拟其访问权限的使用者账户名称。然后可查询视图,并查看该使用者账户中的用户将看到的结果。
脚本示例¶
以下脚本说明了如何执行上一节中介绍的所有任务:
在“私有”架构中创建两个表,并在第一个表中填充三家不同公司(Apple、Microsoft 和 IBM)的股票数据。随后在第二个账户中填充将股票数据映射到个人账户的数据:
use role sysadmin; create or replace table mydb.private.sensitive_data ( name string, date date, time time(9), bid_price float, ask_price float, bid_size int, ask_size int, access_id string /* granularity for access */ ) cluster by (date); insert into mydb.private.sensitive_data values('AAPL',dateadd(day, -1,current_date()), '10:00:00', 116.5, 116.6, 10, 10, 'STOCK_GROUP_1'), ('AAPL',dateadd(month,-2,current_date()), '10:00:00', 116.5, 116.6, 10, 10, 'STOCK_GROUP_1'), ('MSFT',dateadd(day, -1,current_date()), '10:00:00', 58.0, 58.9, 20, 25, 'STOCK_GROUP_1'), ('MSFT',dateadd(month,-2,current_date()), '10:00:00', 58.0, 58.9, 20, 25, 'STOCK_GROUP_1'), ('IBM', dateadd(day, -1,current_date()), '11:00:00', 175.2, 175.4, 30, 15, 'STOCK_GROUP_2'), ('IBM', dateadd(month,-2,current_date()), '11:00:00', 175.2, 175.4, 30, 15, 'STOCK_GROUP_2'); create or replace table mydb.private.sharing_access ( access_id string, snowflake_account string ); /* In the first insert, CURRENT_ACCOUNT() gives your account access to the AAPL and MSFT data. */ insert into mydb.private.sharing_access values('STOCK_GROUP_1', CURRENT_ACCOUNT()); /* In the second insert, replace <consumer_account> with an account name; this account will have */ /* access to IBM data only. Note that account names are case-sensitive and must be in uppercase */ /* enclosed in single-quotes, e.g. */ /* */ /* insert into mydb.private.sharing_access values('STOCK_GROUP_2', 'ACCT1') */ /* */ /* To share the IBM data with multiple accounts, repeat the second insert for each account. */ insert into mydb.private.sharing_access values('STOCK_GROUP_2', '<consumer_account>');
在“公共”架构中创建安全视图。此视图使用第二个表中的映射信息,按账户筛选第一个表中的股票数据:
create or replace secure view mydb.public.paid_sensitive_data as select name, date, time, bid_price, ask_price, bid_size, ask_size from mydb.private.sensitive_data sd join mydb.private.sharing_access sa on sd.access_id = sa.access_id and sa.snowflake_account = current_account(); grant select on mydb.public.paid_sensitive_data to public; /* Test the table and secure view by first querying the data as the provider account. */ select count(*) from mydb.private.sensitive_data; select * from mydb.private.sensitive_data; select count(*) from mydb.public.paid_sensitive_data; select * from mydb.public.paid_sensitive_data; select * from mydb.public.paid_sensitive_data where name = 'AAPL'; /* Next, test the secure view by querying the data as a simulated consumer account. You specify the */ /* account to simulate using the SIMULATED_DATA_SHARING_CONSUMER session parameter. */ /* */ /* In the ALTER command, replace <consumer_account> with one of the accounts you specified in the */ /* mapping table. Note that the account name is not case-sensitive and does not need to be enclosed */ /* in single-quotes, e.g. */ /* */ /* alter session set simulated_data_sharing_consumer=acct1; */ alter session set simulated_data_sharing_consumer=<account_name>; select * from mydb.public.paid_sensitive_data;
使用 ACCOUNTADMIN 角色创建共享。
use role accountadmin; create or replace share mydb_shared comment = 'Example of using Secure Data Sharing with secure views'; show shares;
将对象添加到共享。您可以选择通过数据库角色将这些对象的权限添加到共享(选项 1),或者 将这些对象的权限直接授予共享(选项 2):
/* Option 1: Create a database role, grant privileges on the objects to the database role, and then grant the database role to the share */ create database role mydb.dr1; grant usage on database mydb to database role mydb.dr1; grant usage on schema mydb.public to database role mydb.dr1; grant select on mydb.public.paid_sensitive_data to database role mydb.dr1; grant database role mydb.dr1 to share mydb_shared; /* Option 2: Grant privileges on the database objects to include in the share. */ grant usage on database mydb to share mydb_shared; grant usage on schema mydb.public to share mydb_shared; grant select on mydb.public.paid_sensitive_data to share mydb_shared; /* Confirm the contents of the share. */ show grants to share mydb_shared;
将账户添加到共享。
/* In the alter statement, replace <consumer_accounts> with the */ /* consumer account(s) you assigned to STOCK_GROUP2 earlier, */ /* with each account name separated by commas, e.g. */ /* */ /* alter share mydb_shared set accounts = acct1, acct2; */ alter share mydb_shared set accounts = <consumer_accounts>;
脚本示例(面向使用者)¶
使用者可使用以下脚本来创建数据库(从上述脚本中创建的共享),并在所获得的数据库中查询安全视图:
通过从共享创建数据库,将共享数据库引入您的账户。
/* In the following commands, the share name must be fully qualified by replacing */ /* <provider_account> with the name of the account that provided the share, e.g. */ /* */ /* desc prvdr1.mydb_shared; */ use role accountadmin; show shares; desc share <provider_account>.mydb_shared; create database mydb_shared1 from share <provider_account>.mydb_shared;
向您账户中的其他角色授予数据库权限(例如 CUSTOM_ROLE1)。根据数据使用者是使用数据库角色向共享添加对象(选项 1),还是直接向共享授予对象权限(选项 2),GRANT 语句会有所不同:
/* Option 1 */ grant database role mydb_shared1.db1 to role custom_role1; /* Option 2 */ grant imported privileges on database mydb_shared1 to custom_role1;
使用 CUSTOM_ROLE1 角色查询您创建的数据库中的视图。请注意,会话中必须在使用有效的仓库才能执行查询。在 USE WAREHOUSE 命令中,将 <warehouse_name> 替换为账户中一个仓库的名称。CUSTOM_ROLE1 角色必须具有仓库的 USAGE 权限:
use role custom_role1; show views; use warehouse <warehouse_name>; select * from paid_sensitive_data;