PII データセット用の Cloud DLP 匿名化変換テンプレートの作成

このチュートリアルでは、Cloud データ損失防止(Cloud DLP)テンプレートを使用して大規模な個人情報(PII)データセットの匿名化変換を作成、管理する方法について説明します。このチュートリアルでは、ユースケースに適した変換を選択する方法についても説明します。

このドキュメントはシリーズの一部です。

このチュートリアルは、ユーザーに基本的なシェル スクリプトの知識があることを前提としており、エンタープライズ セキュリティ管理者を対象としています。

リファレンス アーキテクチャ

このチュートリアルでは、次の図に示されている構成(DLP テンプレートとキー)の管理セクションについて説明します。

匿名化構成のアーキテクチャ

このアーキテクチャは、匿名化方法と暗号鍵を公開しないように、少数のユーザー グループ(セキュリティ管理者など)のみがアクセスできるマネージドの匿名化構成で構成されます。

目標

  • サンプル データセットの Cloud DLP 変換を設計します。
  • 変換の構成を格納する Cloud DLP テンプレートを作成します。

費用

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    [プロジェクトの選択] ページに移動

  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud Console で、Cloud Shell をアクティブにします。

    Cloud Shell をアクティブにする

    Cloud Console の下部にある Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。gcloud コマンドライン ツールなどの Cloud SDK がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

  5. このチュートリアルでは、Cloud Shell からすべてのコマンドを実行します。
  6. Cloud Shell で、Cloud DLP、Cloud Key Management Service、BigQuery、Cloud Storage、Dataflow、Cloud Build API を有効にします。
    gcloud services enable dlp.googleapis.com
    gcloud services enable cloudkms.googleapis.com
    gcloud services enable bigquery.googleapis.com
    gcloud services enable storage-component.googleapis.com
    gcloud services enable dataflow.googleapis.com
    gcloud services enable cloudbuild.googleapis.com
    

Cloud Storage バケットの作成

このシリーズでは、2 つの Cloud Storage バケットが必要です。最初のバケットはサンプル データセットを格納し、2 番目のバケットはこのシリーズの次のパート(自動化された Dataflow パイプラインの実行による PII データセットの匿名化)で使用される自動化されたパイプライン用の一時データを格納します。

  1. Cloud Shell で、2 つの Cloud Storage バケットを作成します(REGIONus-central1 などの選択した Dataflow リージョンに置き換えます)。

    export REGION=REGION
    export PROJECT_ID=$(gcloud config get-value project)
    export DATA_STORAGE_BUCKET=${PROJECT_ID}-data-storage-bucket
    export DATAFLOW_TEMP_BUCKET=${PROJECT_ID}-dataflow-temp-bucket
    gsutil mb -c standard -l ${REGION} gs://${DATA_STORAGE_BUCKET}
    gsutil mb -c standard -l ${REGION} gs://${DATAFLOW_TEMP_BUCKET}
    

サンプル ファイルのダウンロード

