はじめに
様々なデータを抱える現代の企業では、自社の規模や状況に応じた最適なデータガバナンスが展開されています。
その中には 職員やユーザーの役割に従って、閲覧できるデータを管理者が制御する こともあります。
Amazon Redshiftでは、各ユーザーやロール、細かい条件によってデータをマスキングできる動的データマスキング(DDM) という機能があります。
多くのデータを扱うRedshiftで、かなり簡単にデータマスキングを実現できる点に興味を持ち、ハンズオンを実施しました。
本記事では、Amazon Redshiftの動的データマスキング(DDM)を利用して、ロール別にマスキングできることを確認していきます。
サービス概要
Amazon Redshiftは、大規模データ(テラバイト、ペタバイト級)に対して高速にSQL実行できるフルマネージド型データウェアハウスサービスです。
このセクションでは、Redshiftの列指向データベースや動的データマスキング(DDM)について紹介します。
列指向データベース
通常のリレーショナルデータベースは行指向のデータベースですが、Redshiftは列指向のデータベースです。 行指向データベースでは1つのレコードを1つのディスクブロックに保存されるのに対して、列指向データベースでは複数の行の1つの列の値がディスクブロックに保存されます。
以下の画像は、AWS公式ドキュメントに公開されている行指向データベースと列指向データベースのイメージです。


参考
動的データマスキング(DDM)
Amazon Redshiftの動的データマスキング(DDM)はユーザーやロール、細かい条件によって機密データをマスキングすることができます。条件はマスキングポリシーによって柔軟に設定できます。マスキングでは任意の文字列を設定できるので、仮名表記やアルファベット表記に変換するといった使い方も可能です。
マスキングの処理には、SQLやPythonで記述されたユーザー定義関数、またはAWS Lambdaを使用します。
本記事のハンズオンでは、動的データマスキングの使い方をステップごとに説明していきます。
参考
実装
ハンズオンの背景として、以下のような状況を想定します。
東京にある病院では、Amazon Redshiftを使用してデータを扱っています。
データにアクセスするのは受付、医者、研究者の3つの職種です。
それぞれの職種が閲覧できるデータは以下の通りです。
・受付
・患者ID
・患者名
・都道府県
・クレジットカード番号の下4桁(都道府県が「東京都」の時のみ)
・医者
・患者ID
・患者名
・都道府県
・クレジットカード番号の下4桁(都道府県が「東京都」の時のみ)
・病名
・研究者
・患者ID
・都道府県
・病名
データエンジニアとして、職種によって表示するデータを変える仕組みを提供する必要があります。
閲覧可能データを表にまとめると以下のようになります。
| 項目 | 受付 | 医者 | 研究者 |
|---|---|---|---|
| 患者ID | 〇 | 〇 | 〇 |
| 患者名 | 〇 | 〇 | × |
| 都道府県 | 〇 | 〇 | 〇 |
| クレジットカード番号 | △ (条件付き) | △ (条件付き) | × |
| 病名 | × | 〇 | 〇 |
上記のアクセス制御を達成するために、今回のハンズオンでは以下の流れでAmazon Redshiftの動的データマスキングを使っていきます。なお、今回はコスト削減のためAmazon Redshift Serverlessを使用します。VPC、サブネット、セキュリティグループは前提として作成しているものとします。
- Amazon Redshift Serverlessのネームスペース、ワークグループを作成する
- Redshiftのクエリエディタからテーブルを作成し、ダミーデータを挿入する
- ロール、ユーザーを作成し権限をアタッチする
- 動的データマスキングポリシーを作成する
- 各ユーザーからデータを参照し、マスキングを確認する
今回のハンズオンは以下のような構成になります。

Amazon Redshift Serverlessのネームスペース、ワークグループを作成する
まず、Amazon Redshift Serverlessを使うために、ネームスペース、ワークグループを作成していきます。
Redshiftの利用が初めての方は、トップページにアクセスすると以下のようなページが表示されます。オレンジ色の「Redshift Serverless の無料トライアルをお試しください」というボタンをクリックし、Redshift Serverlessを設定していきます。

