高度な列レベルセキュリティのトピック

このトピックでは、列レベルのセキュリティマスキングポリシーに関連する2つの高度な概念についてその概要を説明します。

  1. ロール階層。

  2. 複数の コンテキスト関数 を使用します。

コンテキスト関数およびロール階層

列レベルのセキュリティでは、マスキングのポリシー本文の条件で コンテキスト関数 を使用して、ユーザーにデータを表示する権限があるかどうかを強制できます。ユーザーが特定の SQL ステートメントでデータを表示できるかどうかを判断するには、次の点を考慮してください。

現在のセッション

CURRENT_ROLE を使用したマスキングポリシー条件では、現在のセッションで使用されているロールがターゲットになります。

実行中のロール

INVOKER_ROLE を使用したマスキングポリシー条件では、SQLステートメントの実行ロールがターゲットになります。

ロール階層

ポリシー条件でロール階層が必要な場合は、 IS_ROLE_IN_SESSION を使用します。

マスキングポリシー条件で指定されたロール(例: analyst カスタムロール)が CURRENT_ROLE または INVOKER_ROLE ロール階層において権限が低いロールであるかどうかを確認します。その場合、 CURRENT_ROLE または INVOKER_ROLE 関数によって返されるロールは、指定されたロールの権限を継承します。ロール階層と権限継承の詳細については、以下をご参照ください。

次のテーブルは、現在のセッション、実行中のロール、およびロール階層を対象とするマスキングポリシーの一般的なコンテキスト関数を示しています。

コンテキスト関数

説明

CURRENT_ROLE

現在のセッションで使用中のロールの名前を返します。

IS_ROLE_IN_SESSION

セッション内のユーザーの現在のロール(つまり、 CURRENT_ROLE によって返されるロール)が指定されたロールの権限を継承する場合は、TRUE を返します。

INVOKER_ROLE

実行中ロールの名前を返します。

IS_GRANTED_TO_INVOKER_ROLE

INVOKER_ROLE 関数によって返されたロールが、関数の呼び出されるコンテキストに基づいて引数で指定されたロールの権限を継承する場合は、TRUE を返します。

INVOKER_SHARE

INVOKER_SHARE 関数が呼び出されたテーブルまたはビューに直接アクセスした共有の名前を返します。

CURRENT_ROLE および IS_ROLE_IN_SESSION を使用する

CURRENT_ROLEを使用したマスキングポリシー条件では、現在のセッションがターゲットになり、SQLステートメントの実行コンテキストによる影響を受けません。

ポリシー条件でロールのアクティブ化とロール階層が必要な場合は、 IS_ROLE_IN_SESSION を使用します。

次のマスキングポリシー本文を検討してください。

CREATE OR REPLACE MASKING POLICY mask_string AS
(val string) RETURNS string ->
CASE
  WHEN CURRENT_ROLE() IN ('ANALYST') THEN val
  ELSE '********'
END;
Copy

特定のユーザーに、このマスキングポリシーが設定されている列のデータを表示する権限があるかどうかを確認するには、次のステップを実行します。

  1. マスキングポリシーの条件を評価します。

  2. 指定されたロールが CURRENT_ROLE 階層にあるかどうかを確認します。

  3. 検証するテストクエリを実行します。

ステップ1: マスキングポリシーの条件を評価する

次のテーブルは、マスキングポリシー本文の条件の結果をまとめたものです。

コンテキスト

マスクされていないデータを表示する

マスクされたデータを表示する

CURRENT_ROLE = ANALYST カスタムロール。

CURRENT_ROLE は、階層内の ANALYSTカスタムロールにあります。

CURRENT_ROLE は、 ANALYSTカスタムロール階層にありません。

次に、ロール階層を評価します。

ステップ2: 指定されたロールが CURRENT_ROLE 階層にあるかどうかを確認する

CURRENT_ROLE が ANALYST カスタムロールではないと想定して、 CURRENT_ROLE が ANALYST カスタムロールに付与された権限を継承しているかどうかを確認します。

次のステートメントを実行します。

SELECT IS_ROLE_IN_SESSION('ANALYST');
Copy
+-------------------------------+
| IS_ROLE_IN_SESSION('ANALYST') |
+-------------------------------+
| FALSE                         |
+-------------------------------+

SnowflakeはFALSEを返すため、CURRENT_ROLEはANALYSTカスタムロールに付与された権限を継承しません。したがって、この例のマスキングポリシー本文に基づいて、ユーザーに固定マスク値が表示されます。

