行フィルターと列マスクを使用した機密テーブル データのフィルター処理

プレビュー

この機能はパブリックプレビュー段階です。

この記事では、行フィルター、列マスク、マッピング テーブルを使用してテーブル内の機密データをフィルター処理するためのガイダンスと例を示します。

行フィルターとは

行フィルターを使用すると、テーブルにフィルターを適用して、後続のクエリーがフィルター述語が true と評価された行のみを返すようにすることができます。 行フィルターは、SQL ユーザー定義関数 (UDF) として実装されます。

行フィルターを作成するには、まず SQL UDF を記述してフィルター ポリシーを定義し、 ALTER TABLE ステートメントを使用してテーブルに適用します。 または、最初の CREATE TABLE ステートメントでテーブルの行フィルターを指定することもできます。 各テーブルには、行フィルターを 1 つだけ含めることができます。 行フィルターは、0 個以上の入力パラメーターを受け入れ、各入力パラメーターは対応するテーブルの 1 つの列にバインドされます。

これらのフィルターと動的ビューの違いは何ですか?

動的ビューは、1 つ以上のソース表の抽象化された読み取り専用 ビュー です。 ユーザーは、ソース表に直接アクセスしなくても、動的ビューにアクセスできます。 動的ビューを作成すると、新しいテーブル名が定義されますが、その名前は、ソース テーブル、または同じスキーマに存在する他のテーブルおよびビューの名前と一致してはなりません。

一方、行フィルターまたは列マスクをターゲット表に関連付けると、新しい表名を導入することなく、対応するロジックが表自体に直接適用されます。 後続のクエリーは、元の名前を使用してターゲットテーブルを直接参照し続けることができます。

動的ビューと行フィルターおよび列マスクの両方で、複雑なロジックをテーブルに適用し、クエリー ランタイムでフィルター処理の決定を処理できます。

フィルターやマスクなどの変換ロジックを読み取り専用テーブルに適用する必要がある場合、およびユーザーが別の名前を使用して動的ビューを参照できる場合は、動的ビューを使用します。 特定のデータに対して式をフィルター処理またはコンピュートする一方で、ユーザーが元の名前を使用してテーブルにアクセスできるようにする場合は、行フィルターと列マスクを使用します。

行フィルター構文

行フィルターを作成して既存のテーブルに追加するには、次の構文を使用します。

行フィルターを作成します。

CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
RETURN {filter clause whose output must be a boolean};

行フィルターをテーブルに適用します。

ALTER TABLE <table_name> SET ROW FILTER <function_name> ON (<column_name>, ...);

テーブルから行フィルターを削除します。

ALTER TABLE <table_name> DROP ROW FILTER;

行フィルターを変更します。

Run a DROP FUNCTION statement to drop the existing function, or use CREATE OR REPLACE FUNCTION to replace it.

行フィルターを削除します。

ALTER TABLE <table_name> DROP ROW FILTER;
DROP FUNCTION <function_name>;

注:

関数をドロップする前に ALTER TABLE ... DROP ROW FILTER コマンドを実行しないと、テーブルがアクセス不能状態になります。

この方法でテーブルにアクセスできなくなった場合は、テーブルを変更し、 ALTER TABLE <table_name> DROP ROW FILTER;を使用して孤立した行フィルター参照を削除します。

行フィルターの例

領域 US内のグループ admin のメンバーに適用される SQL ユーザー定義関数を作成します。

この機能を使用すると、 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);

カラムマスクとは何ですか?

列マスクを使用すると、表の列にマスキング関数を適用できます。 マスキング関数はクエリー ランタイムで評価され、ターゲットカラムの各参照をマスキング関数の結果に置き換えます。 ほとんどのユースケースでは、列マスクは、呼び出し元のユーザーの ID に基づいて、元の列の値を返すか、編集するかを決定します。 列マスクは、SQL UDF として記述される式です。