すでにRedshiftを利用したことがある方は、サイドバーから「ワークグループの設定」ページ、もしくはダッシュボードにアクセスし「ワークグループを作成」ボタンをクリックすることで、新しいワークグループを作成することが可能です。


作成画面は以下のようになっています。ネームスペースの名前などを順に設定していきます。

以下の画面のようにベースRPU容量を設定できます。今回のハンズオンでは少量のデータのみ扱うので最小の4を設定します。
RPUとは
RPU(Redshift Processing Unit)とは、ワークロードの処理に使用されるコンピューティング容量(リソース)の測定単位です。
Amazon Redshift Serverlessではワークロードの要件に合わせて自動でリソースがスケールアップもしくはスケールダウンします。
ここで設定したのはRedshiftの使用を始めるときのRPUの初期値になります。

「ネットワークとセキュリティ」のセクションでVPCやサブネットなどを設定していきます。Redshift Serverlessは最低2つのサブネットを必要としています。

Autonomicsは、クエリパフォーマンスを向上させ、ストレージコストと最適化を自律管理する機能です。以下の設定ではこのAutonomicsに常に追加のコンピューティングリソースを割り当てることが可能です。デフォルトでは無効になっています。今回のハンズオンでは無効のままにしておきます。
参考

以上でRedshift Serverlessの設定は完了です。セットアップには数分かかります。
設定後以下のポップアップが表示されますが、こちらはセットアップ完了まで消すことはできません…

完了すると以下のようになります。「次へ」をクリックするとダッシュボードへ遷移します。

ダッシュボードは以下のようになります。

Redshiftのクエリエディタからテーブルを作成し、ダミーデータを挿入する
今回のハンズオンで使用するテーブルをRedshift上のdevデータベースに作成していきます。
まずダッシュボード右上の「クエリデータ」ボタンから、「クエリエディタ v2」をクリックします。

クエリエディタにアクセスすると以下のような見た目になっています。

左のペイン、もしくは上部の「Cluster or wor…」というボタンからワークグループに接続していきます。

クリックすると以下のようなポップアップが表示され、どのようにワークグループに接続するか選択することが可能です。
今回は「Federated user」を選択します。

接続後、以下のようになり作成したblog-handson-redshift-workgroupのdevデータベースにクエリを投げることが可能になりました。

それでは、今回のハンズオンで扱うテーブルを作成していきます。
patient_recordsテーブルを作成し、以下のようなダミーデータを挿入します。
-- テスト用テーブルの作成
CREATE TABLE patient_records (
patient_id INT PRIMARY KEY, -- 患者のID
patient_name VARCHAR(50), -- 患者の名前
prefecture VARCHAR(20), -- 都道府県
credit_card VARCHAR(19), -- クレジットカード番号
disease_name VARCHAR(50) -- 病名
);
-- ダミーデータの挿入
INSERT INTO patient_records VALUES
(1, '佐藤 健太', '東京都', '1111-1111-1111-1111', '急性胃炎'),
(2, '鈴木 花子', '大阪府', '2222-2222-2222-2222', 'スギ花粉症'),
(3, '高橋 勇気', '北海道', '3333-3333-3333-3333', '2型糖尿病'),
(4, '田中 美咲', '福岡県', '4444-4444-4444-4444', '高血圧症'),
(5, '伊藤 隆', '愛知県', '5555-5555-5555-5555', '腰椎椎間板ヘルニア');

ちゃんとデータが入っているか確認しましょう。

