在查询时对 BigQuery 数据进行去标识化处理

本教程介绍了如何使用远程函数和 Sensitive Data Protection 在查询 BigQuery 中的表时对数据进行去标识化处理。此方法有助于清理实时查询结果,从而最大限度地减少对分析不需要的数据的访问。

本教程演示了如何对传输中的数据进行加密和解密。如需了解如何使用 Sensitive Data Protection 对静态数据进行加密,请参阅对存储空间中的敏感数据进行去标识化处理

本教程适用于负责数据安全、数据处理或数据分析的受众群体。本指南假设您熟悉数据处理和数据隐私,而无需成为专家。本指南还假定您能够运行基本的 Cloud Shell 和 SQL 脚本。

本教程将使用基于 SQL 的函数、BigQuery远程函数Cloud Run 和 Sensitive Data Protection。

加密等去标识化技术可对数据中的原始敏感标识符进行模糊处理。这些技术可让您保留数据的实用性以进行联接或分析,同时降低数据处理的风险。

企业可能制定了政策或有法规要求,规定只能在云数据仓库中存储去标识化数据。此外,他们可能还需要高效地重标识去标识化的数据,以便生成报告。

如需最大限度地降低处理大量敏感数据的风险,您可以使用自动数据转换流水线来创建去标识化数据集。您可以使用本教程中的方法,通过 SQL 查询来替换该流水线,以仅进行重新标识或同时进行去标识和重新标识。本教程将帮助您使用托管在 Cloud Run 上的中央服务执行去标识化和重标识化。您可以在整个组织中使用此中央服务,而无需设置或维护 Dataflow 集群。

Sensitive Data Protection 可以通过检查数据中的敏感信息来对数据集进行分类。Sensitive Data Protection 具有 200 多个内置分类器,称为 infoTypes。使用 Cloud Data Loss Prevention API 对数据进行去标识化处理需要数据流水线和应用。本教程旨在帮助数据分析师、工程师或科学家通过 SQL 函数实现相同的结果。

完成本教程后,您将能够编写类似于以下内容的查询;查询结果中的敏感数据将被去标识化和重新标识。

SELECT
    pii_column,
    fns.dlp_freetext_encrypt(pii_column) AS dlp_encrypted,
    fns.dlp_freetext_decrypt(fns.dlp_freetext_encrypt(pii_column)) AS dlp_decrypted
FROM
    UNNEST(
    [
        'My name is John Doe. My email is john.doe@example.com']) AS pii_column

输出类似于以下内容:

pii_column dlp_encrypted dlp_decrypted
1 My name is John Doe. My email is john.doe@example.com My name is John Doe. My email is BQ_TRF_EMAIL(40):AQy6lGvwKR+AiiRqJpEr+nBzZUzOcjXkXamUugU= My name is John Doe. My email is john.doe@example.com

架构

下图显示了本教程如何使用 BigQuery 作为数据仓库、使用 Sensitive Data Protection 对数据进行去标识化和重标识处理,以及使用 Cloud Run 托管远程函数。

本教程的高级架构图

准备环境

  1. 在 Cloud Shell 中,克隆源代码库:

    git clone https://github.com/GoogleCloudPlatform/bigquery-dlp-remote-function.git
    
  2. 前往本教程的目录:

    cd bigquery-dlp-remote-function/
    

使用脚本部署资源

如果您想使用部署脚本而不进行自定义,请按以下步骤操作。如果您想自定义部署,请跳过此部分,改为参阅手动部署自定义解决方案

  1. PROJECT_IDREGION 字段设置值:

    # Project ID of the Google Cloud project
    PROJECT_ID="PROJECT_ID"
    
    # Google Cloud region to use for deployment of resources
    # Refer to https://cloud.google.com/about/locations
    REGION="REGION"
    

    替换以下内容:

    • PROJECT_ID:本教程所用项目的 ID。
    • REGION:您希望存储和处理数据的区域,例如 us-west1。提供区域,而不是可用区。
  2. 可选:如果您有要使用的检查模板,请将 DLP_INSPECT_TEMPLATE 字段设置为相应检查模板的完整资源名称。检查模板必须与您在 REGION 字段中设置的区域位于同一区域。

    确保检查模板包含去标识化模板中使用的所有 infoType。

    如果您跳过此步骤,Sensitive Data Protection 将使用一组系统默认的 infoType 检测器检查数据。

    DLP_INSPECT_TEMPLATE="DLP_INSPECT_TEMPLATE"
    

    DLP_INSPECT_TEMPLATE 替换为检查模板的完整资源名称,例如 projects/PROJECT_ID/locations/REGION/inspectTemplates/TEMPLATE_ID

  3. 使用应用默认凭据进行身份验证:

    gcloud auth application-default login && \
    gcloud auth application-default set-quota-project "${PROJECT_ID}"
    
  4. 初始化并运行 Terraform 脚本以创建所有资源:

    terraform init && \
    terraform apply \
    -var "project_id=${PROJECT_ID}" \
    -var "region=${REGION}" \
    -var "dlp_inspect_template_full_path=${DLP_INSPECT_TEMPLATE}"
    

    系统会显示 Terraform 将执行的所有操作。查看操作。如需继续,请输入 yes

  5. 验证数据是否可以加密和解密。

