機微なカラム — SSN、クレジットカード、メール、住所 — はサポート、分析、開発のためにクエリ可能であり続けなければなりません。広範な平文アクセスは答えではありません。データマスキングが答えです。GDPR、HIPAA、PCI などのワークロードでは、マスキングは法的要件でもあります。
SQL Server はDynamic Data Maskingをコアに同梱しています。すべてのエディション。2016 年以降。Bytebase Dynamic Data Masking はその前段に位置します。すべての SQL Server ディストリビューションで、そしてフリート内のあらゆる他エンジンでも、1 つのポリシーモデル。申請。レビュー。承認。本記事で両者を比較します。
SQL Server Dynamic Data Masking
DDM は SQL Server 2016 以降(Express を含む全エディション)、Azure SQL Database、Azure SQL Managed Instance、Azure Synapse Analytics、Microsoft Fabric の SQL database で GA です。プラグイン不要。エディションゲート無し。MASKED WITH は CREATE TABLE と ALTER TABLE の一部です。
マスクはカラムごとに定義します。サーバーは UNMASK を持たないプリンシパルに対してクエリ結果を書き換えます。ディスク上のデータは変更されません。
5 つのマスク種別
| Function | 挙動 |
|---|---|
default() | 完全マスク。文字列は XXXX、数値は 0、日時は 1900-01-01、バイナリは 1 バイトのゼロ。 |
email() | 先頭 1 文字と固定の .com サフィックスを露出: aXXX@XXXX.com。 |
random(start, end) | 数値を範囲内のランダム値に置換。クエリごとに再生成。 |
partial(prefix, [padding], suffix) | 任意の文字列マスク。先頭 N と末尾 M 文字を露出し、中央をパディングで埋める。 |
datetime("Y"|"M"|"D"|"h"|"m"|"s") | SQL Server 2022 のみ。datetime の構成要素 — 年、月、日、時、分、秒 — の 1 つをマスク。 |
CREATE TABLE Data.Membership (
MemberID INT IDENTITY(1,1) PRIMARY KEY,
FirstName VARCHAR(100) MASKED WITH (FUNCTION = 'partial(1, "xxxxx", 1)') NULL,
LastName VARCHAR(100) NOT NULL,
Phone VARCHAR(12) MASKED WITH (FUNCTION = 'default()') NULL,
Email VARCHAR(100) MASKED WITH (FUNCTION = 'email()') NOT NULL,
DiscountCode SMALLINT MASKED WITH (FUNCTION = 'random(1, 100)') NULL,
BirthDay DATETIME MASKED WITH (FUNCTION = 'datetime("Y")') NULL
);
-- 既存カラムにマスクを追加。
ALTER TABLE Data.Membership
ALTER COLUMN LastName ADD MASKED WITH (FUNCTION = 'partial(2,"xxxx",0)');
-- UNMASK を持たないユーザーにはマスク値が見える。
EXECUTE AS USER = 'MaskingTestUser';
SELECT FirstName, LastName, Phone, Email FROM Data.Membership;
-- Rxxxxxo Taxxxxo xxxx RXXX@XXXX.com
REVERT;権限
モデルを統制するのは 2 つの権限です:
UNMASK—SELECTで平文を返す。基となるデータが必要なプリンシパルに付与する。ALTER ANY MASK— マスクの追加、変更、削除。テーブルのALTERとは別に、通常はセキュリティ担当者へ付与する。
sysadmin、db_owner、データベースに対する CONTROL を持つ者は常に平文を見られます — CONTROL は両者を暗黙的に含みます。db_owner を持つ DBA は DDM の対象外です。
SQL Server 2022 の粒度の細かい UNMASK
2022 以前、UNMASK はデータベース全体に対するものでした — 一度付与すれば、そのプリンシパルはデータベース内のすべてのマスク済みカラムを見られました。**SQL Server 2022(16.x)**は 4 段階のスコープ付き付与を追加しました:
-- カラム単位: Data.Membership.FirstName のみ。
GRANT UNMASK ON Data.Membership(FirstName) TO ServiceAttendant;
-- テーブル単位: Data.Membership のすべてのマスク済みカラム。
GRANT UNMASK ON Data.Membership TO ServiceLead;
-- スキーマ単位: Data スキーマ配下のすべてのマスク済みカラム。
GRANT UNMASK ON SCHEMA::Data TO ServiceManager;
-- データベース単位: 2022 以前の付与と等価。
GRANT UNMASK TO ServiceHead;付与先は Microsoft Entra(旧 Azure AD)のユーザーやグループに直接指定できます。ディレクトリ駆動のアクセスモデルへ、変換層を挟まず DDM を組み込めます。
DDM がしないこと
- アドホックな推測を防ぐ。
SELECTを持ちUNMASKを持たないプリンシパルは、述語で探りを入れられます —WHERE Salary BETWEEN 99999 AND 100001はマスクされた0を返しますが、どの行が一致したかは露見します。DDM は事故的な露出を塞ぎますが、悪意ある推測は塞ぎません。行レベルセキュリティと監査と併用すべきです。 CONTROL保有者を止める。sysadmin、db_owner、データベースに対するCONTROLは平文を見られます。これらを持つ者を制限してください。- 書き込みをゲートする。 マスク済み
SELECTとUPDATEを持つユーザーは、依然としてカラムを上書きできます。マスクの認可と書き込みの認可は別の判断です。 SELECT INTO/INSERT INTOでマスクを剥がす。UNMASK無しでマスク済みカラムからコピーすると、宛先にマスク値が書き込まれます。環境クローンはマスクを継承します。ETL パイプラインはソース側でUNMASKを必要とします。- 式の中でマスク種別を保つ。 マスク済みカラムを参照する式は常にマスクされますが、必ずデフォルトマスクになります —
LEFT(email, 3)はemail()の形ではなくXXXを返します。 - あらゆるカラム種別に適用する。 Always Encrypted カラム、
FILESTREAM、COLUMN_SET内のスパースカラム、計算列から参照されるカラム、フルテキストインデックスのキー、PolyBase 外部テーブルはマスクできません。 - インデックス付きビューをサポートする。 基テーブルがインデックス付きビューから参照されている場合は非サポート。
- マスク済みカラムでクロスデータベース結合を正しく返す。 リモート側はリンク越しにマスク値を送ります。結合や比較はマスク済みデータ上で実行されます。
- 行をフィルタする。 DDM はカラムをゲートします。行レベル制御が必要ならRow-Level Securityと併用します。
Bytebase Dynamic Data Masking

