動的データマスキング (DDM)
動的データマスキング (DDM) は、マスクされた列へのアクセスを許可しながら、機密情報を隠蔽します。DDM は保存されたデータを変更しません。代わりに、`SELECT` クエリ中にデータを表示する際にのみ、データを隠蔽された形式で表示します。これは、偶発的なデータ漏洩に対するある程度の保護を提供することを目的としています。ただし、SSTable ファイルに直接アクセスできるユーザーは、クリアなデータを読み取ることができます。
マスキング関数
DDM は、機密情報を隠蔽する一連の CQL ネイティブ関数に基づいています。利用可能な関数は次のとおりです。
関数 | 説明 |
---|---|
|
最初の引数を `null` 列で置き換えます。返される値は常に存在しない列であり、`null` 値を表す null 以外の列ではありません。 例 `mask_null('Alice')` → `null` `mask_null(123)` → `null` |
|
その引数を、同じ型の任意の固定されたデフォルト値で置き換えます。テキスト値の場合は `****`、数値の場合はゼロ、ブール値の場合は `false` などになります。 リスト、セット、マップなどの可変長の複数値型は、空のコレクションとしてマスクされます。 タプル、ユーザー定義型 (UDT)、ベクターなどの固定長の複数値型は、それぞれの値を値型のデフォルトのマスキング値で置き換えることによってマスクされます。 例 `mask_default('Alice')` → `'****'` `mask_default(123)` → `0` `mask_default((list<int>) [1, 2, 3])` → `[]` `mask_default((vector<int, 3>) [1, 2, 3])` → `[0, 0, 0]` |
|
最初の引数を、2 番目の引数の置換値で置き換えます。置換値は、置き換えられる値と同じ型である必要があります。 例 `mask_replace('Alice', 'REDACTED')` → `'REDACTED'` `mask_replace(123, -1)` → `-1` |
|
最初の `text`、`varchar`、または `ascii` 引数のコピーを返し、先頭と末尾以外の各文字をパディング文字で置き換えます。2 番目と 3 番目の引数は、公開されるプレフィックスとサフィックスのサイズです。オプションの 4 番目の引数はパディング文字で、デフォルトは `*` です。 例 `mask_inner('Alice', 1, 2)` → `'A*ce'` `mask_inner('Alice', 1, null)` → `'A*'` `mask_inner('Alice', null, 2)` → `'*ce'` `mask_inner('Alice', 2, 1, '#')` → `'Al##e'` |
|
最初の `text`、`varchar`、または `ascii` 引数のコピーを返し、先頭と末尾の文字をパディング文字で置き換えます。2 番目と 3 番目の引数は、公開されるプレフィックスとサフィックスのサイズです。オプションの 4 番目の引数はパディング文字で、デフォルトは `*` です。 例 `mask_outer('Alice', 1, 2)` → `'*li*'` `mask_outer('Alice', 1, null)` → `'*lice'` `mask_outer('Alice', null, 2)` → `'Ali*'` `mask_outer('Alice', 2, 1, '#')` → `'##ic#'` |
|
最初の引数のハッシュを含む `blob` を返します。オプションの 2 番目の引数は、使用されるハッシュアルゴリズムで、利用可能な Java セキュリティプロバイダーに従います。デフォルトのハッシュアルゴリズムは `SHA-256` です。 例
|
これらの関数は、`SELECT` クエリで使用して、データの隠蔽されたビューを取得できます。たとえば
CREATE TABLE patients (
id timeuuid PRIMARY KEY,
name text,
birth date
);
INSERT INTO patients(id, name, birth) VALUES (now(), 'alice', '1982-01-02');
INSERT INTO patients(id, name, birth) VALUES (now(), 'bob', '1982-01-02');
SELECT mask_inner(name, 1, null), mask_default(birth) FROM patients;
// system.mask_inner(name, 1, NULL) | system.mask_default(birth)
// -----------------------------------+----------------------------
// b** | 1970-01-01
// a**** | 1970-01-01
テーブル列へのマスキング関数の添付
マスキング関数は、テーブルの任意の列に永続的に添付できます。マスキング列が定義されている場合、`SELECT` クエリは常に列値をマスクされた形式で返します。マスキングは、`SELECT` クエリを実行しているユーザーには透過的です。列がマスクされていることを知る唯一の方法は、テーブル定義を参照することです。
これはオプションの機能であり、デフォルトでは無効になっています。この機能を使用するには、`cassandra.yaml` で `dynamic_data_masking_enabled` プロパティを有効にします。
テーブルの列のマスクは、`CREATE TABLE` でテーブルスキーマを作成する際に定義できます。この例では、2 つの引数を持つ `mask_inner` 関数を使用しています。
CREATE TABLE patients (
id timeuuid PRIMARY KEY,
name text MASKED WITH mask_inner(1, null),
birth date MASKED WITH mask_default()
);
このデータに対して `SELECT` クエリを使用する場合、`mask_inner` 関数には 3 つの引数が必要ですが、関数をテーブルスキーマに添付する場合は、最初の引数は常に省略されます。最初の引数の値は、この場合は `text` 列であるマスクされた列の値として常に解釈されます。
同じ理由で、`mask_default` マスキング関数を使用する場合は、テーブルスキーマを作成する際に引数はありませんが、`SELECT` クエリで使用する場合には 1 つの引数が必要です。
データは、変更せずにマスクされたテーブルに通常どおり挿入できます。たとえば
INSERT INTO patients(id, name, birth) VALUES (now(), 'alice', '1984-01-02');
INSERT INTO patients(id, name, birth) VALUES (now(), 'bob', '1982-02-03');
`SELECT` クエリはマスクされたデータを返します。マスキング関数は、列値に自動的に適用されます。
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// a**** | 1970-01-01
// b** | 1970-01-01
`ALTER TABLE` クエリを使用して、テーブル列のマスキング関数を変更できます。
ALTER TABLE patients ALTER name
MASKED WITH mask_default();
同様に、`ALTER TABLE` クエリを使用して、列からマスキング関数を切り離すことができます。
ALTER TABLE patients ALTER name
DROP MASKED;
権限
通常のユーザーは `UNMASK` 権限なしで作成され、マスクされた値が表示されます。ユーザーに `UNMASK` 権限を付与すると、マスクされた列のマスクされていない値を取得できます。スーパーユーザーは自動的に `UNMASK` 権限で作成され、`SELECT` クエリ結果でマスクされていない値が表示されます。
たとえば、マスクされた列を持つテーブルがあるとします。
CREATE TABLE patients (
id timeuuid PRIMARY KEY,
name text MASKED WITH mask_inner(1, null),
birth date MASKED WITH mask_default()
);
そして、テーブルにいくつかのデータを入力します。
INSERT INTO patients(id, name, birth) VALUES (now(), 'alice', '1984-01-02');
INSERT INTO patients(id, name, birth) VALUES (now(), 'bob', '1982-02-03');
LOGIN unprivileged
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// a**** | 1970-01-01
// b** | 1970-01-01
次に、テーブルに対する `SELECT` 権限を持つ 2 つのユーザーを作成しますが、`UNMASK` 権限は 1 つのユーザーのみに付与します。
CREATE USER privileged WITH PASSWORD 'xyz';
GRANT SELECT ON TABLE patients TO privileged;
GRANT UNMASK ON TABLE patients TO privileged;
CREATE USER unprivileged WITH PASSWORD 'xyz';
GRANT SELECT ON TABLE patients TO unprivileged;
`UNMASK` 権限を持つユーザーは、クリアでマスクされていないデータを見ることができます。
LOGIN privileged
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// alice | 1984-01-02
// bob | 1982-02-03
`UNMASK` 権限を持たないユーザーは、マスクされたデータのみを見ることができます。
LOGIN unprivileged
SELECT name, birth FROM patients;
// name | birth
// -------+------------
// a**** | 1970-01-01
// b** | 1970-01-01
`UNMASK` 権限は他の権限と同じように機能し、必要に応じて取り消すことができます。
REVOKE UNMASK ON TABLE patients
FROM privileged;
認証が無効になっている場合、匿名のデフォルトユーザーには `UNMASK` 権限を含むすべての権限があり、マスクされていないデータを見ることができることに注意してください。言い換えれば、列にデータマスキング関数を添付するのは、認証が有効になっている場合にのみ意味があります。
`UNMASK` 権限を持つユーザーのみが、`SELECT` クエリの `WHERE` 句でマスクされた列を使用できます。`UNMASK` 権限を持たないユーザーはこの機能を使用できません。この機能により、悪意のあるユーザーが網羅的なブルートフォースクエリを実行してクリアなデータを見るのを防ぎます。`UNMASK` 権限を持たないユーザーには、次のものが表示されます。
CREATE USER untrusted_user WITH PASSWORD 'xyz';
GRANT SELECT ON TABLE patients TO untrusted_user;
LOGIN untrusted_user
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
// Unauthorized: Error from server: code=2100 [Unauthorized] message="User untrusted_user has no UNMASK nor SELECT_UNMASK permission on table k.patients"
信頼できるデータベースユーザーが、信頼できない外部ユーザーがクエリを実行するマスクされたデータを作成する必要があるユースケースがいくつかあります。たとえば、信頼できるアプリはデータベースに接続し、クエリを使用して、エンドユーザーに表示されるマスクされたデータを取得できます。この場合、信頼できるユーザー(アプリ)に `SELECT_MASKED` 権限を付与できます。この権限により、ユーザーは `SELECT` クエリの `WHERE` 句でマスクされた列をクエリできますが、クエリ結果ではマスクされたデータのみが表示されます。
CREATE USER trusted_user WITH PASSWORD 'xyz';
GRANT SELECT, SELECT_MASKED ON TABLE patients TO trusted_user;
LOGIN trusted_user
SELECT name, birth FROM patients WHERE name = 'Alice' ALLOW FILTERING;
// name | birth
// -------+------------
// a**** | 1970-01-01
カスタム関数
ユーザー定義関数 (UDF) をテーブル列に添付できます。マスキングに使用される UDF は、マスクされたテーブルと同じ keyspace に属している必要があります。マスクする列の値は、添付された UDF の最初の引数として渡されます。したがって、列に添付された UDF は少なくとも 1 つの引数を持つ必要があり、その引数はマスクされた列と同じ型である必要があります。また、添付された UDF は、マスクされた列と同じ型の値を返す必要があります。
CREATE FUNCTION redact(input text)
CALLED ON NULL INPUT
RETURNS text
LANGUAGE java
AS 'return "redacted";';
CREATE TABLE patients (
id timeuuid PRIMARY KEY,
name text MASKED WITH redact(),
birth date
);
これにより、テーブルスキーマと関数間に依存関係が作成されます。この依存関係が存在する間は、関数を削除しようとする試みは拒否されます。したがって、関数を削除する前に、テーブルのマスク列を削除する必要があります。
ALTER TABLE patients ALTER name
DROP MASKED;
列、またはその列を含むテーブル、またはその列を含むキースペースを削除すると、依存関係も削除されます。
集計関数は、マスキング関数として使用できません。