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

動的アクセス制御にはマッピングテーブルを使用する

このチュートリアルでは、マッピングテーブルを使用して、多数のグループを管理することなく、行レベルおよび列レベルのアクセスを制御する方法を示します。単一のルックアップテーブルが、行フィルタリングと列マスキングの両方を制御します。アクセス権限の変更は、行の更新のみで済みます。新しいグループを作成したり、ポリシーを書き換えたりする必要はありません。

このチュートリアルでは、条件付きマスキングについても説明します。PII(個人情報)列は、同じ行の別の列の値に応じて、異なる方法でマスキングされます。confidentialとマークされた注文は、ユーザーのアクセス権限レベルに関わらず、個人情報が完全に削除されます。

マッピングテーブルの設計に関する一般的なガイダンスについては、 「マッピングテーブルを使用してアクセス制御リストを作成する」を参照してください。

前提条件

  • Databricks Runtime 16.4 以降、またはサーバレス コンピュート。
  • アカウント管理者またはワークスペース管理者権限(管理タグを作成するため)。
  • MANAGE 対象のカタログまたはスキーマに対する権限。
  • EXECUTE UDFについて。
  • SQLノートブックまたはクエリ エディター。

シナリオ

貴社は、4つの地域(米国東部、米国西部、欧州、アジア太平洋)と4つの部門にまたがる従業員を抱えています。各ユーザーは、自分の地域と部署に一致する行のみを表示し、PII 列は、マッピング テーブルに保存されているユーザーのクリアランス レベル ( fullmasked 、またはnone ) と注文のorder_priorityの 2 つの要素に基づいてマスクする必要があります。

グループベースのアプローチでは、地域と部門の組み合わせごとにグループを作成する必要があります。例えば、4つの地域と4つの部署のために、16のグループが必要になります。PII(個人情報)のクリアランスレベルを追加すると、そのカウントは3倍になります。新しい地域または部門ごとに、新しいグループとポリシーの更新が必要になります。

マッピングテーブル方式では、これを単一のルックアップテーブルに置き換えます。つまり、ユーザーごとに1行、アクセス次元ごとに1列となります。ユーザーのアクセス権限を変更するには、該当する行を更新します。

ステップ 1: 管理タグを作成する

SQL実行する前に、カタログ エクスプローラー UI で次の管理タグを作成します ( [カタログ] > [管理] > [管理タグ] > [管理タグの作成] )。

タグキー

許容値

region

(キーのみのタグ)

department

(キーのみのタグ)

pii

name, email

priority

(キーのみのタグ)

regiondepartmentタグは、行フィルタポリシーにフィルタUDFに渡す列を指定します。piiタグは、列マスク ポリシーに対して、どの列をマスクするか、およびそれらの列にどのような PII タイプが含まれているかを示します。priorityタグを使用すると、列マスク ポリシーが条件付きマスキングのためにorder_priority値をマスク UDF に渡すことができます。

警告

タグデータはプレーンテキストとして保存され、グローバルに複製される可能性があります。リソースのセキュリティを損なう可能性のあるタグ名、値、または記述子を使用しないでください。例えば、個人情報や機密情報を含むタグ名、値、記述子は使用しないでください。

ステップ 2: サンプルデータを構築する

カタログ、スキーマ、および注文テーブルを作成します。order_priority列は条件付きマスキングを制御します。 confidentialとマークされた注文は、高いアクセス権限を持つユーザーであっても、個人情報が完全にマスキングされます。

SQL
CREATE CATALOG IF NOT EXISTS abac_tutorial;
USE CATALOG abac_tutorial;

CREATE SCHEMA IF NOT EXISTS mapping_demo;
USE SCHEMA mapping_demo;
SQL
CREATE OR REPLACE TABLE orders (
order_id INT,
customer_name STRING,
customer_email STRING,
sales_region STRING,
dept STRING,
amount DOUBLE,
order_date DATE,
order_priority STRING
);