各テーブル列には、オプションで 1 つのマスキング関数を適用できます。 マスキング関数は、列のマスクされていない値を入力として受け取り、その結果としてマスクされた値を返します。 マスク関数の戻り値は、マスクされる列と同じ型である必要があります。 マスキング関数は、追加の列を入力パラメーターとして受け取り、マスキングロジックで使用することもできます。

列マスクを適用するには、関数を作成し、 ALTER TABLE ステートメントを使用してテーブル列に適用します。 または、テーブルの作成時にマスキング機能を適用することもできます。

列マスク構文

MASK 句内では、Databricks 組み込みランタイム関数のいずれかを使用したり、他のユーザー定義関数を呼び出したりすることができます。一般的なユース ケースには、 current_user( ) を使用して関数を実行している呼び出し元のユーザーの ID や、 is_account_group_member( )を使用してメンバーになっているグループの検査が含まれます。

列マスクを作成します。

CREATE FUNCTION <function_name> (<parameter_name> <parameter_type>, ...)
RETURN {expression with the same type as the first parameter};

既存のテーブルの列に列マスクを適用します。

ALTER TABLE <table_name> ALTER COLUMN <col_name> SET MASK <mask_func_name> [USING COLUMNS <additional_columns>];

テーブル内の列から列マスクを削除します。

ALTER TABLE <table_name> ALTER COLUMN <column where mask is applied> DROP MASK;

列マスクを変更します。

既存の関数 DROP か、 CREATE OR REPLACE TABLEを使用します。

列マスクを削除します。

ALTER 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_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_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);

サポート

  • SQL ワークロード用の Databricks SQL と Databricks ノートブックがサポートされています。

  • MODIFY 権限を持つユーザーによる DML コマンドがサポートされています。 フィルターとマスクは、UPDATE および DELETE によって読み取られたデータに適用され、書き込まれるデータ (INSERT されたデータを含む) には適用されません。

  • サポートされている形式: DeltaおよびParquet 。 Parquet は、マネージド テーブルまたは外部テーブルでのみサポートされます。

  • 列マスクまたは行フィルターを持つ表のビューがサポートされています。

  • Delta Lake チェンジデータフィードは、スキーマがターゲットテーブルに適用される可能性のある行フィルターおよび列マスクと互換性がある限りサポートされます。

  • 外部テーブルがサポートされています。

制限事項

  • 12.2 LTS より前の Databricks Runtime バージョンでは、行フィルターまたは列マスクはサポートされません。 これらのランタイムは安全に失敗するため、これらのランタイムのサポートされていないバージョンからテーブルにアクセスしようとしても、データは返されません。

  • Delta Live Tables マテリアライズドビューとストリーミングテーブルは、行フィルターまたは列マスクをサポートしていません。

  • Python および Scala UDF は、行フィルターまたは列マスク関数として直接サポートされていません。 ただし、定義がカタログに永続的に保存されている限り (つまり、セッションに対して一時的ではない限り)、SQL UDF でこれらを参照することは可能です。

  • Delta Sharing は、行レベルのセキュリティまたは列マスクでは機能しません。

  • タイムトラベルは、行レベルのセキュリティまたは列マスクでは機能しません。

  • テーブルのサンプリングは、行レベルのセキュリティまたは列マスクでは機能しません。

  • ポリシーを持つテーブル内のファイルへのパスベースのアクセスは、現在サポートされていません。

  • 元のポリシーに戻る循環依存関係を持つ行フィルター ポリシーまたは列マスク ポリシーはサポートされていません。

  • MERGE また、浅いクローンはサポートされていません。

単一ユーザー クラスターの制限

行フィルターまたは列マスクは、単一ユーザー・クラスターからアクセスする表に追加しないでください。 これは通常、Databricks ジョブのコンテキストで行われます。 パブリック プレビュー中は、フィルターまたはマスクが適用されると、1 つのユーザー クラスターからテーブルにアクセスできなくなります。