💡
Snowflakeでリーダーアカウントに閲覧許可を出すProcedureを作ってみた
Snowflakeにおいてデータシェアリングを行う機能があります。
今回はお客様に、ユーザは発行できないが、リーダーアカウントでDWHのなかを全部見れる(=SELECTできる)状態にしたい!
ってことで、Snowflake Scriptingを使って、実現してみました。
使い方
- call public.grant_share_reader_account('[SCHEMA_NAME]');
- 指定スキーマにUSAGEを付与
- 指定スキーマのTABLE全部にSELECTを付与
- 指定のスキーマ以下のVIEWについて
- SCURE VIEWにする
- [READER_ACCOUNT_NAME]へSHARE設定する
- 上位ROLE( ACCOUNTADMIN やカスタムロールの最上位ロール)で実施する
READER_ACCOUNTに閲覧許可を出す際に、TABLEについては、「ALL TABLE」はできるのですが、「FUTRURE」がないため、新しいVIEW (やTABLE?)が生成されると、追加でSHARE設定をしなければならないのです。
本来ならば、一つ一つのVIEWやTABLEについて、精査してGRANT TO SHARE を発行すべきなのですが、今回は常に全部見れる状態に!
というオーダなので、こちらをTASKに設定して、一日一回発行する形にしよかなっておもってます。
ハマった点
- カーソルの設定で変数を叩き込む際に ? 演算子を使う
- view_names cursor for select table_name from information_schema.views where TABLE_SCHEMA = ?;
- ?演算子に埋め込むのの open [CURSOL_NAME] using ([変数名]) を使う
ってしないと怒られました。
-- use account_admin;
create or replace procedure public.grant_share_reader_account(schema_name string)
returns varchar not null
language sql
as
$$
declare
role_name := '[READER_ACCOUNT_NAME]';
view_names cursor for select table_name from information_schema.views where TABLE_SCHEMA = ?;
begin
let all_command string := '';
-- schema
let schema_command string := 'grant usage on schema ' || :schema_name || ' to share ' || :role_name;
execute immediate schema_command;
-- tables
let tables_command string := 'grant select on all tables in schema ' || :schema_name || ' to share ' || :role_name;
execute immediate tables_command;
-- views
open view_names using (schema_name);
for view_name in view_names do
let alter_secure_command string := 'alter view ' || :schema_name || '.' || view_name.table_name || ' set secure';
execute immediate alter_secure_command;
let command string := 'grant select on view ' || :schema_name || '.' || view_name.table_name || ' to share ' || :role_name;
all_command := all_command || ', ' || command;
execute immediate command;
end for;
return :schema_name || '-' || :role_name || ':' || all_command;
end
$$;
call public.grant_share_reader_account('SCHEMA_1');
Discussion