INSERT INTO orders VALUES
(1, 'Acme Corp', 'orders@acme.com', 'us_east', 'engineering', 50000, '2025-01-15', 'standard'),
(2, 'Beta Inc', 'sales@beta.com', 'us_east', 'sales', 75000, '2025-02-01', 'confidential'),
(3, 'Gamma LLC', 'info@gamma.com', 'us_west', 'engineering', 30000, '2025-01-20', 'standard'),
(4, 'Delta Co', 'deals@delta.com', 'us_west', 'sales', 95000, '2025-03-01', 'confidential'),
(5, 'Epsilon GmbH', 'kontakt@epsilon.de', 'eu', 'engineering', 45000, '2025-02-15', 'standard'),
(6, 'Zeta SA', 'contact@zeta.fr', 'eu', 'sales', 62000, '2025-01-30', 'standard'),
(7, 'Eta Ltd', 'hello@eta.sg', 'apac', 'marketing', 28000, '2025-03-10', 'confidential'),
(8, 'Theta Corp', 'biz@theta.com', 'us_east', 'marketing', 55000, '2025-02-20', 'standard'),
(9, 'Iota KK', 'info@iota.jp', 'apac', 'engineering', 41000, '2025-01-25', 'standard'),
(10, 'Kappa Inc', 'sales@kappa.com', 'us_west', 'marketing', 33000, '2025-03-05', 'standard');

ステップ 3: 管理タグを適用する

ABAC ポリシーが列を自動的に検出できるように、列にタグを付けます。 order_priority列にはキーのみのpriorityタグが付けられているため、列マスクMATCH COLUMNSを介して一致し、その値をマスクUDFに渡すことができます。

SQL
ALTER TABLE abac_tutorial.mapping_demo.orders
ALTER COLUMN sales_region SET TAGS ('region' = '');
ALTER TABLE abac_tutorial.mapping_demo.orders
ALTER COLUMN dept SET TAGS ('department' = '');
ALTER TABLE abac_tutorial.mapping_demo.orders
ALTER COLUMN customer_name SET TAGS ('pii' = 'name');
ALTER TABLE abac_tutorial.mapping_demo.orders
ALTER COLUMN customer_email SET TAGS ('pii' = 'email');
ALTER TABLE abac_tutorial.mapping_demo.orders
ALTER COLUMN order_priority SET TAGS ('priority' = '');

ステップ 4: マッピングテーブルを作成する

地域、部署、および承認の組み合わせごとにグループを作成する代わりに、ユーザーごとに1行を持つ1つのテーブルを維持します。pii_access列は、PII列の表示方法を制御します。

  • full — 実際の値を確認してください(標準優先注文の場合)
  • maskedA***などの部分値を参照 o***@acme.com
  • none - 見る ***REDACTED***

expires_on列は、各アクセスエントリの有効期限を設定します。この日付以降、行フィルタUDFはエントリに一致しなくなり、ユーザーは手動での取り消しを必要とせずに、通知なくアクセス権を失います。これは、請負業者、一時的なデータ共有契約、または期間限定のプロジェクトに役立ちます。

ユーザーが複数の地域と部署の組み合わせにアクセスする必要がある場合は、行を追加してください。

注記

マッピングテーブルは小さく、シンプルに保つ。保護されたテーブルに対する各クエリは、行フィルタと列マスクのUDFを実行し、それらがマッピングテーブルに対してクエリを実行します。大規模なマッピングテーブルや複雑なUDFロジックは、クエリのパフォーマンスに影響を与える可能性があります。可能な限り、狭いスキーマを使用し、UDFロジックは単一のルックアップに限定してください。

SQL
CREATE OR REPLACE TABLE abac_tutorial.mapping_demo.user_access (
user_email STRING,
region STRING,
department STRING,
pii_access STRING,
expires_on DATE
);

INSERT INTO abac_tutorial.mapping_demo.user_access VALUES
(current_user(), 'us_east', 'engineering', 'masked', '2099-12-31'),
('bob@example.com', 'us_west', 'sales', 'full', '2099-12-31'),
('carol@example.com', 'eu', 'engineering', 'none', '2099-12-31'),
('david@example.com', 'apac', 'marketing', 'masked', '2099-12-31');

ステップ 5: 行フィルターUDFを作成する

このUDFは、行のsales_regiondept値(タグマッチングによってポリシーから渡される)を受け取り、マッピングテーブルで現在のユーザーを検索し、一致するエントリが存在し、かつ有効期限が切れていない場合にのみTRUEを返します。マッピングテーブルに登録されていないユーザー、またはアクセス権が期限切れになっているユーザーには、行が表示されません(フェイルクローズ設計)。

SQL
CREATE OR REPLACE FUNCTION abac_tutorial.mapping_demo.access_filter(
region_val STRING,
dept_val STRING
)
RETURNS BOOLEAN
RETURN EXISTS (
SELECT 1 FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user()
AND region = region_val
AND department = dept_val
AND expires_on >= current_date()
);

