DLP APIを使ってCSVデータの機密情報をマスキングする方法

# はじめに
こんにちは。
これは、[2021年 NI+C Advent Calendar](https://qiita.com/advent-calendar/2021/niandc_teamgcp) 17日目の記事です。

2年以上前ですが、弊社のメンバーがBigQuery上のデータをCloud Data Loss Prevention(以下DLP)を利用してマスキングする方法について[ブログ](https://www.niandc.co.jp/sol/tech/date20190723_1790.php)を投稿しております。
しかし、そもそもクラウド上に個人情報をアップロードしたくないといった声もあるため、
今回はpythonでローカルのCSVデータをDLP APIを利用してマスキングする方法をご紹介したいと思います。


# Cloud Data Loss Prevention(DLP)とは
簡単に説明すると、機密データの検出・マスキングを自動で行ってくれるサービスです。
今回のように文字列データはもちろん、Google Cloud StorageやBigQueryのデータもマスキングすることが可能です。
詳しくは公式ドキュメントをご覧ください。
https://cloud.google.com/dlp

# 環境
- windows 10
- python 3.7.9
- Google Cloud

# GCPでの事前準備
- GCPプロジェクトの作成
- Cloud Data Loss Prevention (DLP) APIの有効化
- DLP管理者の権限を付与したサービスアカウントの作成
- サービスアカウントキーのダウンロード

# DLP APIを実行する
今回はローカルにある機密情報を含むCSVファイルをマスキングして再びCSVファイルとして出力するプログラムを作成して実行します。

## 入力ファイル
今回は以下のサンプルデータを作成しマスキングを実行しました。

```csv:input_sample.csv
連番,氏名,性別,電話番号,メールアドレス,郵便番号,住所
1,岡山澄江,女,080-9575-8563,sumieokayama@lluoa.zfr.ca,791-3152,愛媛県伊予郡松前町永田4-14-13
2,矢島裕子,女,090-4642-2411,wsftjfquspiihiroko611@muduuojh.pu,711-0931,岡山県倉敷市児島赤崎1-15-4
3,森山俊史,男,080-2080-7860,kddyswkweaacdssichiru9472@zxxv.elf,920-2123,石川県白山市鶴来日詰町1-10-9
4,山川由美子,女,080-8427-8337,yumiko66941@uagzzzb.sw,851-2215,長崎県長崎市鳴見台3-11-12
5,河内光信,男,090-1671-4745,ukawauchi@rpqvkfa.ixi,841-0205,佐賀県三養基郡基山町けやき台4-16-11
```
##  ソースコード
今回は以下のpythonプログラムを作成してDLP APIを実行しました。

```python:data_masking.py
import google.cloud.dlp
import csv
import os
import io

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = '[サービスアカウントキーのパス]'
parent = f'[GCPプロジェクトID]'
input_file = '[入力ファイルのパス]'
output_file = '[入力ファイルのパス]'
info_types = ['PERSON_NAME', 'FIRST_NAME', 'LAST_NAME',
              'EMAIL_ADDRESS', 'PHONE_NUMBER', 'LOCATION'] # マスキング対象項目を定義

def run_dlp(input_str):
    client = google.cloud.dlp_v2.DlpServiceClient()
    min_likelihood = google.cloud.dlp_v2.Likelihood.VERY_UNLIKELY # マスキング対象の検出レベルを定義
    max_findings = 0
    include_quote = True
    item = {"value": input_str}
    inspect_config = {
        "info_types": [{"name": info_type} for info_type in info_types],
        "min_likelihood": min_likelihood,
        "include_quote": include_quote,
        "limits": {"max_findings_per_request": max_findings},
    }

    deidentify_config = {
        "info_type_transformations": {
            "transformations": [
                {
                    "primitive_transformation": {
                        "character_mask_config": {
                            "masking_character": "*", # マスキング後の文字列を定義
                            "number_to_mask": 0,
                            "characters_to_ignore": [{
                                "common_characters_to_ignore": None
                            }]
                        }
                    }
                }
            ]
        }
    }

    response = client.deidentify_content(
        request={
            "parent": parent,
            "deidentify_config": deidentify_config,
            "inspect_config": inspect_config,
            "item": item,
        }
    )
    return response.item.value


def main():

    # 入力ファイルを読み込み、DLP APIを実行
    with open(input_file, "r", encoding="utf-8") as csvfile_open:
        input_str = csvfile_open.read()
        response = run_dlp(input_str)
        # レスポンスを整形し、出力ファイルを生成
        f = io.StringIO()
        f.write(response)
        f.seek(0)
        csv_reader = csv.reader(f)
        read_data = [row for row in csv_reader]
        with open(output_file, "w", encoding='utf8', newline="") as write_csv:
            writer = csv.writer(write_csv)
            writer.writerows(read_data)

    return

main()

```
- 10行目のマスキング対象項目の設定値については以下のinfoTypeのドキュメントを参照 
https://cloud.google.com/dlp/docs/infotypes-reference


- 15行目のマスキング対象の検出レベルは以下の一致の可能性のドキュメントを参照 
https://cloud.google.com/dlp/docs/likelihood

- 参考の公式ドキュメント 
https://cloud.google.com/dlp/docs/libraries#client-libraries-usage-python



## 出力ファイル
以下がマスキング実行の結果として出力されたCSVファイルとなります。
一部住所にマスキングされていない箇所がありますが、情報の特定までには至らない範囲かと思います。

```csv:output_sample.csv
連番,氏名,性別,電話番号,メールアドレス,郵便番号,住所
1,********,女,*************,*************************,************************************4-14-13
2,********,女,*************,*********************************,*************************************
3,********,男,*************,**********************************,**********************************************
4,**********,女,*************,**********************,*********************************
5,********,男,*************,*********************,**************************************

```

# まとめ
初めてDLPを使った際は思った以上にマスキング率が高くて驚きました。
それにも関わらずスキャンデータが月1GB以下であれば無料で利用できるのでさらに驚きです。
非常に取っつきやすいサービスになっておりますので、是非使ってみてください。