メインコンテンツまでスキップ

行フィルタリングと列マスキングの一般的なパターン

このページでは、ABACの行フィルタおよび列マスクポリシーを実装するための一般的なパターンについて説明します。全体的な概念については、 「属性ベースアクセス制御(ABAC)の基本概念」を参照してください。ポリシーの構文については、 「ABAC ポリシーの作成と管理」を参照してください。

キャスト対応のマスキング機能

Databricks 、ターゲットカラムのデータ型に一致するようにマスキング関数の出力を自動的にキャストします。 列マスクの自動型変換を参照してください。

以下のパターンは、キャストに対応したマスキング関数を設計するのに役立ちます。

キャスト可能な型を返します

列をマスクする場合、同じデータ型、またはそれにキャスト可能な型を返します。ポリシーの対象となる列のデータ型を確認し、関数の各分岐が互換性のある値を返すことを確認してください。

SQL
-- Succeeds: Masks a DOUBLE column, returns DOUBLE in every branch
CREATE FUNCTION mask_salary(salary DOUBLE, user_role STRING)
RETURNS DOUBLE
RETURN CASE
WHEN user_role IN ('admin', 'hr') THEN salary
WHEN user_role = 'manager' THEN ROUND(salary / 1000) * 1000
ELSE 0.0
END;

-- Fails: 'CONFIDENTIAL' cannot be cast to a DOUBLE column type
CREATE FUNCTION mask_salary_as_text(salary DOUBLE, user_role STRING)
RETURNS STRING
RETURN CASE
WHEN user_role IN ('admin', 'hr') THEN CAST(salary AS STRING)
ELSE 'CONFIDENTIAL'
END;

数値オーバーフローを回避する

マスク関数がターゲットカラムよりも広い数値型を受け入れて返す場合、結果は自動的に列の型にキャスト バックされます。 返された値がより狭い型の範囲を超えると、キャストがオーバーフローし、クエリが失敗します。 。

SQL
-- The target column is TINYINT (max 127). The input is upcast to BIGINT
-- for the function. Adding 1000 produces a BIGINT result that overflows
-- when cast back to TINYINT.
CREATE FUNCTION mask_score(score BIGINT)
RETURNS BIGINT
RETURN score + 1000;

複数の列タイプにはVARIANTを使用します

複数の列タイプに対応するVARIANTベースのマスキング関数を参照してください。

キャスト適合性テスト

異なるデータパターンを用いてマスキング機能をテストする。

SQL
SELECT CAST(mask_salary(salary, 'admin') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'manager') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'viewer') AS DOUBLE) FROM employees;

複数の列タイプに対応するVARIANTベースのマスキング関数

異なるデータ型の列 (たとえば、 INTDOUBLEDECIMAL(10,2)DECIMAL(15,5)など) をマスクする必要がある場合は、 VARIANT型を受け入れて返す単一のマスキング UDF を作成できます。Databricks 、ANSI SQL標準に従ってターゲットカラムのデータ型と一致するように列マスク関数の出力を自動的にキャストします。

このアプローチにより、必要なUDFとポリシーの数を削減できます。列の型ごとに個別のマスキング関数を作成する代わりに、1つの関数ですべての型を処理します。

複数の数値型を単一の関数でマスクする

数値精度ごとに個別のマスク関数を作成する代わりに、 VARIANT使用して単一の関数ですべてを処理できます。

SQL
CREATE FUNCTION mask_numeric(val VARIANT)
RETURNS VARIANT
DETERMINISTIC
RETURN 0::VARIANT;

この関数は0 VARIANTとして返します。Databricks Databricksこれをターゲットカラムの型に自動的にキャストします。 この機能を使用する単一の ABAC ポリシーは、各精度ごとに個別の関数を必要とせずに、 INTDOUBLE 、およびDECIMAL列をマスクできます。

関数内で型を明示的に保持したい場合は、型に基づいて分岐し、 schema_of_variant()を使用してそれぞれに適切なマスクされた値を返すことができます。

