行フィルターと列マスクを使用した機密性の高いテーブルデータのフィルタリング
この記事では、行フィルター、列マスク、マッピングテーブルを使用してテーブル内の機密データをフィルターするためのガイダンスと例を紹介します。これらの機能を利用するには、Unity Catalogが必要です。
行フィルターとは何ですか?
行フィルタを使用すると、テーブルにフィルタを適用して、クエリがフィルタ条件を満たす行のみを返すようにすることができます。 行フィルターは、 SQL ユーザー定義関数 (UDF) として実装します。 Python と Scala の UDF もサポートされていますが、SQL UDF でラップされている場合に限ります。
列マスクとは
列マスクを使用すると、テーブル列にマスキング機能を適用できます。 マスキング関数は、クエリの実行時に評価され、ターゲットカラムの各参照をマスキング関数の結果で置き換えます。 ほとんどのユースケースでは、列マスクは、呼び出し元のユーザーの ID に基づいて、元の列値を返すか、編集するかを決定します。 列マスクは、SQL UDF、またはSQL UDFにラップされたPythonまたはScala UDFとして記述された式です。
各テーブル列には、マスキング関数を 1 つだけ適用できます。 マスキング関数は、列のマスクされていない値を入力として受け取り、マスクされた値を結果として返します。 マスキング関数の戻り値は、マスキングされる列と同じ型である必要があります。 マスキング関数は、追加の列を入力パラメーターとして受け取り、それらをマスキング ロジックで使用することもできます。
これらのフィルターと動的ビューの違いは何ですか?
ダイナミックビュー、行フィルター、列マスクを使用すると、複雑なロジックをテーブルに適用し、クエリーのランタイムにフィルタリングの決定を処理できます。
動的ビューは、1 つ以上のソーステーブルの抽象化された読み取り専用ビューです。ユーザーは、ソース・テーブルに直接アクセスしなくても、動的ビューにアクセスできます。 動的ビューの作成では、新しいテーブル名を定義しますが、この名前は、同じスキーマに存在するソース・テーブルや他のテーブルおよびビューの名前と一致してはなりません。
一方、行フィルターまたは列マスクをターゲット テーブルに関連付けると、新しいテーブル名を導入することなく、対応するロジックがテーブル自体に直接適用されます。後続のクエリでも引き続き、元の名前を使用してターゲット テーブルを直接参照できます。
動的ビューは、フィルターやマスクなどの変換ロジックを読み取り専用テーブルに適用する必要がある場合、およびユーザーが異なる名前を使用して動的ビューを参照することが許容される場合に使用します。 Delta Sharing を使用してデータを共有するときにデータをフィルター処理する場合は、動的ビューを使用する必要があります。 特定のデータに対してフィルターまたはコンピュート式を行いながら、ユーザーが元の名前を使用してテーブルにアクセスできるようにする場合は、行フィルターと列マスクを使用します。
始める前に
テーブルに行フィルターと列マスクを追加するには、次のものが必要です。
- Unity Catalog が有効になっているワークスペース。
- Unity Catalogに登録されている関数。この関数は、SQL UDF、または Unity Catalog に登録され、SQL UDF にラップされた Python または Scala UDF にすることができます。 詳細については、「ユーザー定義関数 (UDF) とは」、「列
mask
句」、および「ROW FILTER
句」を参照してください。
また、次の要件を満たす必要があります。
- 行フィルターまたは列マスクをテーブルに追加する関数を割り当てるには、関数の
EXECUTE
権限、スキーマのUSE SCHEMA
権限、親カタログのUSE CATALOG
権限が必要です。 - 新しい テーブルを作成するときにフィルターまたはマスクを追加する場合は、スキーマに対する
CREATE TABLE
権限が必要です。 - 既存の テーブルにフィルターまたはマスクを追加する場合は、テーブルの所有者である必要があります。
行フィルターや列マスクのあるテーブルにアクセスするには、コンピュートリソースが次の要件のいずれかを満たしている必要があります。
- A SQLウェアハウス.
- Databricks Runtime 12.2 LTS 以降の標準アクセス モード (以前の共有アクセス モード)。
- Databricks Runtime 15.4 LTS 以降の専用アクセス モード (旧称シングル ユーザー アクセス モード)。
Databricks Runtime 15.3以下では、専用のコンピュートを使用して行フィルターや列マスクを読み取ることはできません。
Databricks Runtime 15.4 LTS 以降で提供されているデータ フィルタリングを利用するには、 ワークスペースがサーバレス コンピュートに対して有効になっている ことも確認する必要があります。これは、ロー フィルタとカラム マスクをサポートするデータ フィルタリング機能がサーバレス コンピュートで実行されるためです。行フィルタまたは列マスクを使用するテーブルを読み取るために、専用アクセスモードとして設定されたコンピュートを使用する場合、サーバレス コンピュート リソースに対して料金が発生する場合があります。 「専用コンピュート (旧称 single user コンピュート) のきめ細かなアクセス制御」を参照してください。
行フィルターを適用する
行フィルターを作成するには、フィルターポリシーを定義する関数 (UDF) を記述し、それをテーブルに適用します。各テーブルに設定できる行フィルターは1つだけです。行フィルターは0個以上の入力パラメーターを受け入れます。各入力パラメーターは対応する表の1つの列にバインドされます。
行フィルタは、カタログエクスプローラまたは SQL コマンドを使用して適用できます。 Catalog Explorer の手順では、関数を既に作成し、Unity Catalog に登録していることを前提としています。 SQL 命令には、行フィルタ関数を作成し、それをテーブルに適用する例が含まれています。
DLT パイプラインを使用している場合は、DLT Python APIを使用して、行フィルターと列マスクを使用するストリーミングテーブルまたはマテリアライズドビューを作成できます。行フィルターと列マスクを使用したテーブルのパブリッシュを参照してください。
- Catalog Explorer
- SQL
- Databricks ワークスペースで、
カタログ をクリックします。
- フィルタリングするテーブルを参照または検索します。
- [ 概要 ] タブで、[ 行フィルター: フィルターを追加 ] をクリックします。
- [ 行フィルターを追加 ] ダイアログで、フィルター機能を含むカタログとスキーマを選択し、関数を選択します。
- 展開されたダイアログで関数定義を表示して、関数ステートメントに含まれる列と一致するテーブル列を選択します。
- [ 追加 ] をクリックします。
テーブルからフィルターを削除するには、[ fx行フィルター ] をクリックして [ 削除 ] をクリックします。
行フィルターを作成し、それを既存のテーブルに追加するには、 CREATE FUNCTION
を使用し、 ALTER TABLE
を使用して関数を適用します。CREATE TABLE
を使用してテーブルを作成するときにも関数を適用できます。
-
行フィルターを作成します。
SQLCREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
RETURN {filter clause whose output must be a boolean}; -
列名を使用してテーブルに行フィルターを適用します。
SQLALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<column_name>, ...);
その他の構文の例 :
-
関数パラメーターと一致する定数リテラルを使用して、行フィルターをテーブルに適用します。
SQLALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<constant_literal>, ...);
-
テーブルから行フィルターを削除する
SQLALTER TABLE <table_name> DROP ROW FILTER;
-
行フィルターを変更する
SQLRun a DROP FUNCTION statement to drop the existing function, or use CREATE OR REPLACE FUNCTION to replace it.
-
行フィルターを削除する
SQLALTER TABLE <table_name> DROP ROW FILTER;
DROP FUNCTION <function_name>;
関数を削除する前に、ALTER TABLE ... DROP ROW FILTER
コマンドを実行する必要があります。そうしないと、テーブルはアクセスできない状態になります。
この方法でテーブルにアクセスできなくなった場合は、テーブルを変更し、ALTER TABLE <table_name> DROP ROW FILTER;
を使用して孤立行フィルターの参照を削除してください。
ROW FILTER
節も参照してください。
行フィルターの例
この例では、US
リージョンのadmin
グループのメンバーに適用されるSQLユーザー定義関数を作成します。
このサンプル関数をsales
テーブルに適用すると、admin
グループのメンバーはテーブル内のすべてのレコードにアクセスできます。関数が管理者以外の人によって呼び出された場合、RETURN_IF
条件は失敗し、region='US'
式が評価され、US
リージョンのレコードのみが表示されるようにテーブルがフィルタリングされます。
CREATE FUNCTION us_filter(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('admin'), true, region='US');
関数を行フィルターとしてテーブルに適用します。sales
テーブルからの後続のクエリでは、行のサブセットが返されます。
CREATE TABLE sales (region STRING, id INT);
ALTER TABLE sales SET ROW FILTER us_filter ON (region);
行フィルターを無効にします。今後、sales
テーブルからユーザーがクエリーを実行すると、テーブル内のすべての行が返されます。
ALTER TABLE sales DROP ROW FILTER;
CREATE TABLE
ステートメントの一部として、行フィルターとして関数を適用したテーブルを作成します。sales
テーブルからの以降のクエリーは、それぞれ行のサブセットを返します。
CREATE TABLE sales (region STRING, id INT)
WITH ROW FILTER us_filter ON (region);
列マスクを適用する
列マスクを適用するには、関数 (UDF) を作成し、それをテーブル列に適用します。
列マスクは、カタログ エクスプローラまたは SQL コマンドを使用して適用できます。 Catalog Explorer の手順では、関数を既に作成し、Unity Catalog に登録していることを前提としています。 SQL 命令には、列マスク関数を作成し、それをテーブル列に適用する例が含まれています。
DLT パイプラインを使用している場合は、DLT Python APIを使用して、行フィルターと列マスクを使用するストリーミングテーブルまたはマテリアライズドビューを作成できます。行フィルターと列マスクを使用したテーブルのパブリッシュを参照してください。
- Catalog Explorer
- SQL
- Databricks ワークスペースで、
カタログ をクリックします。
- テーブルを参照または検索します。
- [ 概要 ] タブで、列マスクを適用する行を見つけ、[
マスク ] 編集アイコンをクリックします。
- [ 列マスクを追加 ] ダイアログで、フィルター関数を含むカタログとスキーマを選択し、関数を選択します。
- 展開されたダイアログで、関数定義を表示します。関数に、マスクされる列に加えてパラメーターが含まれている場合は、それらの追加の関数パラメーターをキャストするテーブル列を選択します。
- [ 追加 ] をクリックします。
テーブルから列マスクを削除するには、テーブル行の fx列マスク をクリックし、[ 削除 ] をクリックします。
列マスクを作成して既存のテーブル列に追加するには、CREATE FUNCTION
を使用し、ALTER TABLE
を使用してマスキング関数を適用します。CREATE TABLE
を使用してテーブルを作成するときに関数を適用することもできます。
SET MASK
を使用してマスキング機能を適用します。MASK
句内では、Databricks の組み込みランタイム関数のいずれかを使用したり、他のユーザー定義関数を呼び出したりできます。一般的な使用例には、 current_user( )
を使用して関数を実行している呼び出し元のユーザーの ID を検査したり、 is_account_group_member( )
を使用してメンバーが属するグループを取得したりすることが含まれます。詳細については、 Column mask
句 と 組み込み関数を参照してください。
-
列マスクを作成します。
SQLCREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
RETURN {expression with the same type as the first parameter}; -
既存のテーブルの列に列マスクを適用する
SQLALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS <additional_columns>;
その他の構文の例 :
-
関数パラメーターと一致する定数リテラルを使用して、既存のテーブルの列に列マスクを適用します。
SQLALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> USING COLUMNS (<constant_name>, ...);
-
テーブル内の列から列マスクを削除する
SQLALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
-
列マスクを変更するには、既存の関数
DROP
を使用するか、CREATE OR REPLACE TABLE
を使用します。 -
列マスクを削除する
SQLALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
DROP FUNCTION <function_name>;
関数を削除する前にALTER TABLE
コマンドを実行する必要があります。そうしないと、テーブルにアクセスできない状態になります。
この方法でテーブルにアクセスできなくなった場合は、テーブルを変更し、 ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;
を使用して孤立したマスク参照を削除します。
列マスクの例
この例では、ssn
列をマスクするユーザー定義関数を作成して、HumanResourceDept
グループのメンバーであるユーザーのみがその列の値を表示できるようにします。
CREATE FUNCTION ssn_mask(ssn STRING)
RETURN CASE WHEN is_account_group_member('HumanResourceDept') THEN ssn ELSE '***-**-****' END;
新しい関数を列マスクとしてテーブルに適用します。 列マスクは、テーブルを作成するとき、または後で追加できます。
--Create the `users` table and apply the column mask in a single step:
CREATE TABLE users (
name STRING,
ssn STRING MASK ssn_mask);
--Create the `users` table and apply the column mask after:
CREATE TABLE users
(name STRING, ssn STRING);
ALTER TABLE users ALTER COLUMN ssn SET MASK ssn_mask;
クエリーを実行するユーザーがHumanResourceDept
グループのメンバーでない場合、そのテーブルに対するクエリーではマスクされたssn
列の値が返されるようになりました。
SELECT * FROM users;
James ***-**-****
列マスクを無効にして、クエリーがssn
列の元の値を返すようにするには、次の手順を実行します。
ALTER TABLE users ALTER COLUMN ssn DROP MASK;
マッピング・テーブルを使用してアクセス制御リストを作成する
行レベルのセキュリティを実現するには、マッピング・テーブル (またはアクセス制御リスト) を定義することを検討してください。 包括的なマッピング・テーブルは、元のテーブルのどのデータ・ローが特定のユーザーまたはグループからアクセス可能かをエンコードします。 マッピング テーブルは、直接結合を通じてファクト テーブルと簡単に統合できるため便利です。
この手法は、カスタム要件を含む多くのユースケースに対応しています。 たとえば、次のようなものがあります。
- ログインしたユーザーに基づいて制限を課し、特定のユーザーグループに対して異なるルールに対応する。
- 組織構造など、多様なルールセットを必要とする複雑な階層を作成する。
- 外部ソースシステムからの複雑なセキュリティモデルを複製する。
マッピング・テーブルを採用することで、これらの困難なシナリオを実現し、行レベルと列レベルのセキュリティ実装を堅牢にすることができます。
マッピング・テーブルの例
マッピングテーブルを使用して、現在のユーザーがリストにあるかどうかを確認します。
USE CATALOG main;
新しいマッピングテーブルを作成します。
DROP TABLE IF EXISTS valid_users;
CREATE TABLE valid_users(username string);
INSERT INTO valid_users
VALUES
('fred@databricks.com'),
('barney@databricks.com');
新しいフィルターを作成します。
すべてのフィルターは、呼び出し元として実行されるユーザーコンテキストをチェックする関数 (CURRENT_USER
関数やIS_ACCOUNT_GROUP_MEMBER
関数など) を除き、定義者の権限で実行されます。
この例では、関数は現在のユーザーが valid_users
テーブルにいるかどうかを確認します。 ユーザーが見つかった場合、関数は true を返します。
DROP FUNCTION IF EXISTS row_filter;
CREATE FUNCTION row_filter()
RETURN EXISTS(
SELECT 1 FROM valid_users v
WHERE v.username = CURRENT_USER()
);
次の例では、テーブルの作成時に行フィルターを適用します。 また、 ALTER TABLE
ステートメントを使用して、後でフィルタを追加することもできます。 テーブル全体に適用する場合は、 ON ()
構文を使用します。 特定の行には、 ON (row);
.
DROP TABLE IF EXISTS data_table;
CREATE TABLE data_table
(x INT, y INT, z INT)
WITH ROW FILTER row_filter ON ();
INSERT INTO data_table VALUES
(1, 2, 3),
(4, 5, 6),
(7, 8, 9);
テーブルからデータを選択します。このデータは、ユーザーがvalid_users
テーブルにいる場合にのみ返されます。
SELECT * FROM data_table;
列の値に関係なく、常にテーブルのすべての行を表示できるアカウントを含むマッピングテーブルを作成します。
CREATE TABLE valid_accounts(account string);
INSERT INTO valid_accounts
VALUES
('admin'),
('cstaff');
次に、行内のすべての列の値が 5 未満の場合、または呼び出し元のユーザーが上記のマッピング テーブルのメンバーである場合に true
を返す SQL UDF を作成します。
CREATE FUNCTION row_filter_small_values (x INT, y INT, z INT)
RETURN (x < 5 AND y < 5 AND z < 5)
OR EXISTS(
SELECT 1 FROM valid_accounts v
WHERE IS_ACCOUNT_GROUP_MEMBER(v.account));
最後に、SQL UDFを行フィルターとしてテーブルに適用します。
ALTER TABLE data_table SET ROW FILTER row_filter_small_values ON (x, y, z);
サポートと制限事項
行フィルターと列マスクは、すべてのDatabricks機能、あるいはすべてのコンピュートリソースでサポートされているとは限りません。このセクションでは、サポートされている機能と制限事項を紹介します。
サポートされている機能と形式
このサポートされている機能のリストは、すべてを網羅しているわけではありません。一部、パブリックプレビュー中にサポートされなかったためにリストされているアイテムもあります。
-
SQL ワークロード用の Databricks SQL および Databricks ノートブックがサポートされています。
-
MODIFY
権限を持つユーザーによる DML コマンドがサポートされています。フィルタとマスクは、UPDATE
ステートメントとDELETE
ステートメントによって読み取られるデータに適用され、書き込まれるデータ (INSERT
を含む) には適用されません。 -
サポートされているデータ形式は以下の通りです。
- マネージドテーブルと外部テーブル用の Delta と Parquet。
- Unity Catalogに登録されているフォーリンテーブルの他の複数のデータ形式は、レイクハウスフェデレーションを使用して登録されています。
-
ポリシーパラメーターには、定数式(文字列、数値、区間、ブーリアン、ヌル)を含めることができます。
-
SQL、Python、Scala UDF は、Unity Catalog に登録されている場合、行フィルターまたは列マスク関数としてサポートされます。 Python と Scala の UDF は SQL UDF でラップする必要があります。
-
列マスクや行フィルターを参照するテーブルにビューを作成できますが、列マスクや行フィルターをビューに追加することはできません。
-
Delta Lake チェンジデータフィードは、スキーマがターゲットテーブルに適用される行フィルターおよび列マスクと互換性がある場合にサポートされます。
-
フォーリンテーブルがサポートされています。
-
テーブルサンプリングはサポートされています。
-
MERGE
文は、ソース表、ターゲット表、あるいはその両方で行フィルタと列マスクを使用する場合にサポートされます。 これには、単純なサブクエリを含む行フィルタ関数を持つテーブルが含まれます。 制限事項については、次のセクションにリストされています。 -
Databricks SQL マテリアライズド ビュー と Databricks SQL ストリーミング テーブル で行フィルターと列マスクがサポートされるようになりました (パブリック プレビュー)。
- 行フィルターと列マスクは、Databricks SQL マテリアライズド ビューまたはストリーミング テーブルに追加できます。 マスクの追加は、マテリアライズド・ビューまたはストリーミング・テーブルが定義されるときに宣言的に行う必要があります。 CREATE MATERIALIZED VIEW または CREATE STREAMING TABLE を参照してください。
- 行フィルターと列マスクを含むテーブルで、Databricks SQLマテリアライズドビューまたはストリーミングテーブルを定義できます。
-
DLT で宣言および公開されたマテリアライズドビュー とストリーミングテーブルは、行フィルターまたは列マスクをサポートします (パブリック プレビュー)。
- 行フィルタと列マスクを DLT マテリアライズドビューまたはストリーミングテーブルに追加できます。
- DLT マテリアライズドビューまたはストリーミングテーブルは、行フィルタと列マスクを含むテーブルで定義できます。
行フィルターと列マスクを使用したテーブルのパブリッシュを参照してください。
パフォーマンスに関する推奨事項
行フィルタと列マスクは、フィルタ操作とマスキング操作の前にユーザーがベース テーブルの値の内容を表示できないようにすることで、データの可視性を制御します。 これらは、一般的なユースケースでのクエリに対する応答性に優れています。 あまり一般的ではないアプリケーションでは、クエリ エンジンがクエリ パフォーマンスの最適化と、フィルター処理/マスクされた値からの情報の漏洩から保護するかを選択する必要があるため、クエリ エンジンは常に安全な決定を下しますが、クエリ パフォーマンスに多少の影響は生じません。 このパフォーマンスへの影響を最小限に抑えるには、次の推奨事項を適用します。
- シンプルなポリシー関数を使用する: 式が少ないポリシー関数は、多くの場合、より複雑な式よりもパフォーマンスが優れています。 マッピング・テーブルや式のサブクエリの使用は避け、単純な CASE 関数を使用してください。
- 関数の引数の数を減らします。 Databricks は、ポリシー関数の引数の結果としてソース テーブルへの列参照を最適化できません (これらの列がクエリで使用されていない場合でも)。 引数の少ないポリシー関数を使用すると、これらのテーブルからのクエリのパフォーマンスが向上します。
- AND 結合が多すぎる行フィルターを追加しないでください。 各テーブルは最大で 1 つの行フィルターの追加しかサポートしていないため、一般的なアプローチは、複数の必要なポリシー関数を
AND
と組み合わせることです。 ただし、結合ごとに、この表の他の場所に記載されているパフォーマンスに影響を与える可能性のあるコンポーネント (マッピング テーブルなど) が結合に含まれる可能性が高くなります。 パフォーマンスを向上させるために、使用する接続を減らします。 - これらのテーブルからのテーブルポリシーおよびクエリでエラーをスローできない決定論的な式を使用します。 一部の式では、ANSI 除算など、指定された入力が有効でない場合、エラーがスローされる場合があります。 このような場合、SQL コンパイラは、これらの式 (フィルターなど) を使用した操作をクエリ プランの下位にプッシュしすぎないようにして、フィルター処理やマスク操作の前に値に関する情報を明らかにする "ゼロ除算" などのエラーの可能性を回避してはなりません。 エラーをスローしない決定論的な式 (この例では の のように
try_divide
) を使用します。 - テーブルに対してテストクエリを実行してパフォーマンスを測定する: 行フィルタや列マスクを使用して、テーブルに期待される作業負荷を表す現実的なクエリを構築し、パフォーマンスを測定します。フィルタリングとマスキングロジックのパフォーマンスと表現力のバランスが取れるまでポリシー関数を少しずつ修正し、その効果を観察してください。
制限
- 12.2 LTS以前のDatabricks Runtimeバージョンでは、行フィルターまたは列マスクはサポートされません。これらのランタイムは安全に失敗します。つまり、サポートされていないバージョンのランタイムのテーブルにアクセスしようとしても、データは返されません。
- デルタ共有は、行レベルのセキュリティまたは列マスクでは機能しません。
- カタログ Iceberg REST Unity REST APIs を使用して、行フィルターや列マスクを持つテーブルにアクセスすることはできません。
- ビューに行レベルのセキュリティまたは列マスクを適用することはできません。
- タイムトラベルは、行レベルのセキュリティまたは列マスクでは機能しません。
- ポリシーを持つテーブル内のファイルへの、パスベースのアクセスはサポートされていません。
- 元のポリシーに戻る循環依存性を持つ行フィルターまたは列マスクポリシーはサポートされていません。
- ディープクローン、シャロークローンはサポートされていません。
MERGE
ステートメントは、ネスト、集計、ウィンドウ、制限、または非決定論的関数を含む行フィルタまたはカラムマスクポリシーを持つテーブルをサポートしません。- Delta Lake APIsはサポートされていません。
専用アクセスモードの制限
行フィルターまたは列マスクを持つテーブルには、 Databricks Runtime 15.3 以前の専用のアクセス コンピュート リソースからアクセスできません。 Databricks Runtime 15.4 LTS 以降では、 ワークスペースでサーバレス コンピュートが有効になっている場合 、専用アクセスモードを使用できます。詳細については、「 Fine-grained access control on dedicated コンピュート (旧称 single user コンピュート)」を参照してください。