计算数据集的 l-多样性

L-多样性是数据集的属性以及对 k-匿名性的扩展,可针对出现敏感值的每一列测量敏感值的多样性。如果对于具有相同准标识符的每组行,每个敏感属性至少有 l 个不同的值,则数据集具有 l-多样性。

您可以根据数据集的一个或多个列或字段计算 l-多样性值。本主题演示了如何使用 Sensitive Data Protection 计算数据集的 l-多样性值l。如需从总体上详细了解 l-多样性或风险分析,请参阅风险分析概念主题,然后再继续。

准备工作

在继续操作之前,请确保您已完成以下步骤:

  1. 登录您的 Google 账号。
  2. 在 Google Cloud 控制台的项目选择器页面上,选择或创建 Google Cloud 项目。
  3. 转到项目选择器
  4. 确保您的 Google Cloud 项目已启用结算功能。 了解如何确认您的项目已启用结算功能
  5. 启用 Sensitive Data Protection。
  6. 启用 Sensitive Data Protection

  7. 选择要分析的 BigQuery 数据集。Sensitive Data Protection 通过扫描 BigQuery 表来计算 l-多样性指标l
  8. 在数据集中确定一个敏感字段标识符(如果适用)以及至少一个准标识符。如需了解详情,请参阅风险分析术语和技术

计算 l-多样性

每当运行风险分析作业时,Sensitive Data Protection 都会执行风险分析。您必须先创建作业,方法是使用Google Cloud 控制台、发送 DLP API 请求或使用 Sensitive Data Protection 客户端库。

控制台

  1. 在 Google Cloud 控制台中,前往创建风险分析页面。

    前往“创建风险分析”页面

  2. 选择输入数据部分中,通过输入包含表的项目的 ID、表的数据集 ID 以及表的名称来指定要扫描的 BigQuery 表。

  3. 要计算的隐私权指标下,选择 l-多样性

  4. 任务 ID 部分中,您可以视需要为作业提供自定义标识符,然后选择 Sensitive Data Protection 将在其中处理您的数据的资源位置。完成操作后,请点击继续

  5. 定义字段部分中,您为 l-多样性风险作业指定敏感字段和准标识符。Sensitive Data Protection 会访问您在上一步中指定的 BigQuery 表的元数据,并尝试填充字段列表。

    1. 选择相应的复选框,将字段指定为敏感字段 (S) 或准标识符 (QI)。您必须选择 1 个敏感字段和至少 1 个准标识符。
    2. 如果 Sensitive Data Protection 无法填充字段,请点击输入字段名称以手动输入一个或多个字段,并将每个字段设置为敏感字段或准标识符。完成操作后,请点击继续
  6. 添加操作部分中,您可以添加可选操作,以便在风险作业完成时执行。可用的选项包括:

    • 保存到 BigQuery:将风险分析扫描的结果保存到 BigQuery 表中。
    • 发布到 Pub/Sub:将通知发布到 Pub/Sub 主题

    • 通过电子邮件发送通知:向您发送电子邮件,其中包含结果。完成操作后,请点击创建

l-多样性风险分析作业会立即启动。

C#

如需了解如何安装和使用 Sensitive Data Protection 客户端库,请参阅 Sensitive Data Protection 客户端库

如需向 Sensitive Data Protection 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为本地开发环境设置身份验证


using Google.Api.Gax.ResourceNames;
using Google.Cloud.Dlp.V2;
using Google.Cloud.PubSub.V1;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static Google.Cloud.Dlp.V2.Action.Types;
using static Google.Cloud.Dlp.V2.PrivacyMetric.Types;

