使用安全对象控制数据访问

为确保共享数据库中的敏感数据不会暴露给使用者账户中的用户,Snowflake 强烈建议 共享 安全视图 和/或 安全 UDFs,而非直接共享表。

此外,为保证最佳性能,尤其是在超大表中共享数据时,我们建议在基表上为安全对象定义 <label-clustering-keys>` 群集密钥 :ref:`

本主题介绍在基表中为共享安全对象使用群集密钥,并提供了与使用者账户共享安全视图的详细步骤说明。此外还提供了针对数据提供商和使用者的示例脚本。

备注

共享安全对象的说明与共享表的说明基本相同,只是增加了以下对象:

  • 包含基表的“私有”架构和包含安全对象的“公共”架构。共享的只有公共架构和安全对象。

  • 一个“映射表”(同样位于“私有”架构中),只有在您希望与多个使用者账户共享基表中的数据,以及与特定账户共享表中的特定行时,才需要此映射表。

本主题内容:

为共享数据使用群集密钥

在超大(即大小为数 TB)的表上,群集密钥可提供显著的查询性能优势。通过在共享安全视图或安全 UDFs 中使用的基表上定义一个或多个群集密钥,即可确保使用者账户中的用户在使用这些对象时不会受到负面影响。

在为表选择用作群集密钥的列时,请注意一些重要的 注意事项

设置和任务示例

在这些示例说明中,我们假设数据提供商账户中有一个名为 mydb 的数据库,并且有两个架构,分别是 privatepublic。如果数据库和架构不存在,则应先创建它们,然后再继续操作。

第 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。将此会话参数设置为您想模拟其访问权限的使用者账户名称。然后可查询视图,并查看该使用者账户中的用户将看到的结果。

第 4 步:创建共享

  1. 创建 共享

    要创建共享,必须使用 ACCOUNTADMIN 角色,或者获授全局 CREATE SHARE 权限的角色。要向共享授予对象,该角色还必须符合以下条件之一:

    • 具有共享数据库 OWNERSHIP 权限的角色。

    • 具有 :doc:`数据库 WITH GRANT OPTION 的 USAGE 权限 </sql-reference/sql/grant-privilege>`的角色。例如:

  2. 将数据库 (mydb)、架构 (public) 和安全视图 (paid_sensitive_data) 添加到共享。您可以选择通过数据库角色将这些对象的权限添加到共享,或者 将这些对象的权限直接授予共享。有关这些选项的更多信息,请参阅 选择如何共享数据库对象

  3. 确认共享的内容。在最基本的层面上,您应使用 SHOW GRANTS 命令来确认共享中的对象具有必要的权限。

    请注意,安全视图 paid_sensitive_data 在命令输出中显示为表的形式。

  4. 向共享添加一个或多个账户。

脚本示例

以下脚本说明了如何执行上一节中介绍的所有任务:

  1. 在“私有”架构中创建两个表,并在第一个表中填充三家不同公司(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>');
    
    Copy
  2. 在“公共”架构中创建安全视图。此视图使用第二个表中的映射信息,按账户筛选第一个表中的股票数据:

    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;
    
    Copy
  3. 使用 ACCOUNTADMIN 角色创建共享。

    use role accountadmin;
    
    create or replace share mydb_shared
      comment = 'Example of using Secure Data Sharing with secure views';
    
    show shares;
    
    Copy
  4. 将对象添加到共享。您可以选择通过数据库角色将这些对象的权限添加到共享(选项 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;
    
    Copy
  5. 将账户添加到共享。

    /* 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>;
    
    Copy

脚本示例(面向使用者)

使用者可使用以下脚本来创建数据库(从上述脚本中创建的共享),并在所获得的数据库中查询安全视图:

  1. 通过从共享创建数据库,将共享数据库引入您的账户。

    /* 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;
    
    Copy
  2. 向您账户中的其他角色授予数据库权限(例如 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;
    
    Copy
  3. 使用 CUSTOM_ROLE1 角色查询您创建的数据库中的视图。请注意,会话中必须在使用有效的仓库才能执行查询。在 USE WAREHOUSE 命令中,将 <warehouse_name> 替换为账户中一个仓库的名称。CUSTOM_ROLE1 角色必须具有仓库的 USAGE 权限:

    use role custom_role1;
    
    show views;
    
    use warehouse <warehouse_name>;
    
    select * from paid_sensitive_data;
    
    Copy
语言: 中文