ネイティブ DDM には文書化された 2 つの隙があります。CONTROL 保有者は平文を見られる。SELECT のみのユーザーは範囲述語で値を推測できる。どちらも同じ設計に由来します — DDM はエンジン内部で結果を書き換えますが、権限と述語はその書き換えの上流で動きます。隙を塞ぐには、結果だけでなくクエリそのものを統制する必要があります。
Bytebase Dynamic Data Masking はクエリを統制します。クエリは Bytebase の SQL Editor を経由します。Bytebase は結果をエディタから出る前にマスクします。バックエンドのインスタンスで db_owner や sysadmin であってもポリシーをバイパスできません。アドホックな推測はアクセス判断になります — Query 権限の付与は組み込みのワークフロー — 申請。レビュー。承認。 — を通り、すべてのステップが監査されます。
ポリシーは固定の優先順位で評価される 3 つのレイヤーから構成されます: マスキング例外 > グローバルマスキングルール > カラムマスキング。
- グローバルマスキングルール。 ワークスペース単位。ルールは上から評価され、最初に一致したものが勝ちます。一致条件は環境、プロジェクト、データベース、データ分類にまたがります。一致するたびに Semantic Type が適用され、それがマスキングアルゴリズム(full、partial、MD5、range、カスタム)を選びます。

- カラムマスキング。 プロジェクト単位のオーバーライド。グローバルルールが該当しない特定カラムに適用します。

- マスキング例外。 指名されたユーザーが特定のデータベースまたはテーブルに対して期限付きの
QueryまたはExport例外を受けます。サービスアカウントは対象外。すべての付与とすべてのアクセスが記録されます。

マスキングは感染性があります。カラムがマスクされると、そのポリシーは依存するすべてのビューと派生構造に伝播します。マスク済みカラム上の式もマスクされたままです — DDM の「すべてが default() に潰れる」という落とし穴はありません。

ポリシーは GitOps でコード化することもできます。
マスキングの決定は監査ログに記録されます。SQL 実行エントリは、マスクされたカラム、Semantic Type、一致したルールというカラム単位のマスキングメタデータを、ユーザー、送信元 IP、ステートメント、行数とともに記録します。例外の付与、例外の行使、ポリシーの編集はファーストクラスの監査イベントです。アクセス判断と強制の証跡は同じレコードに収まります。
強制の境界: Bytebase は SQL Editor を経由するクエリをマスクします。SQL Server に直接到達するトラフィックはバイパスし、そこはネイティブ DDM と UNMASK がカバーします。パターンは対称です — データベースではネイティブ DDM、承認と監査が要る人間のクエリ経路では Bytebase。1 つのポリシーが SQL Server、Azure SQL Database、Azure SQL Managed Instance、Azure Synapse、Fabric SQL database、AWS RDS for SQL Server に適用されます。
比較
| SQL Server Dynamic Data Masking | Bytebase Dynamic Data Masking | |
|---|---|---|
| 互換性 | SQL Server 2016+、Azure SQL、MI、Synapse、Fabric | あらゆる SQL Server ディストリビューション ⭐️ |
| メカニズム | カラム上の MASKED WITH ⭐️ | Bytebase 内のポリシー、SQL Editor で適用 |
| 強制位置 | データベース、全読み取り経路 ⭐️ | SQL Editor |
| マスク種別 | 5 つの組み込み関数 | full、partial、MD5、range、カスタム |
| ポリシー管理 | 各データベースで T-SQL DDL | 集中 UI、付与、監査ログ ⭐️ |
| 権限スコープ | DB / スキーマ / テーブル / カラム(2022+) | プロジェクト、データベース、テーブル、カラム |
| ワークフロー | DDL のみ | 申請。レビュー。承認。 ⭐️ |
| 行レベル制御 | 無し(Row-Level Security と併用) | 無し(アクセスポリシーと併用) |
| 価格 | 無料、全エディション ⭐️ | 有償 |
選び方
- 単一の SQL Server インスタンス、または単一の Azure SQL データベース。クライアントを問わずマスキングを強制したい場合。 ネイティブ DDM を使う。無料。コアに同梱。
UNMASKを持たないプリンシパルに対して BCP エクスポート、SSIS、SELECT INTOをマスクする唯一の選択肢。SQL Server 2022 以降では、2016 のオールオアナッシングモデルよりスコープ付き付与(GRANT UNMASK ON SCHEMA::/ON table(column))を選ぶ。 - 混在フリート — SQL Server を Postgres、MySQL、Snowflake、RDS、マネージドフォークと併用する場合。 Bytebase を使う。1 つのポリシーモデル。すべてのエンジン。すべてのアンマスクに監査付きの付与、アクセスログと同じ場所に記録。
- 両方。 ネイティブ DDM はデータベースでマスクします — 直接接続、エクスポート、アドホックツール。Bytebase は人間のクエリ経路を SQL Editor 経由で統制し、承認と監査を提供します。両者は組み合わさります。
このチュートリアルで Bytebase Dynamic Data Masking を試せます。