ステップ 6: 列マスクUDFを作成する

このUDFは、個人情報(PII)列の表示方法を制御します。3 つの引数を取ります。列の値、PII タイプ ( 'name'または'email' )、および行のorder_priority 。マスキングロジックは2つの層から構成されています。

  • レイヤー 1 (条件付きマスキング): order_priorityconfidentialの場合、ユーザーのクリアランスレベルに関係なく、個人情報は常に完全にマスキングされます。
  • レイヤー 2 (ユーザー クリアランス): 標準行の場合、UDF はマッピング テーブルでユーザーのpii_accessレベルをチェックし、対応するマスクを適用します。ユーザーが複数のマッピングテーブルエントリ(複数地域アクセス)を持っている場合、すべての行の中で最も高いクリアランスが適用されます。
SQL
CREATE OR REPLACE FUNCTION abac_tutorial.mapping_demo.pii_mask(
val STRING,
pii_type STRING,
order_pri STRING
)
RETURNS STRING
RETURN CASE
WHEN order_pri = 'confidential' THEN '***REDACTED***'
WHEN EXISTS (
SELECT 1 FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user() AND pii_access = 'full'
) THEN val
WHEN EXISTS (
SELECT 1 FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user() AND pii_access = 'masked'
) THEN
CASE pii_type
WHEN 'email' THEN CONCAT(LEFT(val, 1), '***@', SUBSTRING_INDEX(val, '@', -1))
WHEN 'name' THEN CONCAT(LEFT(val, 1), '***')
ELSE CONCAT(LEFT(val, 1), '***')
END
ELSE '***REDACTED***'
END;

ステップ 7: ポリシーを作成する

同じマッピングテーブルに基づいて動作する3つのポリシーを作成します。どちらの列マスクポリシーも同じpii_mask関数を使用します。引数pii_typeは、どのマスキングスタイルを適用するかを関数に指示するため、列タイプごとに個別の UDF を作成する必要はありません。

priority管理タグはMATCH COLUMNSで使用され、 order_priority列と照合してその値をorder_priとしてマスクUDFに渡します。 条件付きマスキングは次のように実装されます。ポリシーは、クエリ実行時に行の優先度値をUDFに渡します。

SQL
CREATE POLICY user_access_filter
ON SCHEMA abac_tutorial.mapping_demo
ROW FILTER abac_tutorial.mapping_demo.access_filter
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('region') AS r, has_tag('department') AS d
USING COLUMNS (r, d);
SQL
CREATE POLICY pii_mask_name
ON SCHEMA abac_tutorial.mapping_demo
COLUMN MASK abac_tutorial.mapping_demo.pii_mask
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'name') AS m,
has_tag('priority') AS pri
ON COLUMN m
USING COLUMNS ('name', pri);

CREATE POLICY pii_mask_email
ON SCHEMA abac_tutorial.mapping_demo
COLUMN MASK abac_tutorial.mapping_demo.pii_mask
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'email') AS m,
has_tag('priority') AS pri
ON COLUMN m
USING COLUMNS ('email', pri);

ステップ 8: 結果を確認する

マッピングテーブルのエントリにより、 us_east / engineeringへのアクセス権限とmaskedクリアランスが付与されます。以下のクエリを実行して、個人情報が部分的にマスクされた状態で、注文番号1のみが表示されることを確認してください。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

注文番号1はorder_priority = 'standard'なので、 maskedのクリアランスが適用されます。

ユーザーにとって期待される結果:

注文ID

顧客名

顧客メールアドレス

販売地域

部門

注文日

順序優先順位

1

A***

o***@acme.com

アメリカ東部

エンジニアリング

50000

2025年1月15日

Standard

他のユーザーが見るもの:

ユーザー

目に見える注文

順序優先順位

PIIの行動

bob@example.com ( fullクリアランス)

#4 (米国西部、売上)

機密

***REDACTED*** — 機密情報の上書きfullクリアランス

carol@example.com ( noneクリアランス)

#5 (EU、エンジニアリング)

Standard

***REDACTED***none許可は完全な編集を意味します

david@example.com ( maskedクリアランス)

#7(アジア太平洋地域、マーケティング)

機密

***REDACTED*** — 機密情報の上書きmaskedクリアランス

(カタログ所有者)

全10人

全員マスクなし(オーナーはポリシーの適用対象外)

(非公開ユーザー)

なし

行フィルターは行を返しません