SQL
-- Use VARIANT to accommodate different data types
CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
WHEN schema_of_variant(data) = 'INT' THEN 0::VARIANT
WHEN schema_of_variant(data) = 'DATE' THEN DATE'1970-01-01'::VARIANT
WHEN schema_of_variant(data) = 'DOUBLE' THEN 0.00::VARIANT
ELSE NULL::VARIANT
END;

構造体の列を VARIANT でマスクします

Databricks Runtime 18.1以降では、ABAC内で構造体の列をVARIANTにキャストすることで、構造体の列をマスクすることもできます。 。 構造体の形状に基づいて分岐し、フィールドを選択的に削除します。

注記

マスキングのために構造体をVARIANTにキャストすることは、ABAC列マスクポリシー内でのみサポートされています。

次の例では、 schema_of_variant()を使用して 2 つの異なる構造体の形状を識別し、それぞれの中の機密フィールドを伏字にします。

SQL
CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
WHEN schema_of_variant(data) = 'OBJECT<age: BIGINT, email: STRING>' THEN
to_variant_object(named_struct('age', data:age, 'email', 'redacted'))
WHEN schema_of_variant(data) = 'OBJECT<id: BIGINT, ssn: STRING>' THEN
to_variant_object(named_struct('id', data:id, 'ssn', 'xxx-xx-xxxx'))
ELSE NULL::VARIANT
END;

機密性の高い列にタグが付けられるまでアクセスを禁止する

一般的なガバナンスパターンとしては、データが機密指定されているかどうかに基づいてアクセスを制御する方法がある。これは、デフォルトの制限タグと、分類ステータスに応じて異なるレベルの保護を適用するポリシーを使用して実装できます。

  1. 自動化またはカタログまたはスキーマレベルでタグを適用してタグを継承することにより、デフォルトですべての新しいオブジェクトにclassification : unverifiedのようなタグを適用します。これにより、カタログまたはスキーマに追加された新しいテーブルは自動的にタグを継承します。
  2. タグclassification : unverifiedが付いたテーブルへのアクセスをブロックする行フィルタポリシーを作成します。
  3. classification : unverifiedタグが存在しなくなったテーブル上の機密性の高い列をマスクする列マスクポリシーを作成します。
  4. データスチュワードは分類が完了するとタグを更新します。 ブロッキングポリシーが一致しなくなったため、マスキングポリシーが適用されます。
SQL
-- Block access to unverified tables for all non-admin users
CREATE FUNCTION catalog.schema.block_all() RETURNS BOOLEAN
RETURN FALSE;

CREATE POLICY block_unverified
ON CATALOG my_catalog
ROW FILTER catalog.schema.block_all
TO `account users` EXCEPT `data_admins`
FOR TABLES
WHEN has_tag_value('classification', 'unverified');

機密データが分類された後も保護するために、 classification : unverifiedタグが存在しなくなったときに有効になる列マスクポリシーを定義します。

SQL
CREATE FUNCTION catalog.schema.mask_pii(val STRING)
RETURNS STRING
RETURN '***';

CREATE POLICY mask_reviewed_pii
ON CATALOG my_catalog
COLUMN MASK catalog.schema.mask_pii
TO `account users`
EXCEPT `data_admins`
FOR TABLES
WHEN NOT has_tag_value('classification', 'unverified')
MATCH COLUMNS (has_tag_value('pii', 'name') OR has_tag_value('pii', 'address')) AS m
ON COLUMN m;

正規表現なしの部分的な表示

正規表現ではなく文字列操作を使用して、機密値の一部を明らかにする。正規表現に基づくマスキングは、行ごとに値全体をスキャンするため、大きなテキストフィールドではコストが高くなります( 「大きなテキストフィールドでの正規表現マスキングを避ける」を参照)。

SQL
CREATE FUNCTION mask_ssn(ssn STRING, show_last INT) RETURNS STRING
DETERMINISTIC
RETURN CONCAT('***-**-', RIGHT(ssn, show_last));

一貫性ハッシュ(決定論的匿名化)