public class RiskAnalysisCreateLDiversity
{
    public static object LDiversity(
        string callingProjectId,
        string tableProjectId,
        string datasetId,
        string tableId,
        string topicId,
        string subscriptionId,
        IEnumerable<FieldId> quasiIds,
        string sensitiveAttribute)
    {
        var dlp = DlpServiceClient.Create();

        // Construct + submit the job
        var ldiversityConfig = new LDiversityConfig
        {
            SensitiveAttribute = new FieldId { Name = sensitiveAttribute },
            QuasiIds = { quasiIds }
        };

        var config = new RiskAnalysisJobConfig
        {
            PrivacyMetric = new PrivacyMetric
            {
                LDiversityConfig = ldiversityConfig
            },
            SourceTable = new BigQueryTable
            {
                ProjectId = tableProjectId,
                DatasetId = datasetId,
                TableId = tableId
            },
            Actions =
            {
                new Google.Cloud.Dlp.V2.Action
                {
                    PubSub = new PublishToPubSub
                    {
                        Topic = $"projects/{callingProjectId}/topics/{topicId}"
                    }
                }
            }
        };

        var submittedJob = dlp.CreateDlpJob(
            new CreateDlpJobRequest
            {
                ParentAsProjectName = new ProjectName(callingProjectId),
                RiskJob = config
            });

        // Listen to pub/sub for the job
        var subscriptionName = new SubscriptionName(callingProjectId, subscriptionId);
        var subscriber = SubscriberClient.CreateAsync(subscriptionName).Result;

        // SimpleSubscriber runs your message handle function on multiple
        // threads to maximize throughput.
        var done = new ManualResetEventSlim(false);
        subscriber.StartAsync((PubsubMessage message, CancellationToken cancel) =>
        {
            if (message.Attributes["DlpJobName"] == submittedJob.Name)
            {
                Thread.Sleep(500); // Wait for DLP API results to become consistent
                done.Set();
                return Task.FromResult(SubscriberClient.Reply.Ack);
            }
            else
            {
                return Task.FromResult(SubscriberClient.Reply.Nack);
            }
        });

        done.Wait(TimeSpan.FromMinutes(10)); // 10 minute timeout; may not work for large jobs
        subscriber.StopAsync(CancellationToken.None).Wait();

        // Process results
        var resultJob = dlp.GetDlpJob(
            new GetDlpJobRequest
            {
                DlpJobName = DlpJobName.Parse(submittedJob.Name)
            });

        var result = resultJob.RiskDetails.LDiversityResult;

        for (var bucketIdx = 0; bucketIdx < result.SensitiveValueFrequencyHistogramBuckets.Count; bucketIdx++)
        {
            var bucket = result.SensitiveValueFrequencyHistogramBuckets[bucketIdx];
            Console.WriteLine($"Bucket {bucketIdx}");
            Console.WriteLine($"  Bucket size range: [{bucket.SensitiveValueFrequencyLowerBound}, {bucket.SensitiveValueFrequencyUpperBound}].");
            Console.WriteLine($"  {bucket.BucketSize} unique value(s) total.");

            foreach (var bucketValue in bucket.BucketValues)
            {
                // 'UnpackValue(x)' is a prettier version of 'x.toString()'
                Console.WriteLine($"    Quasi-ID values: [{String.Join(',', bucketValue.QuasiIdsValues.Select(x => UnpackValue(x)))}]");
                Console.WriteLine($"    Class size: {bucketValue.EquivalenceClassSize}");

                foreach (var topValue in bucketValue.TopSensitiveValues)
                {
                    Console.WriteLine($"    Sensitive value {UnpackValue(topValue.Value)} occurs {topValue.Count} time(s).");
                }
            }
        }

        return result;
    }

    public static string UnpackValue(Value protoValue)
    {
        var jsonValue = JsonConvert.DeserializeObject<Dictionary<string, object>>(protoValue.ToString());
        return jsonValue.Values.ElementAt(0).ToString();
    }
}

Go

如需了解如何安装和使用 Sensitive Data Protection 客户端库,请参阅 Sensitive Data Protection 客户端库

如需向 Sensitive Data Protection 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为本地开发环境设置身份验证

import (
	"context"
	"fmt"
	"io"
	"strings"
	"time"

	dlp "cloud.google.com/go/dlp/apiv2"
	"cloud.google.com/go/dlp/apiv2/dlppb"
	"cloud.google.com/go/pubsub"
)

// riskLDiversity computes the L Diversity of the given columns.
func riskLDiversity(w io.Writer, projectID, dataProject, pubSubTopic, pubSubSub, datasetID, tableID, sensitiveAttribute string, columnNames ...string) error {
	// projectID := "my-project-id"
	// dataProject := "bigquery-public-data"
	// pubSubTopic := "dlp-risk-sample-topic"
	// pubSubSub := "dlp-risk-sample-sub"
	// datasetID := "nhtsa_traffic_fatalities"
	// tableID := "accident_2015"
	// sensitiveAttribute := "city"
	// columnNames := "state_number", "county"
	ctx := context.Background()
	client, err := dlp.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("dlp.NewClient: %w", err)
	}
	defer client.Close()

	// Create a PubSub Client used to listen for when the inspect job finishes.
	pubsubClient, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return err
	}
	defer pubsubClient.Close()

	// Create a PubSub subscription we can use to listen for messages.
	// Create the Topic if it doesn't exist.
	t := pubsubClient.Topic(pubSubTopic)
	topicExists, err := t.Exists(ctx)
	if err != nil {
		return err
	}
	if !topicExists {
		if t, err = pubsubClient.CreateTopic(