はじめに
Findyでデータエンジニアとして働いている開(hiracky16)です。 この記事ではGoogle Cloudの製品であるCloud DLPを中心に弊社で取り組んでいるデータマスキングについて紹介します。
弊社はFindyやFindy Freelanceなど人材に関する事業を取り扱っているため個人データがより集まりやすい環境にあります。 ファインディの組織が日々拡大しサービス拡張していく中で、利用者の安全性を担保し、データにおけるリスクを低くするためのデータ基盤づくりが求められてきました。 データ基盤には事業部のデータを集約しているため、利用者にすべてを公開してしまうと運用を誤り、思わぬ事故につながる可能性が上がります。 ただ、閲覧できないと困る業務もあり、データの閲覧権限を絞りすぎてもリスクがあります。
今回は、個人データなどのセンシティブなデータを自動で検出・マスキングを行い、業務に必要な場合にのみ閲覧できる状態にする取り組みについてご紹介します。
権限周りの基本設計
マスキングの前に権限周りの基本設計を説明します。 データセットにはレイヤーを設けており、それぞれ次のようになっています。
- source ... ローデータが入っているテーブル
- staging ... ローデータをBigQuery用に加工したテーブル
- intermediate ... CTEなどのテーブル
- mart ... 利用用途ごとに用意したテーブル
まずはデータ基盤を利用するにあたり用途ごとにロールを定義しようと考えました。 用途以外のことができてしまうと誤操作によってデータを書き換えたり、消してしまったりするおそれがあるためです。 データの用途は大きく3つに分けることができ、特定のデータを定期的に見ることやBigQueryコンソールやDataformで自分のほしいデータを作ること、外部ツールにデータを連携することになります。
これらの利用用途ごとに権限を付与するためのロールを作りました。 また1ユーザーごとにロールを付与するのは大変なので、Googleグループを用意しあらかじめ付与しています。 こうすることでグループへの追加・削除によりロールの管理が比較的簡単な操作で可能になります。 更にデータマートに相当するデータセットは用途ごとに作りGoogleグループのメールアドレスをデータセットのIAMメンバーとして追加しておきます。
ロール | できること | Google Cloudプロジェクト上のIAMロール | 対応するGoogleグループ |
---|---|---|---|
管理者 | 全てのデータセットに対して編集 | プロジェクトレベルのオーナー | - |
編集者 | source以外のデータセットへの編集、またDataformなどの周辺サービスの利用 | プロジェクトレベルの「BigQueryユーザー」と「BigQueryデータ編集者」 | editor |
(各データセットの)閲覧者 | 特定のmart_ で始まるデータセットの閲覧 |
プロジェクトレベルの「BigQueryユーザー」とデータセットレベルの「BigQueryデータ閲覧者」 | mart_sales, mart_external_system |
上記のようにデータセットごとにIAMロールを付与するためのTerraform Moduleを公開しているのでよかったらお使いください。 registry.terraform.io
ポリシータグによる動的マスキング
基本的に個人データはsourceからstagingへの伝搬時にセンシティブなデータを省いています。
また上記の通り権限が絞れているので一見問題なさそうに見えますが、mart
データセットの中には業務システムに使うものもあり個人データが含まれます。
そういったデータをグループに属する全員が閲覧できる状態というのは望ましくありません。
このような場合には、カラムレベルでポリシータグを付与し、許可されたユーザーには通常のデータを、許可されていないユーザーにはマスキングされたデータを表示させています。
タグの付与はDataformのconfigで行っています。 次のように書くとテーブルが作られる際にタグを付与してくれます。
config { type: "table", "schema": "stg_hoge", "description": "ユーザーテーブル", "columns": { "id": "ユーザーのID", "email": { description: "メールアドレス", bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"] }, "tel": { description: "電話番号", bigqueryPolicyTags: ["projects/project-hoge/locations/asia-northeast1/taxonomies/fuga/policyTags/piyo"] } }, } ...
マスキングのルールもいろいろなものがあります。 なお今回は試していませんが、BigQuery UDFをルールに追加できます。
動的マスキングの方法はわかりました。 ただ、個人データに対して曖昧な理解のまま運用してしまうと付与忘れや、付与しすぎて情報量が落ちてしまうおそれがあります。 そこで役立つのがCloud DLPです。
Cloud DLPによる個人データ検出
Cloud DLP(Data Loss Prevention)は、機密性の高いデータを検出、分類、保護するために設計されたGoogle Cloudのサービスです。
Cloud DLPにはBigQueryのデータをスキャンして個人データに該当するテーブル、カラムを検出してくれる機能が備わっています。
この検出を定期的に実行することによりポリシータグを付与する候補となるカラムを特定できます。 テーブルはサンプルですが、検査するとデータリスクが中程度〜高のカラムに個人データが含まれていそうなことが一目でわかるようになります。
以下は公式ドキュメントに載っていたイメージになります。
DLP APIを用いてテキスト内の情報をマスキング
ポリシータグを使ったマスキングは値全体をマスクしてしまいますが、ロングテキストの場合一部だけマスクしたいといったニーズが存在します。 例えば、商品レビューのテキストデータをポジネガ判定したい場合、テキスト全てをマスクしてしまうとポジネガ判定に使う情報が落ちてしまいます。
DLP APIを使うとテキスト中の個人情報をマスクできます。 DLP APIによるマスクの手順は「個人データの検出」と「データの匿名化」の2ステップがあります。
「個人データの検出」では事前に用意された検出器(INFO TYPE)を使い検出できます。 INFO TYPEは特定したい情報、例えば名前や電話番号、住所など情報の種類ごとに違います。 INFO TYPEはGCSに置いた辞書から自作でき、固有名詞にも対応できます。 下記が事前に用意されたINFO TYPEのリファレンスです。
「データの匿名化」は検出したINFO TYPEごとにどのように情報をマスクするかを定義します。
DLP APIにはPython ClientがあるのでこれをCloud RunにデプロイしてBigQueryからリモート関数で呼び出せるようにしています。
declare text string; set text = """ 私は山田太郎です。 本日はよろしくお願いします。 山田 090-0000-0000 tensyoku.taro@gmail.com """; select text, `function_dataset.dlp_api`(text) as masked_text;
まとめ
Cloud DLPの機能を使うことでマスキングする術をまとめてみました。 データ利活用が増えることは喜ばしいことですが、常にデータの扱いを気にしながらデータ抽出や分析するのにも限界があります。 これからもデータエンジニアとして安全に意思決定をサポートするデータ基盤を作っていきたいと思っています。
弊社ではデータ基盤を共に育てていくメンバーを募集しています。少しでも興味が湧いた方はカジュアル面談お待ちしております🙏