手动部署自定义解决方案

如果您想自定义部署,请按以下步骤操作。如果您想使用提供的部署脚本,而不进行自定义或手动操作,请改为参阅使用脚本部署资源

设置环境变量

在 Cloud Shell 中,设置以下环境变量:

PROJECT_ID="PROJECT_ID"
REGION="REGION"
CLOUD_RUN_SERVICE_NAME="CLOUD-RUN-SERVICE-NAME"
ARTIFACT_REGISTRY_NAME="ARTIFACT-DOCKER-REGISTRY-NAME"

替换以下内容:

  • PROJECT_ID:本教程所用项目的 ID。
  • REGION:您希望存储和处理数据的区域,例如 us-west1。提供区域,而不是可用区。
  • CLOUD_RUN_SERVICE_NAME:新 Cloud Run 服务的名称。最多可输入 15 个字符。
  • ARTIFACT_REGISTRY_NAME:用于存储容器映像的新 Artifact Registry 的名称。

为 Cloud Run 服务创建服务账号

  1. 创建服务账号:

    RUNNER_SA_NAME="${CLOUD_RUN_SERVICE_NAME}-runner"
    RUNNER_SA_EMAIL="${RUNNER_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
    gcloud iam service-accounts create "${RUNNER_SA_NAME}" \
        --project="${PROJECT_ID}" \
        --description "Runner for BigQuery remote function execution" \
        --display-name "${RUNNER_SA_NAME}"
    
  2. 授予 Sensitive Data Protection 所需的角色。

    授予 DLP Reader 角色:

    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${RUNNER_SA_EMAIL}" \
        --role='roles/dlp.reader'
    

    授予 DLP User 角色:

    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${RUNNER_SA_EMAIL}" \
        --role='roles/dlp.user'
    

部署 Cloud Run 服务

如需部署应用,请按以下步骤操作:

  1. 可选:您可以通过更改环境变量或更新 src/main/resources/aes.properties 文件来更改默认值。

  2. 创建 Artifact Registry 制品库以存储函数的容器映像:

    gcloud artifacts repositories create "${ARTIFACT_REGISTRY_NAME}" \
    --repository-format=docker \
    --location="${REGION}" \
    --description="Container images repository for BigQuery Functions" \
    --project="${PROJECT_ID}"
    
  3. 使用 Cloud Build 编译应用并将其部署到 Cloud Run:

    gcloud builds submit \
    --project ${PROJECT_ID} \
    --substitutions=_CONTAINER_IMAGE_NAME="${REGION}-docker.pkg.dev/${PROJECT_ID}/${ARTIFACT_REGISTRY_NAME}/${CLOUD_RUN_SERVICE_NAME}:latest" \
    --machine-type=e2-highcpu-8 && \
    gcloud beta run deploy ${CLOUD_RUN_SERVICE_NAME} \
    --image="${REGION}-docker.pkg.dev/${PROJECT_ID}/${ARTIFACT_REGISTRY_NAME}/${CLOUD_RUN_SERVICE_NAME}:latest" \
    --execution-environment=gen2 \
    --platform=managed \
    --region="${REGION}" \
    --service-account="${RUNNER_SA_EMAIL}" \
    --cpu=4 \
    --memory=8Gi \
    --no-allow-unauthenticated \
    --project ${PROJECT_ID} \
    --update-env-vars=PROJECT_ID=${PROJECT_ID}
    

    输出的末尾类似于以下内容:

    ID: 403a276e-b0c6-41f3-aaed-f0ec9f9cedba
    CREATE_TIME: 2023-02-04T01:52:15+00:00
    DURATION: 1M59S
    SOURCE: gs://PROJECT_ID_cloudbuild/source/1675475534.124241-9c43787f64e04cfd9e4a1979d3324fe0.tgz
    IMAGES: gcr.io/PROJECT_ID/CLOUD_RUN_SERVICE_NAME (+1 more)
    STATUS: SUCCESS
    Deploying container to Cloud Run service [CLOUD_RUN_SERVICE_NAME] in project [PROJECT_ID] region [REGION]
    OK Deploying new service... Done.
     OK Creating Revision... Revision deployment finished. Checking container heal
     th.
     OK Routing traffic...
    Done.
    Service [CLOUD_RUN_SERVICE_NAME] revision [CLOUD_RUN_SERVICE_NAME-00001-tat] has been deployed and is serving 100 percent of traffic.
    Service URL: https://CLOUD_RUN_SERVICE_NAME-j2bpjx2xoq-uw.a.run.app
    
  4. 检索 Cloud Run 网址并将其保存到环境变量中:

    RUN_URL="$(gcloud run services describe ${CLOUD_RUN_SERVICE_NAME} --region \
        ${REGION} --project ${PROJECT_ID} --format="get(status.address.url)")"
    

