ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

PostgreSQL Anonymizer が提供するマスキング方式の解説

概要

PostgreSQL Anonymizer は、PostgreSQL 上で PII(個人識別情報)や機微データをマスク/匿名化する拡張機能です。セキュリティラベルでテーブルや列に対するマスキングルールを宣言する「宣言的」な設計が特徴です。

本記事では利用頻度の高い以下の 3 方式に絞り、仕組み・ユースケース・制限を整理します。また、v2.4.1 を前提に調査しています。

  • Static Masking
  • Dynamic Masking
  • Anonymous Dumps

本記事ではポイントのみまとめているため、詳細は公式ドキュメントを参照ください。
PostgreSQL Anonymizer

Static Masking

仕組み

Static Masking は対象のテーブルの実データを全行更新して置換する方式です。

ユースケース

  • 開発/テスト環境向けのマスクコピーを作る
    • 本番DBのダンプをリストア後、Static Masking でマスクDBを作成します。
  • 退役DBの長期保管
    • 元データを残さない形で保管したい場合に適します(例:分析用にデータを残したいが、機微情報は破棄したい)。

制限

Static Masking の処理中はテーブルがロックされます。

処理には時間がかかります。44GBのデータベースに29個のマスキングルールを適用したところ、約25分間かかったと、公式ドキュメントに記載されています。Anonymous Dumps して、データベースに再ロードするほうが早いケースすらあるようです。

Dynamic Masking

仕組み

Dynamic Masking は MASKED ロールとして宣言されたユーザーに対し、SELECT の結果を返す直前に値を置換します。元データは変更されず、他のロールは元データをそのまま参照します。

ユースケース

  • 本番DBでの役割別見せ分け
    • 開発者や分析者など「データを読めるが機微は不可視」にしたいロール向けに、本番データを変えずマスク表示を実現します。

制限

実際のデータを随時置換するという方式ゆえ、通常ロールと比べ、レスポンスが悪化します。目安として、テーブルに3,4つのルールを適用すると、通常ロールよりレスポンスが約20~30%程度悪化するといわれています。

MASKED ロールとして宣言されたユーザーは以下の操作が制約されます。

  • INSERT/UPDATE/DELETE は禁止です。
  • EXPLAIN を使用できません。

Anonymous Dumps

仕組み

Anonymous Dumps は MASKED ロールとして宣言されたユーザーを使って pg_dump でマスクされたデータをエクスポートします。

ユースケース

  • 安全なスナップショット配布
    • 社外ベンダーへの障害再現データ提供や、社内の検証・分析環境への安全な移送に向きます。CI バッチで夜間にマスクダンプを生成する、といった運用とも相性が良いです。

制限

通常の pg_dump に比べ、概ね 2 倍程度の時間がかかるというベンチマーク結果が公開されています。

各方式のユースケース適合

以下に各方式と想定ユースケースの比較表を示します(○:適している、△:要件次第、×:不向き)。

ユースケース Static Masking Dynamic Masking Anonymous Dumps
本番DBで特定ユーザにのみ動的にデータを隠す × ×
開発/テスト用のマスクコピーを作る ×
社外ベンダーへ障害再現データを渡す ×
退役DB(分析用)の長期保管 ×

「本番DBで特定ユーザにのみ動的にデータを隠す」なら Dynamic Masking の一択です。Static Masking は元データを書き換えてしまいますし、Anonymous Dumps はダンプ出力です。

「開発/テスト用のマスクコピーを作る」であれば、Static Masking か Anonymous Dumps です。本番DBのダンプデータからリストアし、Static Masking を実行する。もしくは本番DBから Anonymous Dumps を用いてマスクしたダンプを取得できます。

「社外ベンダーへ障害再現データを渡す」であれば、Anonymous Dumps でしょう。出力結果をそのまま渡すことができます。Static Masking だと、一旦マスク用DBで処理する手間が必要となります。

「退役DB(分析用)の長期保管」であれば、Static Masking がよいでしょう。Anonymous Dumps でダンプファイルを保管するという手もありますが、リストアの手間がかかります。また、Dynamic Masking は機微情報を持ち続けることになるリスクがあります。

よくある落とし穴

仮名化と匿名化を混同してしまう

仮名化と匿名化の違いは以下の記事を参照ください。
仮名化とは? | Cloudflare

マスキングによって仮名化したとしても、個人を特定できるリスクは依然として残っていることを考慮する必要があります。

マスクルール次第でデータの整合性が失われる

例えば、UNIQUE制約を設定した列に対し、全て "NULL" でマスクするようなケースです。

また、マスクしたことによって外部キー制約の整合性が損なわれることも想定されます。これを回避するために仮名化関数を使用して一意の値を生成することもできますが、他の情報を追加することで個人を特定できるリスクが残ることに注意が必要です。

スキーマ変更時にマスクルールの適用を忘れる

新しい列には自動でルールが付与されないため、DDL 変更のたびにルール点検が必要です。

Static Masking を誤って本番で実行する

大きな事故につながります。不要であれば Static Masking を無効にしましょう。

ALTER SYSTEM SET anon.static_masking TO off

Anonymous Dumps にマスキングルールを含めてしまう

pg_dump のオプションに --no-security-labels を付与して、マスキングルール情報がダンプに含まれないようにします。--exclude-extension="anon" も追加するとなおよいでしょう。