これでデータの準備は完了です。
ロール、ユーザーを作成し権限をアタッチする
このセクションでは、ロールとユーザーを作成し、ロールに権限を与えていきます。
権限やポリシーはロールに付与し、新規ユーザーには適切なロールを付与するという運用方針で進めていきます。
以下に各職種とロール名の紐づけをまとめました。
| 職種 | ロール名 |
|---|---|
| 受付 | reception_role |
| 医者 | doctor_role |
| 研究者 | researcher_role |
実行SQLは以下のようになります。
-- ① ロールの作成 CREATE ROLE doctor_role; CREATE ROLE reception_role; CREATE ROLE researcher_role; -- ② 検証用ユーザーの作成 CREATE USER doctor_user PASSWORD 'DoctorPass123!'; CREATE USER reception_user PASSWORD 'ReceptionPass123!'; CREATE USER researcher_user PASSWORD 'ResearcherPass123!'; -- ③ ユーザーにロールを付与 GRANT ROLE doctor_role TO doctor_user; GRANT ROLE reception_role TO reception_user; GRANT ROLE researcher_role TO researcher_user; -- ④ テーブルへのアクセス権限(SELECT)をロールに付与 GRANT SELECT ON patient_records TO ROLE doctor_role; GRANT SELECT ON patient_records TO ROLE reception_role; GRANT SELECT ON patient_records TO ROLE researcher_role;

動的データマスキングポリシーを作成する
いよいよ本記事のメインテーマである動的データマスキングを作成していきます。
まずは患者名をマスキングするポリシーを作成します。条件は「ロールが研究者の場合は、患者名をマスキングする」です。
WITH句で条件に使用する列やマスキング対象の列を指定します。
USER_IS_MEMBER_OFはAmazon Redshift固有の関数で、ユーザーがロールまたはグループのメンバーである場合は true を返します。
-- 1. 患者名のマスキングポリシー(研究者の場合は *** に置換)
CREATE MASKING POLICY mask_patient_name
WITH (patient_name varchar(50))
USING (
CASE
WHEN USER_IS_MEMBER_OF(CURRENT_USER, 'researcher_role') THEN '***'
ELSE patient_name
END
);
MASKING周辺に赤線が引かれていますが、おそらくクエリエディタがPostgreSQLの構文に従っており、MASKINGはPostgreSQLに存在しないため指摘されています。動作に影響はないためスルーします。

次に病名をマスキングするポリシーを作成します。
条件は「ロールが受付の場合は、病名をマスキングする」です。
-- 2. 病名のマスキングポリシー(受付の場合は [CONFIDENTIAL] に置換)
CREATE MASKING POLICY mask_disease_name
WITH (disease varchar(50))
USING (
CASE
WHEN USER_IS_MEMBER_OF(CURRENT_USER, 'reception_role') THEN '[CONFIDENTIAL]'
ELSE disease
END
);

最後にクレジットカード番号をマスキングするポリシーを作成します。
条件は「ロールが医者または受付の場合かつ、都道府県が東京都の場合は、クレジットカード番号の下4桁を表示する。それ以外は全桁マスキングする」です。
-- 3. クレジットカードのマスキングポリシー
-- 「医者または受付」かつ「東京都」なら下4桁表示、それ以外は全桁マスク
CREATE MASKING POLICY mask_credit_card_conditional
WITH (credit_card varchar(19), prefecture varchar(20))
USING (
CASE
WHEN (USER_IS_MEMBER_OF(CURRENT_USER, 'doctor_role') OR USER_IS_MEMBER_OF(CURRENT_USER, 'reception_role'))
AND prefecture = '東京都'
THEN 'XXXX-XXXX-XXXX-' || RIGHT(credit_card, 4)
ELSE 'XXXX-XXXX-XXXX-XXXX'
END
);

以上でマスキングポリシーの作成は完了です。
次に作成したポリシーをすべてのロールに付与していきます。
まずは患者名ポリシーを適用します。
ON句にrelation_name(output_column_names)でテーブル名と出力であるマスキング対象の列名を指定します。
-- 患者名ポリシーの適用 ATTACH MASKING POLICY mask_patient_name ON patient_records(patient_name) TO PUBLIC;