创建 Sensitive Data Protection 去标识化模板

Sensitive Data Protection 去标识化模板可帮助您保存去标识化设置,以便在多个操作和数据源中重复使用这些设置。

此步骤使用 sample_dlp_deid_config.json 文件,其中包含一个示例去标识化模板。

在 Cloud Shell 中,创建模板:

DEID_TEMPLATE=$(curl -X POST \
-H "Authorization: Bearer `gcloud auth print-access-token`" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Goog-User-Project: ${PROJECT_ID}" \
--data-binary "@sample_dlp_deid_config.json" \
"https://dlp.googleapis.com/v2/projects/${PROJECT_ID}/locations/${REGION}/deidentifyTemplates")

DEID_TEMPLATE_NAME="$(echo ${DEID_TEMPLATE} | jq -r '.name')"

Google 建议您在对实际敏感工作负载执行 Sensitive Data Protection 加密时使用封装密钥。出于演示目的,本教程使用未封装的密钥。如需详细了解如何创建封装密钥并在去标识化和重标识请求中使用该密钥,请参阅对敏感数据进行去标识化和重标识

创建 BigQuery 与 Cloud Run 之间的连接

  1. 在 Cloud Shell 中,创建 BigQuery 连接以访问 Cloud Run:

    bq mk --connection \
    --display_name='External transform function connection' \
    --connection_type=CLOUD_RESOURCE \
    --project_id="${PROJECT_ID}" \
    --location="${REGION}" \
    ext-${CLOUD_RUN_SERVICE_NAME}
    
  2. 查找并设置用于连接的 BigQuery 服务账号:

    CONNECTION_SA="$(bq --project_id ${PROJECT_ID} --format json show \
        --connection ${PROJECT_ID}.${REGION}.ext-${CLOUD_RUN_SERVICE_NAME} \
        | jq -r '.cloudResource.serviceAccountId')"
    
  3. 向该服务账号授予 Cloud Run Invoker 角色:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${CONNECTION_SA}" \
        --role='roles/run.invoker'
    

为远程函数创建 BigQuery 数据集

  1. 为远程函数定义 BigQuery 数据集:

    BQ_FUNCTION_DATASET="fns"
    
  2. 如果数据集尚不存在,请创建该数据集:

       bq mk --dataset \
           --project_id ${PROJECT_ID} \
           --location ${REGION} \
           ${BQ_FUNCTION_DATASET}
    

创建 Sensitive Data Protection 远程函数

  1. 可选:如果您有想要使用的检查模板,请将 DLP_INSPECT_TEMPLATE 变量设置为相应检查模板的完整资源名称。检查模板必须位于您在 REGION 环境变量中设置的同一区域。

    确保检查模板包含去标识化模板中使用的所有 infoType。

    如果您跳过此步骤,Sensitive Data Protection 将使用一组系统默认的 infoType 检测器检查数据。

    DLP_INSPECT_TEMPLATE="DLP_INSPECT_TEMPLATE"
    

    DLP_INSPECT_TEMPLATE 替换为检查模板的完整资源名称,例如 projects/PROJECT_ID/locations/REGION/inspectTemplates/TEMPLATE_ID

  2. 创建 Sensitive Data Protection 去标识化函数:

    bq query --project_id ${PROJECT_ID} \
    --use_legacy_sql=false \
    "CREATE OR REPLACE FUNCTION ${BQ_FUNCTION_DATASET}.dlp_freetext_encrypt(v STRING)
    RETURNS STRING
    REMOTE WITH CONNECTION \`${PROJECT_ID}.${REGION}.ext-${CLOUD_RUN_SERVICE_NAME}\`
    OPTIONS (endpoint = '${RUN_URL}', user_defined_context = [('mode', 'deidentify'),('algo','dlp'),('dlp-deid-template','${DEID_TEMPLATE_NAME}'),('dlp-inspect-template', '${DLP_INSPECT_TEMPLATE}')]);"
    
  3. 创建 Sensitive Data Protection 重新标识函数:

    bq query --project_id ${PROJECT_ID} \
    --use_legacy_sql=false \
    "CREATE OR REPLACE FUNCTION ${BQ_FUNCTION_DATASET}.dlp_freetext_decrypt(v STRING)
    RETURNS STRING
    REMOTE WITH CONNECTION \`${PROJECT_ID}.${REGION}.ext-${CLOUD_RUN_SERVICE_NAME}\`
    OPTIONS (endpoint = '${RUN_URL}', user_defined_context = [('mode', 'reidentify'),('algo','dlp'),('dlp-deid-template','${DEID_TEMPLATE_NAME}'),('dlp-inspect-template', '${DLP_INSPECT_TEMPLATE}')]);"
    

验证去标识化和重新标识化

如需验证该解决方案是否能对数据进行去标识化和重新标识化,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,前往 BigQuery。

    转到 BigQuery

    BigQuery 会在您最近访问的项目中打开。

  2. 如需打开查询编辑器,请点击 编写新查询

  3. 输入以下查询:

    SELECT
        pii_column,
        fns.dlp_freetext_encrypt(pii_column) AS dlp_encrypted,
        fns.dlp_freetext_decrypt(fns.dlp_freetext_encrypt(pii_column)) AS dlp_decrypted
    FROM
        UNNEST(
        [
            'My name is John Doe. My email is john.doe@example.com',
            'Some non PII data',
            '650-253-0000',
            'some script with simple number 1234']) AS pii_column
    
  4. 点击运行

bq

  1. 为数据集设置环境变量:

    BQ_FUNCTION_DATASET="fns"
    
  2. 运行查询:

    bq query --project_id ${PROJECT_ID} \
    --use_legacy_sql=false \
    "
    SELECT
      pii_column,
      ${BQ_FUNCTION_DATASET}.dlp_freetext_encrypt(pii_column) AS dlp_encrypted,
    ${BQ_FUNCTION_DATASET}.dlp_freetext_decrypt(${BQ_FUNCTION_DATASET}.dlp_freetext_encrypt(pii_column)) AS dlp_decrypted
    FROM
      UNNEST(
        [
          'My name is John Doe. My email is john.doe@example.com',
          'Some non PII data',
          '650-253-0000',
          'some script with simple number 1234']) AS pii_column"
    

输出类似于以下内容:

pii_column dlp_encrypted dlp_decrypted
1 My name is John Doe. My email is john.doe@example.com My name is John Doe. My email is BQ_TRF_EMAIL(40):AQy6lGvwKR+AiiRqJpEr+nBzZUzOcjXkXamUugU= My name is John Doe. My email is john.doe@example.com
2 Some non PII data Some non PII data Some non PII data
3 650-253-0000 BQ_TRF_PH(40):AeKpGU5KBXaTyecCun7dv1hHht5w5Q2PTpvkRC4= 650-253-0000
4 some script with simple number 1234 some script with simple number 1234 some script with simple number 1234

注意事项

在根据您的需求调整本教程时,请考虑以下事项:

  • 去标识化和重标识化通过 Cloud Run 服务进行处理。根据您的计算需求预配 Cloud Run CPU 和内存。如需了解详情,请参阅 Cloud Run 的 CPU 限制内存限制
  • 使用 Sensitive Data Protection 时,请考虑使用情况限制控制费用的建议
  • 为了帮助控制费用和 Sensitive Data Protection 总配额消耗量,请将您通过 Sensitive Data Protection 远程函数传递的限制为 10,000 或更少。该解决方案可以自动批量处理请求,以便妥善处理以下 Sensitive Data Protection 请求限制:

    • 表格值上限:50,000
    • 默认请求大小限制:0.5 MB

    查询的最终结果和过滤后的结果应传递给敏感数据保护函数,而不是源。

    对于此解决方案,pii_column 列中的每个值都是一个商品,例如 My name is John Doe. My email is john.doe@example.com 就是一个商品。

  • 确保您的 BigQuery 数据集、Cloud Run 服务和敏感数据保护模板位于同一云区域