ユーザーに返されるデータを制御するために、SYSADMIN.setPermissions システムプロシージャを使用して、行ベースのパーミッションとカラムマスキングを一緒に、または個別に設定できます。

Row-based Permissions

完全修飾されたテーブル、ビュー、またはプロシージャに対するパーミッションは、条件を指定することができます。以下に留意点を挙げます:

  • 条件はユーザークエリレベルだけでなく、常に適用されます;
  • サブクエリを介して参照されるテーブルとビューには、行ベースのフィルタとカラムマスキングが適用されます;
  • 条件は、テーブルまたはビューのカラムを参照する有効なSQL 文であれば何でも構いません;
  • この条件は、行ベースのフィルタとして、またINSERT / UPDATE操作のチェック付き制約として機能します;
  • この条件は、テーブルやビューがクエリでどのように使用されるか(UNION、JOIN など)に関係なく存在します。

指定されたリソースに対するUPDATE / DELETE / SELECT / WHERE 句に対して条件が連結的に適用されるため、これらのクエリは条件を通過した行のサブセットにのみ影響します。INSERT / CHANGE の値が、INSERT / UPDATE が成功するための条件(TRUE への評価)に適合するように、影響を受ける物理テーブルに対する挿入と更新がさらに検証されます。INSERT / UPDATE 制約チェックを無効にするには、条件制約フラグをFALSE に設定します。

Currently, conditions on source tables acting as check constraints must not contain correlated subqueries.

複数の適用可能なロールにまたがって、複数の条件が同じリソースに適用される場合、条件は OR を介して分離的に累積されます。これは、TRUE  条件でパーミッションを付与すると、このロールを持つユーザは指定されたリソースのすべての行を見ることができることを意味します。

NULL 値の取り扱いは特定のデータロールの実装者次第であり、カラムがNULL 許容であるときにNULL 値が許可されることを保証するためにISNULL の確認を必要とするかもしれません。

以下に、行ベースのパーミッション設定の例を示します:

1. この例では、col1 > 10 の場合、test_schema.test_view1  の行を表示します:

CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_schema.test_view1',
"permissions" => 'CRUDEAL',
"condition" => 'col1 > 10'
);;

2. この例では、MOD(d, 100) IN (SELECT a FROM test_tables_pg.test_a) の場合、test_tables_pg.test_d  の行を表示します:

CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_tables_pg.test_d',
"permissions" => 'CRUDEAL',
"condition" => 'MOD(d, 100) IN (SELECT a FROM test_tables_pg.test_a)'
);;

Row-based Permissions and Materialization

行ベースの権限は、それらの権限がマテリアライズされるオブジェクトに直接割り当てられている場合にのみ、マテリアライズドテーブルに適用されます。マテリアライズドテーブルは、マテリアライゼーションを実行するユーザに代わって作成される静的スナップショットとして機能するため、親オブジェクトに割り当てられた行ベースの権限は無視されます。このスナップショットは、マテリアライズされるオブジェクトだけでなく、ビュー定義で参照されるすべての基本テーブルおよびビューを含むクエリプランのブランチ全体を完全を置き換えます。

例えば、col_a が10より大きい行のみを返す行レベル権限を持つロール(ROLE_A)が:

CALL "SYSADMIN.setPermissions"(
"role_name" => 'ROLE_A',
"resourceName" => 'test_tables.base_table',
"permissions" => 'CRUDEAL',
"condition" => 'col_a > 10'
) ;;

以下のテーブルにあるとします:

CREATE TABLE "test_tables.base_table" ("col_a" INTEGER) ;;

ROLE_A を持つユーザー(USER_A)は、以下のビューを作成します:

CREATE VIEW "views.view_child" AS SELECT COUNT("col_a") FROM "test_tables.base_table" ;;

USER_A がマテリアライゼーションを伴わずにview_child にクエリする場合、行レベルパーミッションがクエリプランで強制され、col_a > 10 の行のみが結果に含まれるようになります。ただし、管理者ユーザがview_child をマテリアライズすると、システムは管理者に代わってbase_table のすべての行を含むマテリアライズドテーブルを作成し、ROLE_A に適用された行ベースのパーミッションは無視されます。マテリアライズドテーブルはクエリプランの対応するブランチを完全に置き換えるので、base_table を含む元のビュー定義で参照されていたオブジェクトは、view_child をクエリする際に考慮されなくなります。その結果、base_table(または元のクエリ定義内の他のオブジェクト)に割り当てられた行ベースの権限は、マテリアライズドビューには適用されません。

Column Masking

完全修飾されたテーブル、ビュー、またはプロシージャ列に対するPermissionは、マスクと、オプションで条件を指定することもできます。クエリが送信されると、ロールがチェックされ、関連するマスクまたは条件情報が組み合わされて検索ケース式が形成され、アクセスに応じて返されたであろう値をマスクします。結果としてのマスクは、ユーザークエリレベルだけでなく、常に適用されます。条件と式は、テーブルの列、ビュー、またはプロシージャを参照する有効な SQL 文であれば何でもかまいません。

列マスキングは、SELECT ステートメントに対してのみ適用され、2巡目では、行ベースのセキュリティの後に適用されます。しかし、ビューとソーステーブルの両方が行とカラムベースのセキュリティを持つ可能性があるため、実際のビューレベルのマスキングはソースレベルのマスキングの上で行われる可能性があります。マスクとともに条件が指定された場合、有効なマスク式は行のサブセットのみに影響します: CASE WHEN condition THEN mask ELSE column。そうでない場合、条件はTRUE であると仮定され、マスクがすべての行に適用されることを意味します。

複数のロールが1つの列に対してマスクを指定する場合、マスクの順序引数は、より大きな検索された大文字小文字式の一部として、最も高いものから最も低いものへの優先順位を決定します。例えば、デフォルトの次数が0のマスクと次数が1のマスクは、CASE WHEN condition1 THEN mask1 ELSE CASE WHEN condition0 THEN mask0 ELSE column END END のように結合されます。

以下はその例です:

1. この例では、col2 > 3 の場合col2 の代わりに'1111' を表示するよう求めています:

CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_schema.colMask_view1',
"permissions" => 'CRUDEAL'
);;
 
CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_schema.colMask_view1.col2',
"permissions" => 'CRUDEAL',
"condition" => 'col2 > 3',
"mask" => 1111,
"maskOrder" => 1
);;

2. この例はマスク順序を示しています。col2 を CASE WHEN col2 <= 2 THEN 2222 ELSE CASE WHEN col2 >= 2 THEN 1111 ELSE col2 END END として表示するよう求めています:

CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_schema.colMask_view1',
"permissions" => 'CRUDEAL'
);;
 
CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-1',
"resourceName" => 'test_schema.colMask_view1.col2',
"permissions" => 'CRUDEAL',
"condition" => 'col2 >= 2',
"mask" => 1111,
"maskOrder" => 1
);;
 
CALL "SYSADMIN.setPermissions"(
"role_name" => 'user-role-2',
"resourceName" => 'test_schema.colMask_view1.col2',
"permissions" => 'CRUDEAL',
"condition" => 'col2 <= 2',
"mask" => 2222,
"maskOrder" => 2
);;