ステップ3: テストクエリを実行して検証する

この例のマスキングポリシーがその列に適用されている列でクエリを実行し、固定マスク値がユーザーに表示されることを検証します。

USE ROLE analyst;

SELECT * FROM mydb.mysch.mytable;
Copy

INVOKER_ROLE を使用する

INVOKER_ROLE を使用したマスキングポリシー条件では、 SQL ステートメントの実行コンテキストがターゲットになります。

次のテーブルは、実行コンテキストと、マスキングポリシー条件で INVOKER_ROLE が返す値をまとめたものです。

コンテキスト

評価されるロール

ユーザー

CURRENT_ROLE

テーブル

CURRENT_ROLE。

ビュー

ビュー所有者ロール。

UDF

UDF 所有者ロール。

呼び出し元権限を持つストアドプロシージャ

CURRENT_ROLE。

所有者権限を持つストアドプロシージャ

ストアドプロシージャ所有者ロール。

タスク

タスク所有者ロール。

ストリーム

指定された ストリーム をクエリするロール。

テーブル上の単一のビューに適用される次のマスキングポリシー本文を検討してください。

CREATE OR REPLACE MASKING POLICY mask_string AS
(val string) RETURNS string ->
CASE
  WHEN INVOKER_ROLE() IN ('ANALYST') THEN val
  ELSE '********'
END;
Copy

列でクエリを実行している特定のユーザーにデータ表示権限があるかどうかを確認するには、次のステップを実行します。

  1. マスキングポリシーの条件を評価します。

  2. 指定されたロールがビューを所有しているかどうかを確認します。

  3. 検証するテストクエリを実行します。

ステップ1: マスキングポリシーの条件を評価する

次のテーブルは、ビュー列に適用されたマスキングポリシー本文の条件の結果をまとめたものです。

コンテキスト

マスクされていないデータを表示する

マスクされたデータを表示する

analyst カスタムロールは、ビュー所有者ロールです。

analyst カスタムロールは、ビュー所有者ロールではありません。

次に、 ANALYST カスタムロールがビューを所有しているかどうかを確認します。

ステップ2: ANALYST ロールがビューを所有しているかどうかを確認する

ANALYST カスタムロールがビューを所有しているかどうかを確認するには、次のステートメントを実行します。

SHOW GRANTS OF ROLE analyst;
Copy

analyst カスタムロールがビューを所有している場合は、ビュー列に対するクエリではマスクされていないデータが出力されます。

analyst カスタムロールがビューを所有していない場合は、マスクされたデータが表示されます。

ステップ3: テストクエリを実行して検証する

ビュー列でクエリを実行して、 ANALYST カスタムロールにマスクされたデータとマスクされていないデータのどちらが表示されるかを確認します。

USE ROLE analyst;

SELECT * FROM mydb.mysch.myview;
Copy

IS_GRANTED_TO_INVOKER_ROLE を使用する

IS_GRANTED_TO_INVOKER_ROLE関数は、条件の一部としてマスキングポリシー本文に渡すことができます。関数がTRUEと評価されると、関数引数のロールはINVOKER_ROLE階層にあります。

社会保障番号(SSNs)のビュー列に適用される次のマスキングポリシー本文を検討してください。

CREATE OR REPLACE MASKING POLICY mask_string AS
(val string) RETURNS string ->
CASE
  WHEN IS_GRANTED_TO_INVOKER_ROLE('PAYROLL') THEN val
  WHEN IS_GRANTED_TO_INVOKER_ROLE('ANALYST') THEN REGEXP_REPLACE(val, '[0-9]', '*', 7)
  ELSE '*******'
END;
Copy

ビュー列でクエリを実行している特定のユーザーにデータ表示権限があるかどうかを確認するには、次のステップを実行します。

  1. マスキングポリシーの条件を評価します。

  2. 指定されたロールが呼び出し元ロール階層にあるかどうかを確認します。たとえば、ポリシーがビューに設定されている場合、 TRUE を返すには、指定されたロールがビュー所有者のロール階層になければなりません。詳細については、 使用上の注意 をご参照ください。

  3. 検証するテストクエリを実行します。

ステップ1: マスキングポリシーの条件を評価する

次のテーブルは、ビュー列と、ビュー列で表示するデータに適用されたマスキングポリシー本文の条件の結果をまとめたものです。

コンテキスト

マスクされていないデータ

部分的にマスクされたデータ

マスクされたデータ

payroll カスタムロールは、ビュー所有者ロール階層にあります。