次に病名ポリシーを適用します。
-- 病名ポリシーの適用 ATTACH MASKING POLICY mask_disease_name ON patient_records(disease_name) TO PUBLIC;

最後にクレジットカード番号ポリシーを適用します。
上記2つのポリシーは入力と出力のカラム名が同一であったため、USINGを使用しませんでしたが、クレジットカード番号ポリシーは入力に都道府県を使用するため、USINGで明示的に入力カラムを設定します。
-- クレジットカードポリシーの適用(判定用にprefecture列も一緒に指定) ATTACH MASKING POLICY mask_credit_card_conditional ON patient_records(credit_card) USING (credit_card, prefecture) TO PUBLIC;

これでポリシーの準備は完了です。次のセクションで実際にマスキングされている様子を確認します。
参考
各ユーザーからデータを参照し、マスキングを確認する
それでは、各ユーザーから患者データを参照し、マスキングが正しくされているか確認していきます。
まずは「受付」ユーザーにログインしてデータを確認していきます。
管理者でログインしている場合、SET SESSION AUTHORIZATIONコマンドでセッションの権限を切り替えることができます。
SET SESSION AUTHORIZATION reception_user; SELECT * FROM patient_records ORDER BY patient_id;

病名がすべてマスキングされています。クレジットカード番号も、都道府県が東京都の時のみ下4桁が表示されています。
次に「研究者」ユーザーにログインしてデータを確認していきます。
SET SESSION AUTHORIZATION researcher_user; SELECT * FROM patient_records ORDER BY patient_id;

患者名とクレジットカード番号がすべてマスキングされているのが確認できました。
最後に「医者」ユーザーにログインしてデータを確認していきます。
SET SESSION AUTHORIZATION doctor_user; SELECT * FROM patient_records ORDER BY patient_id;

クレジットカード番号が「受付」ユーザーと同じ方法でマスキングされているのが確認できました。
動的データマスキングを利用することで、同じクエリでもロールによって閲覧できるデータをコントロールすることができました。
おわりに
本記事ではAmazon Redshiftの動的データマスキングを利用し、ロールによって異なるマスキングがされることを確認しました。多くのデータを扱う企業にとって、機密情報漏洩のリスクを抑える非常に強力な機能です。
今回のハンズオンで、簡単にデータマスキングの設定を行えることに驚きました。柔軟に条件を設定できるので、複雑なマスキングも簡単に行えるかと思います。
ハンズオンで苦労した点は、Amazon Redshiftが固有のSQL関数を使用することです。例えば、ユーザーのロールを確認するためにPostgreSQLのPG_HAS_ROLE関数を使おうと試しましたが、Amazon Redshiftはこの関数をサポートしていないため以下のエラーが出力されてしまいました。
ERROR: function pg_has_role(character, "unknown", "unknown") does not exist Hint: No function matches the given name and argument types. You may need to add explicit type casts.
そのため、USER_IS_MEMBER_OFという固有の関数を使う必要がありました。
データ活用が進むほどセキュリティの重要性も増します。システムの設計・構築から運用に至るまで、データを適切に制限するアプローチを知っておくことで、より安全で信頼性の高いデータ活用を実現できます。
本記事をきっかけにデータ保護に興味を持っていただけると幸いです。
We Are Hiring!
今回のハンズオンで実装したようなデータを安全に管理する仕組みを、業務でも構築したいと感じた方もいらっしゃるのではないでしょうか。
FindConsultingでは、データ分析基盤の構築において、ロールごとのアクセス制御やデータガバナンス設計まで含めて携わるエンジニアが活躍しています。
こういったデータ分析基盤やアクセス制御の設計を活かした仕事に興味がある方は、ぜひ一緒に働きませんか?
現在、FindConsultingではデータ分析基盤の構築に興味のある仲間を募集しています。
まずはカジュアル面談からでも、ぜひお気軽にお声がけください。


