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

行フィルターと列マスクを使用した機密性の高いテーブルデータのフィルタリング

この記事では、行フィルター、列マスク、マッピングテーブルを使用してテーブル内の機密データをフィルターするためのガイダンスと例を紹介します。これらの機能を利用するには、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を使用して、行フィルターと列マスクを使用するストリーミングテーブルまたはマテリアライズドビューを作成できます。行フィルターと列マスクを使用したテーブルのパブリッシュを参照してください。

  1. Databricks ワークスペースで、カタログアイコン カタログ をクリックします。
  2. フィルタリングするテーブルを参照または検索します。
  3. [ 概要 ] タブで、[ 行フィルター: フィルターを追加 ] をクリックします。
  4. [ 行フィルターを追加 ] ダイアログで、フィルター機能を含むカタログとスキーマを選択し、関数を選択します。
  5. 展開されたダイアログで関数定義を表示して、関数ステートメントに含まれる列と一致するテーブル列を選択します。
  6. [ 追加 ] をクリックします。

テーブルからフィルターを削除するには、[ fx行フィルター ] をクリックして [ 削除 ] をクリックします。

行フィルターの例

この例では、USリージョンのadminグループのメンバーに適用されるSQLユーザー定義関数を作成します。

このサンプル関数をsalesテーブルに適用すると、adminグループのメンバーはテーブル内のすべてのレコードにアクセスできます。関数が管理者以外の人によって呼び出された場合、RETURN_IF条件は失敗し、region='US'式が評価され、USリージョンのレコードのみが表示されるようにテーブルがフィルタリングされます。

SQL
CREATE FUNCTION us_filter(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('admin'), true, region='US');

関数を行フィルターとしてテーブルに適用します。salesテーブルからの後続のクエリでは、行のサブセットが返されます。

SQL
CREATE TABLE sales (region STRING, id INT);
ALTER TABLE sales SET ROW FILTER us_filter ON (region);

行フィルターを無効にします。今後、salesテーブルからユーザーがクエリーを実行すると、テーブル内のすべての行が返されます。

SQL
ALTER TABLE sales DROP ROW FILTER;

CREATE TABLEステートメントの一部として、行フィルターとして関数を適用したテーブルを作成します。salesテーブルからの以降のクエリーは、それぞれ行のサブセットを返します。

SQL
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を使用して、行フィルターと列マスクを使用するストリーミングテーブルまたはマテリアライズドビューを作成できます。行フィルターと列マスクを使用したテーブルのパブリッシュを参照してください。

  1. Databricks ワークスペースで、カタログアイコン カタログ をクリックします。
  2. テーブルを参照または検索します。
  3. [ 概要 ] タブで、列マスクを適用する行を見つけ、[ 編集アイコン マスク ] 編集アイコンをクリックします。
  4. [ 列マスクを追加 ] ダイアログで、フィルター関数を含むカタログとスキーマを選択し、関数を選択します。
  5. 展開されたダイアログで、関数定義を表示します。関数に、マスクされる列に加えてパラメーターが含まれている場合は、それらの追加の関数パラメーターをキャストするテーブル列を選択します。
  6. [ 追加 ] をクリックします。

テーブルから列マスクを削除するには、テーブル行の fx列マスク をクリックし、[ 削除 ] をクリックします。

列マスクの例

この例では、ssn列をマスクするユーザー定義関数を作成して、HumanResourceDeptグループのメンバーであるユーザーのみがその列の値を表示できるようにします。

SQL
CREATE FUNCTION ssn_mask(ssn STRING)
RETURN CASE WHEN is_account_group_member('HumanResourceDept') THEN ssn ELSE '***-**-****' END;

新しい関数を列マスクとしてテーブルに適用します。 列マスクは、テーブルを作成するとき、または後で追加できます。

SQL
--Create the `users` table and apply the column mask in a single step:

CREATE TABLE users (
name STRING,
ssn STRING MASK ssn_mask);
SQL
--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列の値が返されるようになりました。

SQL
SELECT * FROM users;
James ***-**-****

列マスクを無効にして、クエリーがssn列の元の値を返すようにするには、次の手順を実行します。

SQL
ALTER TABLE users ALTER COLUMN ssn DROP MASK;

マッピング・テーブルを使用してアクセス制御リストを作成する

行レベルのセキュリティを実現するには、マッピング・テーブル (またはアクセス制御リスト) を定義することを検討してください。 包括的なマッピング・テーブルは、元のテーブルのどのデータ・ローが特定のユーザーまたはグループからアクセス可能かをエンコードします。 マッピング テーブルは、直接結合を通じてファクト テーブルと簡単に統合できるため便利です。

この手法は、カスタム要件を含む多くのユースケースに対応しています。 たとえば、次のようなものがあります。

  • ログインしたユーザーに基づいて制限を課し、特定のユーザーグループに対して異なるルールに対応する。
  • 組織構造など、多様なルールセットを必要とする複雑な階層を作成する。
  • 外部ソースシステムからの複雑なセキュリティモデルを複製する。

マッピング・テーブルを採用することで、これらの困難なシナリオを実現し、行レベルと列レベルのセキュリティ実装を堅牢にすることができます。

マッピング・テーブルの例

マッピングテーブルを使用して、現在のユーザーがリストにあるかどうかを確認します。

SQL
USE CATALOG main;

新しいマッピングテーブルを作成します。

SQL
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 を返します。

SQL
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);.

SQL
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テーブルにいる場合にのみ返されます。

SQL
SELECT * FROM data_table;

列の値に関係なく、常にテーブルのすべての行を表示できるアカウントを含むマッピングテーブルを作成します。

SQL
CREATE TABLE valid_accounts(account string);
INSERT INTO valid_accounts
VALUES
('admin'),
('cstaff');

次に、行内のすべての列の値が 5 未満の場合、または呼び出し元のユーザーが上記のマッピング テーブルのメンバーである場合に true を返す SQL UDF を作成します。

SQL
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を行フィルターとしてテーブルに適用します。

SQL
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 コンピュート)」を参照してください。