ボブにはfullクリアランスがありますが、注文番号4がconfidentialなので、 ***REDACTED***が見えます。これは条件付きマスキングです。行の優先度値がユーザーによる承認よりも優先されます。

ステップ 9: アクセスを動的に更新する

マッピングテーブル方式の主な利点は、テーブル内の行を更新することでアクセス権限を変更できる点です。ポリシー、UDF、グループメンバーシップを更新する必要はありません。

別の部署に再配置する

所属部署をengineeringからsalesに変更してください。注文番号2(Beta Inc)はconfidential販売注文であるため、 masked承認があっても個人情報は完全に伏せられています。

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'sales'
WHERE user_email = current_user();

検証するには、以下のクエリを実行してください。注文番号2には***REDACTED***個人情報が含まれているはずです。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

変更を元に戻す:

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'engineering'
WHERE user_email = current_user();

PIIクリアランスのアップグレード

クリアランスをmaskedからfullに変更してください。標準優先度の行については、実際の個人情報(PII)の値が表示されるようになりました。

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'full'
WHERE user_email = current_user();

検証するには、以下のクエリを実行してください。注文番号1は優先度standardなので、 full承認があればAcme Corporders@acme.comが表示されるはずです。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

変更を元に戻す:

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'masked'
WHERE user_email = current_user();

追加地域へのアクセスを許可する

EUのエンジニアリングへのアクセスを許可するには、2行目を挿入してください。新しいグループやポリシーは必要ありません。

SQL
INSERT INTO abac_tutorial.mapping_demo.user_access
VALUES (current_user(), 'eu', 'engineering', 'masked', '2099-12-31');

検証するには、以下のクエリを実行してください。これで、注文番号1(us_east、エンジニアリング)と注文番号5(eu、エンジニアリング)の両方が表示されるはずです。個人情報は部分的にマスクされています。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

追加アクセス権限を削除します。

SQL
DELETE FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user() AND region = 'eu';

アクセス権を期限切れにする

アクセスエントリを過去の日付に設定してください。行フィルタUDFはexpires_on >= current_date()をチェックするため、期限切れのエントリは黙って無視され、アクセス権は自動的に取り消されます。これは、請負業者、期間が定められたデータ共有契約、または期限付きのプロジェクトに役立ちます。

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = current_date() - INTERVAL 1 DAY
WHERE user_email = current_user();

以下のクエリを実行して、行が表示されないことを確認してください。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

将来の有効期限を指定してアクセス権を復元する:

SQL
UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = '2099-12-31'
WHERE user_email = current_user();

アクセスが復元されたことを確認するには、次のクエリを実行してください。

SQL
SELECT * FROM abac_tutorial.mapping_demo.orders;

まとめ

このチュートリアルでは、次の3つのパターンを示しました。

  • マッピングテーブルパターン :単一のルックアップテーブルが、行フィルタリングと列マスキングの両方を制御します。アクセス権限の変更は行を更新するだけで行われ、ポリシーやグループの変更は必要ありません。
  • 条件付きマスキング :マスクUDFは、各行のorder_priority列をチェックして、PIIをどのようにマスキングするかを決定します。機密行は、ユーザーのクリアランスレベルに関係なく常に完全に墨消しされます。これは、 order_priorityタグ付けし、 MATCH COLUMNSを介して UDF に渡すことによって実現されます。
  • アクセス期限 :マッピングテーブルにexpires_on日付が含まれています。行フィルタUDFは、この日付をcurrent_date()と比較するため、期限切れのエントリは黙って無視され、手動による介入なしにアクセス権が自動的に取り消されます。

掃除

このチュートリアルで作成したすべてのオブジェクトを削除するには、次のコマンドを実行します。

SQL
DROP POLICY user_access_filter ON SCHEMA abac_tutorial.mapping_demo;
DROP POLICY pii_mask_name ON SCHEMA abac_tutorial.mapping_demo;
DROP POLICY pii_mask_email ON SCHEMA abac_tutorial.mapping_demo;
DROP FUNCTION IF EXISTS abac_tutorial.mapping_demo.access_filter;
DROP FUNCTION IF EXISTS abac_tutorial.mapping_demo.pii_mask;
DROP TABLE IF EXISTS abac_tutorial.mapping_demo.orders;
DROP TABLE IF EXISTS abac_tutorial.mapping_demo.user_access;
DROP SCHEMA IF EXISTS abac_tutorial.mapping_demo CASCADE;

regiondepartmentpii 、およびpriority管理タグを削除するには、カタログ エクスプローラー UI を使用します。