一貫性ハッシュ(決定論的匿名化とも呼ばれる)は、機密データを複数のテーブル間で同じハッシュ値に置き換える。関数をDETERMINISTICとマークすることで、その関数が同じ入力に対して常に同じ結果を返すことをエンジンに伝えることができ、クエリの最適化に役立ちます。決定論的でエラーのない式を使用するを参照してください。

次の関数は一貫して文字列値をハッシュし、 versionを使用してキーのローテーションをサポートします。 ポリシーのUSING COLUMNS節を通じてversion数値をインクリメントし、以前のバージョンを使用していた履歴データを壊さずに新しいハッシュを生成します。 この関数は、ハッシュ化する前に元の値とバージョン番号を連結するため、同じ入力値で同じバージョンであれば、常に同じハッシュ値が生成されます。

SQL
CREATE FUNCTION pseudonymize(val STRING, version INT) RETURNS STRING
DETERMINISTIC
RETURN SHA2(CONCAT(val, CAST(version AS STRING)), 256);

列のみの述語による行フィルタリング

テーブルの列のみを参照する単純なブール論理を使用して行をフィルタリングします。 列のみの述語を使用すると述語プッシュダウンが有効になり、エンジンはスキャン中に無関係なデータをスキップできます(保護されたテーブルでの述語プッシュダウンについて理解するを参照)。

SQL
CREATE FUNCTION filter_by_region(region STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
RETURN array_contains(split(allowed, ','), lower(region));

許可された地域を定数として渡すポリシーと組み合わせて使用します。

SQL
CREATE POLICY regional_access
ON CATALOG analytics
ROW FILTER filter_by_region
TO 'emea_team'
FOR TABLES
MATCH COLUMNS has_tag('region') AS rgn
USING COLUMNS (rgn, 'emea,apac');

複数の関連列にわたる行フィルタリング

テーブルに、関連する属性を表す複数の列(たとえば、 ship_to_countrybill_to_country )がある場合、それらを個別のタグ条件で照合し、両方を単一のUDFに渡すことができます。これにより、列ごとに個別のポリシーを作成する必要がなくなります。ポリシーには、 MATCH COLUMNS句に最大 3 つの列式を含めることができます (ポリシー クォータを参照)。

SQL
CREATE FUNCTION filter_by_countries(ship_country STRING, bill_country STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
RETURN array_contains(split(allowed, ','), lower(ship_country))
OR array_contains(split(allowed, ','), lower(bill_country));

CREATE POLICY regional_orders
ON SCHEMA prod.orders
ROW FILTER filter_by_countries
TO analysts
FOR TABLES
WHEN has_tag_value('sensitivity', 'high')
MATCH COLUMNS
has_tag('ship_country') AS ship,
has_tag('bill_country') AS bill
USING COLUMNS (ship, bill, 'us,ca,mx');

アナリストは、配送国または請求国のいずれかが許可リストに含まれている注文のみを閲覧できます。

ABAC ポリシー UDF のルックアップ テーブル

アクセスルールがユーザーごとに異なり、ポリシーのTO / EXCEPT条項だけでは表現できない場合は、小さなルックアップテーブルに対してアクセス権限を確認できます。可能であればTO / EXCEPTを使用してください。これはプリンシパルをターゲットにするための推奨されるアプローチです(プリンシパルをターゲットにするためのアプローチを参照)。オプティマイザがサブクエリをブロードキャストハッシュ結合に変換するように、ルックアップテーブルを小さく保ってください( 「ルックアップテーブルを小さく保つ」を参照)。

SQL
CREATE TABLE access_rules (
principal VARCHAR(255),
priority VARCHAR(64)
);

INSERT INTO access_rules VALUES
('alice@company.com', '1-URGENT'),
('alice@company.com', '2-HIGH'),
('bob@company.com', '1-URGENT');

CREATE FUNCTION priority_allowed(o_priority STRING) RETURNS BOOLEAN
RETURN EXISTS (
SELECT 1 FROM access_rules
WHERE principal = session_user() AND priority = o_priority
);

CREATE POLICY priority_filter
ON CATALOG operations
ROW FILTER priority_allowed
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('priority') AS pri
USING COLUMNS (pri);