analyst カスタムロールは、ビュー所有者ロール階層にあります。

payrollanalyst のカスタムロールのいずれも、ビュー所有者の階層にはありません。

ステップ2: 指定されたロールがビュー所有者ロール階層にあるかどうかを確認する

payroll または analyst のカスタムロールのいずれかがビュー所有者階層にある場合は、ビュー所有者ロールで SHOW GRANTS コマンドを実行すると、ロール階層を検証できます。例:

SHOW GRANTS TO ROLE view_owner_role;
Copy

SQL ステートメントの出力には、ビュー所有者ロールに payroll または analyst のカスタムロールが付与されているかどうかが示されます。

ステップ3: テストクエリを実行して検証する

この例のマスキングポリシーがその列に適用されている列でクエリを実行し、ユーザーのビュー列にどのようにデータを表示されるかを検証します。

USE ROLE payroll;

SELECT * FROM mydb.mysch.myview;

USE ROLE analyst;

SELECT * FROM mydb.mysch.myview;
Copy

マスキングポリシーで CURRENT_ROLE と INVOKER_ROLE を組み合わせる

Snowflakeは、クエリを実行するセッション(つまり、 CURRENT_ROLE)とクエリを実行するオブジェクト所有者(例: ビュー所有者、 INVOKER_ROLE)で使用されているロールを区別するために、単一のマスキングポリシーの作成をサポートしています。このタイプのユースケースは、通常、マスクする値のセットと、マスクされていない値を表示できる比較的少数のオーディエンス(たとえば、 analyst カスタムロールを持つユーザー)を決定するよりも複雑です。

マスキングポリシー内のハッシュ、暗号化、および暗号化関数

ハッシュ および 暗号化/チェックサム は、機密データをマスクするためのマスキングポリシーで使用できます。

これらの関数のいずれかを マスキングポリシー に実装する前に、これらの関数のユースケースに JOIN 操作が含まれるかどうかを検討することが重要です。特定のマスキングポリシーの実装では、テーブルとビューを含むクリエイティブなJOIN操作により、次の制限に基づいてマスクされた値がその実際の値にリバースエンジニアリングされる可能性があります。

  • 実際の値(つまり入力)と、値の総数に基づくハッシュ値、暗号化値、またはチェックサム値(つまり、出力、値の範囲)は1対1の表現でないため、競合が発生する可能性があります。

1対1の表現は、入力値の総数が変換する出力値の平方根に達するまで発生する可能性が高くなります。

たとえば、ハッシュへの出力値が144個の場合、最初の12個の値(つまり、144^(1/2) -- 144の平方根)が一意であり、残りの132個の値に対して競合が発生する可能性があると予期することは妥当です。この制限とその結果が発生する可能性があるため、JOIN操作で値が使用される可能性のあるマスキングポリシーでは、ハッシュ関数、暗号化関数、またはチェックサム関数を使用しないことをお勧めします。

ちなみに

マスキングポリシーのユースケースがセキュリティ強化のために競合回避を優先する場合は、 外部トークン化 を実装します。入力値と出力値の表現は常に1対1であるため、トークン化によって競合が発生することはありません。

トークン化が不可能な場合、考えられる回避策の1つは、クエリを実行するセッションロール(つまり CURRENT_ROLE)とクエリを実行するオブジェクト所有者(つまり INVOKER_ROLE)を区別するマスキングポリシーを実装することです。

たとえば、次のマスキングポリシーは、従業員情報へのアクセスを規制するために、2つの異なるカスタムロール CSR_EMPL_INFO と DBA_EMPL_INFO を想定しています。

CREATE OR REPLACE MASKING POLICY mask_string AS
(val string) RETURNS string ->
CASE
    WHEN CURRENT_ROLE() IN ('CSR_EMPL_INFO') THEN HASH(val)
    WHEN INVOKER_ROLE() IN ('DBA_EMPL_INFO') THEN val
    ELSE null
END;
Copy

ポリシーがテーブルに適用されると、ポリシーはテーブルから作成されたすべてのビューに継承されます。カスタムロール dba_empl_info がこのテーブルから作成されたビューを所有している場合(つまり、ビューに対する OWNERSHIP 権限を持っている場合)にビューをクエリすると、このカスタムロールを持つユーザーのみが実際の値を表示できます。 csr_empl_info カスタムロールを持つユーザーには、クエリがテーブルまたはビューのどちらで行われたかに関係なく、常にハッシュ値が表示されます。他のすべてのユーザーには NULL が表示されます。