AWS Glue DataBrewで個人を特定できる情報 (PII) の検出と変換処理を試す

GUIでデータプレパレーションができるサービス AWS Glue DataBrew を使って、個人を特定できる情報 (PII) の検出とデータマスキング変換をできます。

GitHubのaws-samplesに、S3にデータセットをアップロードすると自動的に個人を特定できる情報 (PII) を検出して、データマスキング変換した結果をS3に出力するCloud Formationsテンプレートが公開されています。
https://github.com/aws-samples/automating-pii-data-detection-and-data-masking-tasks-with-aws-glue-databrew-and-aws-step-functions

ざっくりポイントをメモ

# Solution概要

- INPUTファイルとOUTPUTファイル（変換済み）はS3を利用
- S3の指定バケットにファイルをULすると、EventBridgeが検知してStep Fnctions（以下SFn）を起動する（イベント駆動）
- SFnはGlue DataBrewを利用して、PII情報検出と変換処理のワークフローを実行する
    - PII情報検出はプロファイルジョブで実行
    - Lambda関数でプロファイルジョブ結果からPII情報有無を参照する
    - データマスキング変換処理はレシピジョブで実行(PII情報が含まれてた場合のみ)
    - 変換処理は`HMAC_SHA256`でハッシュ化し、そのためのシークレット値はSecrets Managerで管理する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/270f27b5-b364-3056-333c-f69ea99d582b.png)

# 各構成要素別ポイントまとめ

- サンプルダミーデータは以下を利用（mockaroroで生成できる https://www.mockaroo.com/）
https://github.com/aws-samples/automating-pii-data-detection-and-data-masking-tasks-with-aws-glue-databrew-and-aws-step-functions/raw/main/data/pii-sample-dataset.csv

- Solution構築のためのCloud Formations（CFn）を実行すると以下の入力パラメータがある
    - `HashingSecretValue` : PII情報をHMAC_SHA256でハッシュ化する際のシークレット値（指定した値はBase64エンコードされてSecrets Managerで保管される）
    - `PIIMatching ThresholdValue` : Glue DataBrewのプロファイルジョブでPII情報検知する際の閾値として利用。例えば80%に指定すると、該当カラムをスキャンして80%以上PIIっぽい情報が検知できたらそのカラムをPII情報を含むカラムとして判定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/373e8dc2-ac9b-8dca-f731-645d06582f6a.png)


## [1] EventBridge でファイル追加を検知

- CFnで`automate-pii-handling-dat-EventBridgeRuleNewDataAr-XXXXXX`というルールが生成される。
- 指定バケットにオブジェクトが追加されたことを検知するイベントパターンでルールを規定する。
- 検知したらターゲットにSFnステートマシンを指定してキックさせる。


イベントパターン）
```JSON
{
  "detail-type": ["Object Created"],
  "source": ["aws.s3"],
  "detail": {
    "bucket": {
      "name": ["gluedatabrew-pii-data-input-45e5c580"]
    }
  }
}
```

参考）
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-s3-object-created-tutorial.html

## [2] Step Functions
- CFnで`StateMachinePIITask-XXXXX`というステートマシンが生成される。
- 上から順に
    - EventBridgeが検知したファイルを元にGlue DataBrewデータセットを作成
    - Glue DataBrewプロファイルジョブを作成（PII検知処理用）
    - Glue DataBrewプロファイルジョブを実行
    - LambdaでS3に出力されるプロファイルジョブ実行結果（JSON）を参照しPII情報カラムを抽出
    - SFn Choiceステートで、PII情報有無によって条件分岐
        - PII情報なし（Lambdaの返却値が`No PII columns found.`なら終了
        - PII情報ありなら、Glue DataBrewの処理継続
    - PII情報マスキングのGlue DataBrewレシピを作成
    - Glue DataBrewプロジェクトを作成
    - Glue DataBrewレシピジョブを実行（PII情報マスキング用）
    - 終了

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/65cacd84-03c6-8348-3d39-9befb923d6cc.png" width=60%>

## [3] Glue DataBrew

### プロファイルジョブ
- CFnで`[データセット名] + -PII-Detection-Job`という名前のプロファイルジョブが生成される
- データプロファイルの設定のPII統計設定が下記の通り有効化されていることがわかる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/209ad185-5ec0-b802-a503-19572979e118.png)
- データ系列的にはこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/4c9e8915-7eab-0f8f-f149-a78ddb45040e.png)
- [データセット] - [データプロファイルの概要]からプロファイルジョブ結果を参照でき、`full_name`、`contact_phone_number`、`email_address`、`registered_credit_card`の4つがPII情報として識別されたことがわかる。
- `spoken_language`はPII列の統計が17%となっており、CFnのパラメータで指定したThreshold（PII判定のための閾値）に満たないため対象外になっている。ちなみにデフォルトでは80%。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/1c274cb3-13be-cb64-13ad-8ff47ba58158.png)

### プロジェクトとレシピジョブ
- CFnで`[データセット名] + -PII-Project`という名前のプロジェクトが生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/a3a921c8-6824-01e8-7f56-0a61590bf892.png)
- レシピをyamlで確認するとこんな感じ↓
    - Operationにハッシュか処理をする`CRYPTOGRAPHIC＿HASH`を指定　
        - https://docs.aws.amazon.com/ja_jp/databrew/latest/dg/recipe-actions.CRYPTOGRAPHIC_HASH.html
    - シークレット値はSecretsManagerから取得
    - 対象カラムは前段のプロファイルジョブで検出したPII情報を含むカラムを指定

```yaml
- Action:
    Operation: CRYPTOGRAPHIC_HASH
    Parameters:
      secretId: >-
        arn:aws:secretsmanager:us-east-1:248933603227:secret:GlueDataBrewPIITaskSecret-TcCV4h
      sourceColumns: >-
        ["full_name","contact_phone_number","email_address","registered_credit_card"]
```

## [4] Lambda
- CFnで`automate-pii-handling-dat-FunctionGlueDataBrewProf-XXXXX`という名前で生成される
- Glue DataBrewのプロファイルジョブが出力したJSONファイルをチェックし、PII検知数がThresholdを超えたカラムをPII情報を含むカラムとしてリストで返却。もしなければ`No PII columns found.`を返却。

```python
import json
import boto3
import os

def lambda_handler(event, context):

  s3Bucket = event["Outputs"][0]["Location"]["Bucket"]
  s3ObjKey = event["Outputs"][0]["Location"]["Key"]

  s3 =boto3.client('s3')
  glueDataBrewProfileResultFile = s3.get_object(Bucket=s3Bucket, Key=s3ObjKey)
  glueDataBrewProfileResult = json.loads(glueDataBrewProfileResultFile['Body'].read().decode('utf-8'))
  columnsProfiled = glueDataBrewProfileResult["columns"]

  PIIColumnsList = []
  for item in columnsProfiled:
    if "entityTypes" in item["entity"]:
      if (item["entity"]["rowsCount"]/glueDataBrewProfileResult["sampleSize"]) >= int(os.environ.get("threshold"))/100:
        PIIColumnsList.append(item["name"])

  if PIIColumnsList == []:
    return 'No PII columns found.'
  else:
    return PIIColumnsList
```

# 実行結果の確認

サンプルデータへの処理結果はS3に出力され、S3 Selectで確認すると以下の通り`full_name`、`contact_phone_number`、`email_address`、`registered_credit_card`の4つのPII情報が自動的に識別されハッシュ化されていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112537/6dc937bc-e49a-929f-125b-b504478ff144.png)