サンプル ファイルをダウンロードして、匿名化変換に必要な列を特定します。

  1. Cloud Shell で、ローカルマシンにこのチュートリアルで使用するサンプル データセットとスクリプトをダウンロードします。

    curl -X GET \
        -o "sample_data_scripts.tar.gz" \
        "http://storage.googleapis.com/dataflow-dlp-solution-sample-data/sample_data_scripts.tar.gz"
    
  2. ファイルの内容を解凍して展開します。

    tar -zxvf sample_data_scripts.tar.gz
    
  3. 転送を検証するには、出力がダウンロードした次のファイルのリストと一致していることを確認します。

    wc -l solution-test/CCRecords_1564602825.csv
    

    次のような出力が表示されます。

    100001 solution-test/CCRecords_1564602825.csv
    
  4. DLP 匿名化を必要とする列を特定するには、CSV ファイルのヘッダー レコードを調べます。

    head -1 solution-test/CCRecords_1564602825.csv
    

    次のように出力されます。

    ID,Card Type Code,Card Type Full Name,Issuing Bank,Card Number,Card Holder's Name,Issue Date,Expiry Date,Billing Date,Card PIN,Credit Limit,Age,SSN,JobTitle,Additional Details
    

    各 CSV ファイルの最初の行ではデータスキーマと列名が定義されます。抽出されたデータセットには、直接的な識別子(SSNCard Holder's Name)と準識別子AgeJobTitle)が含まれています。

必要な変換を決定するプロセスは、ユースケースによって異なります。このチュートリアルで使用する変換のサンプル データセットのリストを次の表にまとめます。

列名 InfoType(カスタムまたは組み込み) クラウド DLP 変換のタイプ 変換の説明
Card PIN なし 暗号ハッシュを使用した暗号化 暗号ハッシュ暗号化は元のデータを、元に戻せない base64 エンコード値に置き換えます。
Card Number なし 確定的暗号化(DE)を使用した暗号化 DE は、元のデータを base64 エンコードの暗号化された値に置き換え、元の文字セットや長さを保持しません。
Card Holder's Name なし 確定的暗号化(DE)を使用した暗号化 DE は、元のデータを base64 エンコードの暗号化された値に置き換え、元の文字セットや長さを保持しません。
SSN (Social Security Number) なし マスキング文字 マスキングは暗号を使用しない手法で、指定した文字で元のデータの一部または全体をマスクできます。
Age なし バケット化(一般的な値) バケット化変換は、識別可能な値を汎用値に置き換えるのに役立ちます。
Job Title なし バケット化(一般的な値) バケット化変換は、識別可能な値を汎用値に置き換えるのに役立ちます。
Additional Details 組み込み: IBAN_CODE, EMAIL_ADDRESS, PHONE_NUMBER
カスタム: ONLINE_USER_ID
トークンによる置換 置換変換は、元のデータを任意の値に置き換えます。

BigQuery データセットの作成

  1. Cloud DLP パイプラインが匿名化されたデータを格納できるデータセットを BigQuery に作成します(LOCATION は、US など任意の BigQuery のロケーションに置き換えます)。

    bq mk --location=LOCATION \
        --description="De-Identified PII Dataset" \
        deid_dataset
    

このチュートリアルのステップでは、機密データが Cloud Storage に CSV などの列区切り形式で格納されることを想定しています。このチュートリアルで使用するパイプラインは、データファイル内に含まれる CSV ヘッダー レコードの内容に基づいて BigQuery テーブルを自動的に作成します。このヘッダー レコードが CSV ファイルから削除されると、PII データが BigQuery で公開されるおそれがあります。

鍵暗号鍵(KEK)の作成

トークン暗号鍵(TEK)は、Cloud Key Management Service(Cloud KMS)から取得した別の鍵(鍵暗号鍵)で保護(ラップ)されます。

  1. Cloud Shell で、TEK をローカルに作成します。このチュートリアルでは、ランダムな 32 文字の base-64 暗号鍵を生成します。

    export TEK=$(openssl rand -base64 32); echo ${TEK}
    

    出力は次の形式で生成されたランダムキーです。

    MpyFxEQKYKscEJVOiKMuEPdwqdffk4vTF+qwGwrp7Ps=
    

    base-2 の有効なキーサイズは、192 ビットサイズの (64)^32 =(2^6)^32=2^192 または AES 初期化ベクトル(IV)です。このキーはスクリプトの後半で使用されます。

  2. 鍵、キーリング、KEK ファイルを変数としてエクスポートします。

    export KEY_RING_NAME=my-kms-key-ring
    export KEY_NAME=my-kms-key
    export KEK_FILE_NAME=kek.json
    
  3. Cloud Build サービス アカウントの Cloud KMS 管理者と鍵暗号化のロールを有効にします。

    export PROJECT_NUMBER=$(gcloud projects list \
        --filter=${PROJECT_ID} --format="value(PROJECT_NUMBER)")
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
        --role roles/cloudkms.cryptoKeyEncrypter
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
        --role roles/cloudkms.admin
    
  4. 次の GitHub リポジトリのクローンを作成し、プロジェクトのルートフォルダに移動します。

    git clone https://github.com/GoogleCloudPlatform/dlp-dataflow-deidentification.git
    cd dlp-dataflow-deidentification
    
  5. KEK を作成します。

    gcloud builds submit . \
        --config dlp-demo-part-1-crypto-key.yaml \
        --substitutions \
        _GCS_BUCKET_NAME=gs://${DATA_STORAGE_BUCKET},_KEY_RING_NAME=${KEY_RING_NAME},_KEY_NAME=${KEY_NAME},_TEK=${TEK},_KEK=${KEK_FILE_NAME},_API_KEY=$(gcloud auth print-access-token)
    
  6. KEK が正常に作成されたことを確認します。

    gsutil cat gs://${DATA_STORAGE_BUCKET}/${KEK_FILE_NAME}
    

    出力は次のようになります。

    {
      "name": "kms-key-resource-path",
      "ciphertext": "kms-wrapped-key",
      "ciphertextCrc32c": "checksum"
    }
    

    出力に関する注意事項:

    • kms-key-resource-path: KEK のリソースパス(projects/${PROJECT_ID}/locations/global/keyRings/${KEY_RING_NAME}/cryptoKeys/${KEY_NAME}/cryptoKeyVersions/1 形式)。

    • kms-wrapped-key: Cloud KMS でラップされた TEK の Base64 エンコード値。

    • checksum: 暗号テキストの CRC32C チェックサム。

Cloud DLP テンプレートの作成

この時点で、サンプル データセットの調査と、必要な Cloud DLP 変換についての決定を終えています。暗号変換を必要とする列の場合は、鍵暗号鍵(KEK)も作成しています。次に、Cloud Build スクリプトを実行し、必要な変換と KEK に基づいて Cloud DLP テンプレートを作成します。

Cloud DLP のサービス アカウントを作成する

  1. Cloud Shell で、サービス アカウントを作成します。

    export SERVICE_ACCOUNT_NAME=my-service-account
    gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
        --display-name "DLP Demo Service Account"
    
  2. service-account-key.json という名前のサービス アカウント用の JSON API キーファイルを作成します。

    gcloud iam service-accounts keys create \
        --iam-account ${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \
        service-account-key.json
    
  3. サービス アカウントに project editorstorage admin ロールを割り当てます。

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \
        --role roles/editor
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \
        --role roles/storage.admin
    
  4. サービス アカウントを有効にします。

    gcloud auth activate-service-account --key-file service-account-key.json
    

テンプレートを作成する

  1. Cloud Shell で、Cloud Build スクリプトを実行してテンプレートを作成します。

    gcloud builds submit . \
        --config dlp-demo-part-2-dlp-template.yaml \
        --substitutions \
        _KEK_CONFIG_FILE=gs://${DATA_STORAGE_BUCKET}/${KEK_FILE_NAME},_GCS_BUCKET_NAME=gs://${DATA_STORAGE_BUCKET},_API_KEY=$(gcloud auth print-access-token)
    
  2. 匿名化テンプレートが正常に作成されたことを確認します。

    gsutil cp gs://${DATA_STORAGE_BUCKET}/deid-template.json .
    cat deid-template.json
    

    出力は次のようになります。

    {
      "name": "projects/<project_id>/deidentifyTemplates/<template_id>",
      "displayName": "Config to DeIdentify Sample Dataset",
      "description": "De-identifies Card Number, Card PIN, Card Holder's Name, SSN, Age, Job Title, Additional Details and Online UserId Fields",
      "createTime": "2019-12-01T19:21:07.306279Z",
      "updateTime": "2019-12-01T19:21:07.306279Z",
      "deidentifyConfig": {
        "recordTransformations": {
          "fieldTransformations": [
            {
              "fields": [
                {
                  "name": "Card PIN"
                }
              ],
              "primitiveTransformation": {
                "cryptoHashConfig": {
                  "cryptoKey": {
                    "kmsWrapped": {
                      "wrappedKey": "<var>kms-wrapped-key</var>",
                      "cryptoKeyName": "<var>kms-key-resource-name</var>"
                    }
                  }
                }
              }
            },
            {
              "fields": [
                {
                  "name": "SSN"
                }
              ],
              "primitiveTransformation": {
                "characterMaskConfig": {
                  "maskingCharacter": "*",
                  "numberToMask": 5,
                  "charactersToIgnore": [
                    {
                      "charactersToSkip": "-"
                    }
                  ]
                }
              }
            },
            {
              "fields": [
                {
                  "name": "Age"
                }
              ],
              "primitiveTransformation": {
                "bucketingConfig": {
                  "buckets": [
                    {
                      "min": {
                        "integerValue": "18"
                      },
                      "max": {
                        "integerValue": "30"
                      },
                      "replacementValue": {
                        "stringValue": "20"
                      }
                    },
                    {
                      "min": {
                        "integerValue": "30"
                      },
                      "max": {
                        "integerValue": "40"
                      },
                      "replacementValue": {
                        "stringValue": "30"
                      }
                    },
                    {
                      "min": {
                        "integerValue": "40"
                      },
                      "max": {
                        "integerValue": "50"
                      },
                      "replacementValue": {
                        "stringValue": "40"
                      }
                    },
                    {
                      "min": {
                        "integerValue": "50"
                      },
                      "max": {
                        "integerValue": "60"
                      },
                      "replacementValue": {
                        "stringValue": "50"
                      }
                    },
                    {
                      "min": {
                        "integerValue": "60"
                      },
                      "max": {
                        "integerValue": "99"
                      },
                      "replacementValue": {
                        "stringValue": "60"
                      }
                    }
                  ]
                }
              }
            },
            {
              "fields": [
                {
                  "name": "JobTitle"
                }
              ],
              "primitiveTransformation": {
                "bucketingConfig": {
                  "buckets": [
                    {
                      "min": {
                        "stringValue": "CIO"
                      },
                      "max": {
                        "stringValue": "CIOz"
                      },
                      "replacementValue": {
                        "stringValue": "Executive"
                      }
                    },
                    {
                      "min": {
                        "stringValue": "CEO"
                      },
                      "max": {
                        "stringValue": "CEOz"
                      },
                      "replacementValue": {
                        "stringValue": "Executive"
                      }
                    },
                    {
                      "min": {
                        "stringValue": "Vice President"
                      },
                      "max": {
                        "stringValue": "Vice Presidentz"
                      },
                      "replacementValue": {
                        "stringValue": "Executive"
                      }
                    },
                    {
                      "min": {
                        "stringValue": "Software Engineer"
                      },
                      "max": {
                        "stringValue": "Software Engineerz"
                      },
                      "replacementValue": {
                        "stringValue": "Engineer"
                      }
                    },
                    {
                      "min": {
                        "stringValue": "Product Manager"
                      },
                      "max": {
                        "stringValue": "Product Managerz"
                      },
                      "replacementValue": {
                        "stringValue": "Manager"
                      }
                    }
                  ]
                }
              }
            },
            {
              "fields": [
                {
                  "name": "Additional Details"
                }
              ],
              "infoTypeTransformations": {
                "transformations": [
                  {
                    "infoTypes": [
                      {
                        "name": "EMAIL_ADDRESS"
                      },
                      {
                        "name": "PHONE_NUMBER"
                      },
                      {
                        "name": "IBAN_CODE"
                      },
                      {
                        "name": "ONLINE_USER_ID"
                      }
                    ],
                    "primitiveTransformation": {
                      "replaceWithInfoTypeConfig": {}
                    }
                  }
                ]
              }
            },
            {
              "fields": [
                {
                  "name": "Card Holder's Name"
                },
                {
                  "name": "Card Number"
                }
              ],
              "primitiveTransformation": {
                "cryptoDeterministicConfig": {
                  "cryptoKey": {
                    "kmsWrapped": {
                      "wrappedKey": "<var>kms-wrapped-key</var>",
                      "cryptoKeyName": "<var>kms-key-resource-name</var>"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
  3. 検査テンプレートが正常に作成されたことを確認します。

    gsutil cp gs://${DATA_STORAGE_BUCKET}/inspect-template.json .
    cat inspect-template.json
    

    出力は次のようになります。

    {
      "name": "projects/<project_id>/inspectTemplates/<template_id>",
      "displayName": "Config to Inspect Additional Details Column",
      "description": "Inspect template for built in info types EMAIL_ADDRESS, PHONE_NUMBER, IBAN_CODE and custom Info type ONLINE_USER_ID",
      "createTime": "2019-12-01T19:21:08.063415Z",
      "updateTime": "2019-12-01T19:21:08.063415Z",
      "inspectConfig": {
        "infoTypes": [
          {
            "name": "IBAN_CODE"
          },
          {
            "name": "EMAIL_ADDRESS"
          },
          {
            "name": "PHONE_NUMBER"
          }
        ],
        "minLikelihood": "LIKELY",
        "limits": {},
        "customInfoTypes": [
          {
            "infoType": {
              "name": "ONLINE_USER_ID"
            },
            "regex": {
              "pattern": "\\b:\\d{16}"
            }
          }
        ]
      }
    }
  4. 再識別テンプレートが正常に作成されたことを確認します。

    gsutil cp gs://${DATA_STORAGE_BUCKET}/reid-template.json .
    cat reid-template.json
    

    出力は次のようになります。

    {
      "name": "projects/<project_id>/deidentifyTemplates/<template_id>",
      "displayName": "Config to ReIdentify Sample Dataset",
      "description": "Used to re-identify Card Number and Card Holder's Name",
      "createTime": "2019-12-01T19:21:07.306279Z",
      "updateTime": "2019-12-01T19:21:07.306279Z",
      "deidentifyConfig": {
        "recordTransformations": {
          "fieldTransformations": [
            {
              "fields": [
                {
                  "name": "Card_Holders_Name"
                },
                {
                  "name": "Card_Number"
                }
              ],
              "primitiveTransformation": {
                "cryptoDeterministicConfig": {
                  "cryptoKey": {
                    "kmsWrapped": {
                      "wrappedKey": "<var>kms-wrapped-key</var>",
                      "cryptoKeyName": "<var>kms-key-resource-name</var>"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }

    再識別テンプレートは匿名化テンプレートに似ていますが、元に戻すことができる変換(この場合は Card Holder's Name フィールドと Card Number フィールド)のみが含まれている点は異なります。

  5. Cloud DLP テンプレート名をエクスポートします。

    export DEID_TEMPLATE_NAME=$(jq -r '.name' deid-template.json)
    export INSPECT_TEMPLATE_NAME=$(jq -r '.name' inspect-template.json)
    export REID_TEMPLATE_NAME=$(jq -r '.name' reid-template.json)
    
  6. 次の変数が存在することを確認します。

    echo ${DATA_STORAGE_BUCKET}
    echo ${DATAFLOW_TEMP_BUCKET}
    echo ${DEID_TEMPLATE_NAME}
    echo ${INSPECT_TEMPLATE_NAME}
    echo ${REID_TEMPLATE_NAME}
    

このチュートリアルは正常に完了しました。次のチュートリアルでは、自動化された Dataflow パイプラインをトリガーしてサンプル データセットを検査、匿名化し、このデータセットを BigQuery に格納します。

クリーンアップ

シリーズのチュートリアルを続行する予定がない場合、課金を停止する最も簡単な方法は、チュートリアル用に作成した Cloud プロジェクトを削除することです。また、リソースを個別に削除することもできます。

プロジェクトの削除

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