行アクセスポリシーの使用¶
このトピックでは、行アクセスポリシーの概要を説明します。
このトピックの内容:
行アクセスポリシーの実装¶
次のサブセクションでは、行アクセスポリシー実装方法の2つの例を示します。
マッピングテーブルルックアップを使用した一般的な行アクセスポリシー。
既存の行アクセスポリシーのサブクエリをメモ化可能な関数に置き換えて、クエリのパフォーマンスを向上させます。
例: マッピングテーブルルックアップ¶
次のステップは、行アクセスポリシー権限を設定し、テーブルとビューに行アクセスポリシーを追加するための代表的なガイドです。
これらのステップでは、次を前提としています。
管理アプローチは集中型です。
行アクセスポリシーのユースケースにハイブリッド型または分散型の管理アプローチが含まれている場合のロールと権限の代表的な分布については、 行アクセスポリシーの管理 をご参照ください。
代表的な使用例: マッピングテーブルを使用してクエリ結果をフィルターする と同様に、マッピングテーブルが必要です。
次のステップでは、 CURRENT_ROLE コンテキスト関数を使用して、ユーザーにクエリ結果に行が表示されるかどうかを判断します。一方、代表的なユースケースでは、ユーザーの名(つまり、 CURRENT_USER)に焦点を当てます。
ロールのアクティブ化とロール階層が重要な場合、ポリシー条件で IS_ROLE_IN_SESSION コンテキスト関数を使用することをお勧めします。ポリシーの例については、IS_ROLE_IN_SESSION 関数の 例 セクションを参照してください。
コンテキスト関数が異なっていても、マッピングテーブルを使用して行アクセスポリシーを実装するための全体的なプロセスは同様です。
SECURITYADMIN システムロールは、行アクセスポリシーを管理および実装するための権限をカスタムロールに付与します。
実稼働環境で下位の権限のカスタムロール(例:
database_admin
、finance_admin
)を優先して、上位の権限のロール(つまり、 SECURITYADMIN または ACCOUNTADMIN)を使用したくない場合は、下位の権限のロールに、行アクセスポリシーを管理および実装するために必要な権限があるかどうかを確認します。詳細については、 行アクセスポリシーの権限 および DDL コマンド、操作、および権限の概要 をご参照ください。
行アクセスポリシーによって保護されるテーブルを作成するための個別のステップ(ステップ1)と、行アクセスポリシーをテーブルに追加するステップ(ステップ5)があります。行アクセスポリシーがすでに存在することを前提として、テーブルの作成時に行アクセスポリシーをテーブルに追加することができます。構文の詳細については、 CREATE TABLE をご参照ください。
ステップ1: データのテーブルを作成する¶
販売データのテーブルを作成します。
create table sales (
customer varchar,
product varchar,
spend decimal(20, 2),
sale_date date,
region varchar
);
ステップ2: マッピングテーブル、カスタムロールを作成し、 SELECT 権限を付与する¶
security
スキーマで、 代表的な例 に示すようにマッピングテーブルを作成します。このテーブルは、営業部長が表示できる sales
テーブルの行を定義します。
create table security.salesmanagerregions ( sales_manager varchar, region varchar );
次に、セキュリティ管理者が mapping_role
カスタムロールを作成し、カスタムロールに SELECT 権限を付与します。この付与により、カスタムロールを持つユーザーはマッピングテーブルをクエリできます。
use role securityadmin; create role mapping_role; grant select on table security.salesmanagerregions to role mapping_role;
ステップ3: 行アクセスポリシーを作成する¶
スキーマ所有者のロールを使用して、次の2つの条件で行アクセスポリシーを作成します。
sales_executive_role
カスタムロールを持つユーザーは、すべての行を表示できます。sales_manager
カスタムロールを持つユーザーは、salesmanagerregions
マッピングテーブルに基づいて行を表示できます。
スキーマ所有者のロールには、自動的に CREATE ROW ACCESS POLICY 権限が付与されます。他のロールにより行アクセスポリシーを作成する必要がある場合、スキーマ所有者ロールは、他のロールに CREATE ROW ACCESS ポリシー権限を付与できます。
use role <schema_owner_role>;
create or replace row access policy security.sales_policy as (sales_region varchar) returns boolean ->
'sales_executive_role' = current_role()
or exists (
select 1 from salesmanagerregions
where sales_manager = current_role()
and region = sales_region
)
;
条件:
security.sales_policy
Security
スキーマの行アクセスポリシーの名前。as (sales_region varchar)
行アクセスポリシーの署名。
署名は、マッピングテーブルの属性とデータ型を指定します。戻り値は、行アクセスポリシーが追加されたテーブルまたはビューの特定の行に、ユーザーがアクセスできるかどうかを決定します。
returns boolean ->
行アクセスポリシーの適用を指定します。
行アクセスポリシーの
<expression>
は、右矢印(つまり、->
)の直後にあります。式には、ブール値の SQL 式を使用できます。Snowflakeは、 UDFs を呼び出す式、外部関数、およびサブクエリを使用する式をサポートしています。
'sales_executive_role' = current_role()
sales_executive_role
カスタムロールを持つユーザーがデータを表示できるようにする、行アクセスポリシー式の最初の条件。or exists (select 1 from salesmanagerregions where sales_manager = current_role() and region = sales_region)
サブクエリを使用する行アクセスポリシー式の2番目の条件。
サブクエリでは、
{salesmanagerregions}
マッピングテーブルにリストされているリージョンを指定するために、データに対して実行されたクエリで CURRENT_ROLE がsales_manager
カスタムロールである必要があります。
ちなみに
ポリシーで保護されたテーブルでクエリのパフォーマンスを向上させるには、 EXISTS
句のマッピングテーブルルックアップのサブクエリを メモ化可能な関数 に置き換えます。
詳細については、 メモ化可能な関数の例 (このトピック内)をご参照ください。
ステップ4: カスタムロールに権限を付与する¶
SECURITYADMIN システムロールを使用して、次の2つのステートメントを実行します。
grant ownership on row access policy security.sales_policy to mapping_role;
grant apply on row access policy security.sales_policy to role sales_analyst_role;
これらの2つの GRANT <権限> ステートメントには次の効果があります。
ポリシーの所有権は、 SECURITYADMIN システムロールに依存しません。ポリシーは 所有者の権限 で実行され、より権限のある SECURITYADMIN システムロールではないため、クエリの実行時にSnowflakeはカスタムロールに付与された権限を使用します。このアプローチは、最小権限の原則をサポートします。
sales_analyst_role
カスタムロールは、必要に応じてテーブルから行アクセスポリシーを追加またはドロップできます。
ステップ5: 行アクセスポリシーをテーブルに追加する¶
Snowflakeの任意のテーブルまたはビューは、一度に最大1つの行アクセスポリシーをサポートできます。
行アクセスポリシーを Sales
データテーブルのリージョン列に追加(つまり、バインド)します。
use role securityadmin;
alter table sales add row access policy security.sales_policy on (region);
ステップ6: 保護されたテーブルデータをロールがクエリできるようにする¶
保護された sales
データに対する SELECT 権限を sales_manager_role
カスタムロールに付与します。
grant select on table sales to role sales_manager_role;
ステップ7: ポリシーをテストする¶
販売データが Sales
データに入力されたら、行アクセスポリシーをテストします。
use role sales_manager_role;
select product, sum(spend)
from sales
where year(sale_date) = 2020
group by product;
例: ポリシーのサブクエリをメモ化可能な関数に置き換える¶
この例の手順では、行アクセスポリシー条件のマッピングテーブルルックアップごとに メモ化可能な関数 を作成します。各 EXISTS
句のサブクエリは、マッピングテーブルルックアップを指定します。テーブルにはそれぞれ regions
、 customers
、および products
という名前が付けられます。
CREATE or replace ROW ACCESS POLICY rap_NO_memoizable_function AS (region_id number, customer_id number, product_id number) RETURNS BOOLEAN -> exists(select 1 from regions where id = region_id) or exists(select 1 from customers where id = customer_id) or exists(select 1 from products where id = product_id) ;
次の手順では、 rap_admin
カスタムロールが行アクセスポリシーを作成できる(つまり、SCHEMA に対する CREATE ROW ACCESS POLICY 権限がある)と仮定します。
次の手順を実行して、それぞれの行アクセスポリシーのマッピングテーブルルックアップをメモ化可能な関数に置き換えます。
メモ化可能な関数を管理するために、
functions_admin
という名前のカスタムロールを作成します。use role useradmin; create role functions_admin;
次の権限を
functions_admin
ロールに付与して、governance.functions
という名前の既存のスキーマにメモ化可能な関数を作成できるようにします。use role securityadmin; grant usage on database governance to role functions_admin; grant usage on schema governance.functions to role functions_admin; grant create function on schema governance.functions to role functions_admin;
行アクセスポリシーの
EXISTS
サブクエリ句ごとにメモ化可能な関数を作成します。メモ化可能な各関数定義は、同じ形式を取ります。簡潔にするために、関数の例を1つだけ示します。use role functions_admin; use schema governance.functions; create or replace function allowed_regions() returns array memoizable as 'select array_agg(id) from regions';
CREATE ROW ACCESS POLICY ステートメントを使用して、サブクエリをメモ化可能な関数に置き換える新しい行アクセスポリシーを定義します。
新しい行アクセスポリシーを使用すると、ポリシーがメモ化可能な関数を使用する場合と使用しない場合に、保護されたテーブルでクエリをテストして、ポリシー条件でメモ化可能な関数を使用した場合のパフォーマンスへの影響を定量化できます。
use role rap_admin; create or replace row access policy rap_with_memoizable_function as (region_id number, customer_id number, product_id number) returns boolean -> array_contains(region_id, allowed_regions()) or array_contains(customer_id, allowed_customers()) or array_contains(product_id, allowed_products()) ;