보안 오브젝트를 사용하여 데이터 액세스 제어하기

공유 데이터베이스의 민감한 데이터가 컨슈머 계정의 사용자에게 노출되지 않도록 하기 위해, Snowflake는 테이블을 직접 공유하는 대신 보안 뷰 및/또는 보안 UDFs 를 공유하는 것을 적극 권장합니다.

또한, 최적의 성능을 위해 특히 매우 큰 테이블에서 데이터를 공유하는 경우에는 보안 오브젝트에 대한 기본 테이블에 클러스터링 키 를 정의하는 것이 좋습니다.

이 항목에서는 공유 보안 오브젝트에 대한 기본 테이블의 클러스터링 키 사용에 대해 설명하고 컨슈머 계정과 보안 뷰를 공유하기 위한 단계별 지침을 제공합니다. 그리고 데이터 공급자와 컨슈머 모두를 위한 샘플 스크립트를 제공합니다.

참고

보안 오브젝트를 공유하기 위한 지침은 기본적으로 다음 오브젝트가 추가된 테이블 공유와 동일합니다.

  • 기본 테이블을 포함하는 “비공개” 스키마와 보안 오브젝트를 포함하는 “공용” 스키마. 공개 스키마와 보안 오브젝트만 공유됩니다.

  • 기본 테이블의 데이터를 여러 컨슈머 계정과 공유하고 테이블의 특정 행을 특정 계정과 공유하려는 경우에만 필요한 “매핑 테이블”(“비공개” 스키마에도 있음).

이 항목의 내용:

공유 데이터를 위한 클러스터링 키 사용하기

매우 큰(예: 몇 테라바이트 크기) 테이블에서 클러스터링 키는 상당한 쿼리 성능 이점을 제공합니다. 공유 보안 뷰 또는 보안 UDF에 사용되는 기본 테이블에 1개 이상의 클러스터링 키를 정의하여 이러한 오브젝트를 사용할 때 컨슈머 계정의 사용자가 부정적인 영향을 받지 않도록 합니다.

테이블의 클러스터링 키로 사용할 열을 선택하는 경우의 중요 고려 사항 에 유의하십시오.

샘플 설정 및 작업

이 샘플 지침에서는 이름이 mydb 인 데이터베이스가 데이터 공급자 계정에 있고 privatepublic 스키마 2개가 있는 것으로 가정합니다. 데이터베이스와 스키마가 없는 경우에는 생성한 후 진행해야 합니다.

1단계: 비공개 스키마에 데이터 및 매핑 테이블 만들기

mydb.private 스키마에 다음 테이블 2개를 생성하고 데이터를 채웁니다.

sensitive_data — 공유할 데이터와 계정별로 데이터 액세스를 제어하기 위한 access_id 열을 포함합니다.
sharing_accessaccess_id 열을 사용하여 공유 데이터와 데이터에 액세스할 수 있는 계정을 매핑합니다.

2단계: 공개 스키마에 보안 뷰 만들기

mydb.public 스키마에서 다음 보안 뷰를 생성합니다.

paid_sensitive_data — 계정에 따라 데이터를 표시합니다.

기본 테이블의 sensitive_data 열(access_id)은 뷰에 포함할 필요가 없음에 유의하십시오.

3단계: 테이블 및 보안 뷰의 유효성 검사

데이터가 계정별로 올바르게 필터링되었는지 확인하기 위해 테이블과 보안 뷰의 유효성을 검사합니다.

다른 계정과 공유할 보안 뷰의 유효성을 검사할 수 있도록 Snowflake는 SIMULATED_DATA_SHARING_CONSUMER 세션 매개 변수를 제공합니다. 액세스를 시뮬레이션할 컨슈머 계정의 이름으로 이 세션 매개 변수를 설정합니다. 그런 다음 뷰를 쿼리하고 컨슈머 계정의 사용자에게 표시되는 결과를 확인할 수 있습니다.

4단계: 공유 만들기

  1. 공유 를 생성합니다.

    공유를 생성하려면 ACCOUNTADMIN 역할 또는 전역 CREATE SHARE 권한이 부여된 역할을 사용해야 합니다. 또한 공유에 대한 권한을 오브젝트에 부여하려면 역할에 다음 중 하나가 있어야 합니다.

  2. 데이터베이스(mydb), 스키마(public), 보안 뷰(paid_sensitive_data)를 공유에 추가합니다. 데이터베이스 역할을 통해 이러한 오브젝트에 대한 권한을 공유에 추가하거나, 또는 오브젝트에 대한 권한을 공유에 직접 부여하는 옵션 중에서 선택할 수 있습니다. 이러한 옵션에 대한 자세한 내용은 데이터베이스 오브젝트 공유 방법 선택하기 섹션을 참조하십시오.

  3. 공유의 내용을 확인합니다. 가장 기본적인 수준에서 SHOW GRANTS 명령을 사용하여 공유의 오브젝트에 필요한 권한이 있는지 확인해야 합니다.

    보안 뷰 paid_sensitive_data 는 명령 출력에 테이블로 표시됩니다.

  4. 공유에 계정을 1개 이상 추가합니다.

샘플 스크립트

다음 스크립트는 이전 섹션에서 설명한 모든 작업을 수행하는 방법을 보여줍니다.

  1. ‘private’ 스키마에 테이블을 두 개 만들고 서로 다른 세 회사(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. ‘public’ 스키마에서 보안 뷰를 만듭니다. 이 뷰는 두 번째 테이블의 매핑 정보를 사용하여 계정별로 첫 번째 테이블의 주식 데이터를 필터링합니다.

    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)에 데이터베이스에 대한 권한을 부여합니다. GRANT 문은 데이터 컨슈머가 데이터베이스 역할을 사용하여 공유에 오브젝트를 추가했는지(옵션 1) 또는 오브젝트에 대한 권한을 공유에 직접 부여했는지에(옵션 2) 따라 다릅니다.

    /* 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 명령에서 <웨어하우스_이름>을 계정에 있는 웨어하우스 중 하나의 이름으로 바꿉니다. CUSTOM_ROLE1 역할에는 웨어하우스에 대한 USAGE 권한이 있어야 합니다.

    use role custom_role1;
    
    show views;
    
    use warehouse <warehouse_name>;
    
    select * from paid_sensitive_data;
    
    Copy