为个人身份信息数据集创建 Cloud DLP 去标识化转换模板

本教程介绍如何使用 Cloud Data Loss Prevention (Cloud DLP) 模板为大规模个人身份信息数据集创建和管理去标识化转换。本教程还提供了有关如何为您的使用场景选择适当转换的指导。

本文档是以下系列文章中的一篇:

本教程假定您具备基本的 shell 脚本知识,并且适用于企业安全管理员。

参考架构

本教程演示了“配置(DLP 模板和密钥)管理”部分,如下图所示。

去标识化配置的架构。

此架构包含一个代管式去标识化配置,只有一小部分人(例如安全管理员)可以访问该配置(以避免泄露去标识化方法和加密密钥)。

目标

  • 为示例数据集设计 Cloud DLP 转换。
  • 创建 Cloud DLP 模板以存储转换配置。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 在 Cloud Console 中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Cloud Console 的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Cloud SDK 的 Shell 环境,其中包括 gcloud 命令行工具以及已为当前项目设置的值。该会话可能需要几秒钟时间来完成初始化。

  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 存储分区

在本系列中,您需要两个 Cloud Storage 存储分区。第一个存储分区存储示例数据集,第二个存储分区存储本系列下一个部分(运行自动 Dataflow 流水线以对个人身份信息数据集进行去标识化)中使用的自动流水线的临时数据。

  1. 在 Cloud Shell 中,创建两个 Cloud Storage 存储分区(将 REGION 替换为您选择的 Dataflow 区域,例如 us-central1):

    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(自定义或内置) Cloud 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. BigQuery 中创建数据集,其中 Cloud DLP 流水线可以存储去标识化的数据(将 LOCATION 替换为首选 BigQuery 位置,例如 US):

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

本教程中的步骤假定敏感数据以列分隔格式(通常为 CSV)存储在 Cloud Storage 中。本教程中使用的流水线会根据系统在您的数据文件中找到的 CSV 标题记录的内容自动创建 BigQuery 表。如果此标题记录已从 CSV 文件中移除,则您可能会在 BigQuery 中泄露个人身份信息数据。

创建 KEK(密钥加密密钥)

TEK(令牌加密密钥)会使用 Cloud Key Management Service (Cloud KMS) 中的另一个密钥 (KEK) 进行保护(封装):

  1. 通过 Cloud Shell 在本地创建 TEK。在本教程中,您将生成一个具有 32 个字符的随机 base-64 加密密钥:

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

    输出是一个采用以下格式生成的随机密钥:

    MpyFxEQKYKscEJVOiKMuEPdwqdffk4vTF+qwGwrp7Ps=
    

    base-2 中的有效密钥大小为 (64)^32=(2^6)^32=2^192,或者相当于大小为 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 Admin 和 Key Encrypter 角色:

    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 NameCard 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,然后点击关闭以删除项目。

后续步骤