k-Anonymität für ein Dataset berechnen

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Die k-Anonymität eines Datasets gibt Auskunft über die Re-Identifizierbarkeit der darin enthaltenen Datensätze. Ein Dataset ist k-anonym, wenn Quasi-Identifikatoren für jede im Dataset gespeicherte Person mit jenen von mindestens k – 1 weiteren in demselben Dataset gespeicherten Personen identisch sind.

Sie können den k-Anonymitätswert basierend auf einzelnen oder mehreren Spalten oder Feldern eines Datasets berechnen. In diesem Thema wird gezeigt, wie mithilfe von Cloud Data Loss Prevention k-Anonymitätswerte für ein Dataset berechnet werden. Bevor Sie fortfahren, lesen Sie weitere Informationen zur k-Anonymität oder zur Risikoanalyse im Allgemeinen im Thema zum Konzept der Risikoanalyse.

Hinweis

Bevor Sie fortfahren, müssen Sie die folgenden Schritte ausführen:

  1. Melden Sie sich bei Ihrem Google-Konto an.
  2. Wählen Sie in der Google Cloud Console auf der Seite für die Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
  3. Projektauswahl aufrufen
  4. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein. Weitere Informationen zur Abrechnung Ihres Projekts.
  5. Cloud DLP aktivieren
  6. Cloud DLP aktivieren

  7. Wählen Sie das zu analysierende BigQuery-Dataset aus. Cloud DLP berechnet den k-Anonymitätsmesswert durch Scannen einer BigQuery-Tabelle.
  8. Bestimmen Sie (falls zutreffend) einen Identifikator und mindestens einen Quasi-Identifikator im Dataset. Weitere Informationen finden Sie unter Begriffe und Techniken der Risikoanalyse.

k-Anonymität berechnen

Cloud DLP führt bei jeder Ausführung eines Risikoanalysejobs eine Risikoanalyse durch. Sie müssen den Job zuerst über die Google Cloud Console, das Senden einer DLP API-Anfrage oder die Verwendung einer Cloud DLP-Clientbibliothek erstellen.

Console

  1. Rufen Sie in der Google Cloud Console die Seite Risikoanalyse erstellen auf.

    Zur Risikoanalyse

  2. Geben Sie im Abschnitt Eingabedaten auswählen die zu scannende BigQuery-Tabelle an. Geben Sie dazu die Projekt-ID des Projekts mit der Tabelle, die Dataset-ID und den Namen der Tabelle ein.

  3. Wählen Sie unter Datenschutzmesswert zur Berechnung () k-Anonymität aus.

  4. Im Abschnitt Job-ID können Sie dem Job optional eine benutzerdefinierte Kennung geben und einen Ressourcenstandort auswählen, an dem Cloud DLP Ihre Daten verarbeitet. Wenn Sie fertig sind, klicken Sie auf Weiter.

  5. Im Abschnitt Felder definieren geben Sie Identifikatoren und Quasi-Identifikatoren für den k-Anonymitätsrisiko-Job an. Cloud DLP greift auf die Metadaten der BigQuery-Tabelle zu, die Sie im vorherigen Schritt angegeben haben, und versucht, die Liste der Felder auszufüllen.

    1. Klicken Sie das entsprechende Kästchen an, um ein Feld als Identifikator (ID) oder Quasi-Identifikator (QI) zu designieren. Sie müssen entweder 0 oder 1 Identifikator und mindestens 1 Quasi-Identifikator auswählen.
    2. Wenn Cloud DLP die Felder nicht füllen kann, klicken Sie auf Feldnamen eingeben, um ein oder mehrere Felder manuell einzugeben, und legen Sie jedes Feld als Identifikator oder Quasi-Identifikator fest. Wenn Sie fertig sind, klicken Sie auf Weiter.
  6. Im Abschnitt Aktionen hinzufügen () können Sie optionale Aktionen hinzufügen, die ausgeführt werden, wenn der Risikojob abgeschlossen ist. Folgende Optionen sind verfügbar:

    • In BigQuery speichern (): Die Ergebnisse des Risikoanalysescans werden in einer BigQuery-Tabelle gespeichert.
    • In Pub/Sub veröffentlichen: Veröffentlicht eine Benachrichtigung in einem Cloud Pub/Sub-Thema.
    • Per E-Mail benachrichtigen: Sendet Ihnen eine E-Mail mit Ergebnissen. Wenn Sie fertig sind, klicken Sie auf Erstellen.

Der k-Anonymität-Risikoanalysejob beginnt sofort.

Protokoll

Zum Ausführen eines neuen Risikoanalysejobs zur Berechnung der k-Anonymität senden Sie eine Anfrage an die Ressource projects.dlpJobs, wobei PROJECT_ID für Ihre Projekt-ID steht:

https://dlp.googleapis.com/v2/projects/PROJECT_ID/dlpJobs

Die Anfrage enthält ein RiskAnalysisJobConfig-Objekt, das Folgendes umfasst:

  • Ein PrivacyMetric-Objekt. Hier geben Sie an, dass Sie die k-Anonymität berechnen, indem Sie ein KAnonymityConfig-Objekt einschließen.

  • Ein BigQueryTable-Objekt. Geben Sie die zu untersuchende BigQuery-Tabelle an. Dazu beziehen Sie die folgenden Parameter ein:

    • projectId: die Projekt-ID des Projekts, das die Tabelle enthält
    • datasetId: die Dataset-ID der Tabelle
    • tableId: der Name der Tabelle
  • Ein oder mehrere Action-Objekte für Aktionen, die nach Abschluss des Jobs in der angegebenen Reihenfolge ausgeführt werden sollen. Jedes Action-Objekt kann eine der folgenden Aktionen enthalten:

    Geben Sie im Objekt KAnonymityConfig Folgendes an:

    • quasiIds[]: ein oder mehrere Quasi-Identifikatoren (FieldId-Objekte) zum Scannen und zur Berechnung der k-Anonymität. Wenn Sie mehrere Quasi-Identifikatoren angeben, werden sie als ein einziger zusammengesetzter Schlüssel betrachtet. Structs und wiederholte Datentypen werden nicht unterstützt, verschachtelte Felder werden jedoch unterstützt, sofern sie nicht selbst Structs oder in einem wiederholten Feld verschachtelt sind.
    • entityId: optionaler Identifikator, der angibt, dass alle Zeilen, die der jeweiligen spezifischen entityId entsprechen, für die k-Anonymitätsberechnung gruppiert werden sollen. In der Regel ist eine entityId eine Spalte, die einen eindeutigen Nutzer darstellt, z. B. eine Kunden-ID oder eine Nutzer-ID. Wenn eine entityId in mehreren Zeilen mit unterschiedlichen Quasi-Identifikatoren enthalten ist, werden diese Zeilen zu einem Multiset zusammengefasst, das als Quasi-Identifikator für diese Entität verwendet wird. Weitere Informationen zu Entitäts-IDs finden Sie im Konzept-Thema "Risikoanalyse" unter Entitäts-IDs und das Berechnen der k-Anonymität.

Sobald Sie eine Anfrage an die DLP API senden, wird der Risikoanalysejob gestartet.

Java

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.


import com.google.api.core.SettableApiFuture;
import com.google.cloud.dlp.v2.DlpServiceClient;
import com.google.cloud.pubsub.v1.AckReplyConsumer;
import com.google.cloud.pubsub.v1.MessageReceiver;
import com.google.cloud.pubsub.v1.Subscriber;
import com.google.privacy.dlp.v2.Action;
import com.google.privacy.dlp.v2.Action.PublishToPubSub;
import com.google.privacy.dlp.v2.AnalyzeDataSourceRiskDetails.KAnonymityResult;
import com.google.privacy.dlp.v2.AnalyzeDataSourceRiskDetails.KAnonymityResult.KAnonymityEquivalenceClass;
import com.google.privacy.dlp.v2.AnalyzeDataSourceRiskDetails.KAnonymityResult.KAnonymityHistogramBucket;
import com.google.privacy.dlp.v2.BigQueryTable;
import com.google.privacy.dlp.v2.CreateDlpJobRequest;
import com.google.privacy.dlp.v2.DlpJob;
import com.google.privacy.dlp.v2.FieldId;
import com.google.privacy.dlp.v2.GetDlpJobRequest;
import com.google.privacy.dlp.v2.LocationName;
import com.google.privacy.dlp.v2.PrivacyMetric;
import com.google.privacy.dlp.v2.PrivacyMetric.KAnonymityConfig;
import com.google.privacy.dlp.v2.RiskAnalysisJobConfig;
import com.google.privacy.dlp.v2.Value;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.PubsubMessage;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
class RiskAnalysisKAnonymity {

  public static void main(String[] args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String datasetId = "your-bigquery-dataset-id";
    String tableId = "your-bigquery-table-id";
    String topicId = "pub-sub-topic";
    String subscriptionId = "pub-sub-subscription";
    calculateKAnonymity(projectId, datasetId, tableId, topicId, subscriptionId);
  }

  public static void calculateKAnonymity(
      String projectId, String datasetId, String tableId, String topicId, String subscriptionId)
      throws ExecutionException, InterruptedException, IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) {

      // Specify the BigQuery table to analyze
      BigQueryTable bigQueryTable =
          BigQueryTable.newBuilder()
              .setProjectId(projectId)
              .setDatasetId(datasetId)
              .setTableId(tableId)
              .build();

      // These values represent the column names of quasi-identifiers to analyze
      List<String> quasiIds = Arrays.asList("Age", "Mystery");

      // Configure the privacy metric for the job
      List<FieldId> quasiIdFields =
          quasiIds.stream()
              .map(columnName -> FieldId.newBuilder().setName(columnName).build())
              .collect(Collectors.toList());
      KAnonymityConfig kanonymityConfig =
          KAnonymityConfig.newBuilder().addAllQuasiIds(quasiIdFields).build();
      PrivacyMetric privacyMetric =
          PrivacyMetric.newBuilder().setKAnonymityConfig(kanonymityConfig).build();

      // Create action to publish job status notifications over Google Cloud Pub/Sub
      ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
      PublishToPubSub publishToPubSub =
          PublishToPubSub.newBuilder().setTopic(topicName.toString()).build();
      Action action = Action.newBuilder().setPubSub(publishToPubSub).build();

      // Configure the risk analysis job to perform
      RiskAnalysisJobConfig riskAnalysisJobConfig =
          RiskAnalysisJobConfig.newBuilder()
              .setSourceTable(bigQueryTable)
              .setPrivacyMetric(privacyMetric)
              .addActions(action)
              .build();

      // Build the request to be sent by the client
      CreateDlpJobRequest createDlpJobRequest =
          CreateDlpJobRequest.newBuilder()
              .setParent(LocationName.of(projectId, "global").toString())
              .setRiskJob(riskAnalysisJobConfig)
              .build();

      // Send the request to the API using the client
      DlpJob dlpJob = dlpServiceClient.createDlpJob(createDlpJobRequest);

      // Set up a Pub/Sub subscriber to listen on the job completion status
      final SettableApiFuture<Boolean> done = SettableApiFuture.create();

      ProjectSubscriptionName subscriptionName =
          ProjectSubscriptionName.of(projectId, subscriptionId);

      MessageReceiver messageHandler =
          (PubsubMessage pubsubMessage, AckReplyConsumer ackReplyConsumer) -> {
            handleMessage(dlpJob, done, pubsubMessage, ackReplyConsumer);
          };
      Subscriber subscriber = Subscriber.newBuilder(subscriptionName, messageHandler).build();
      subscriber.startAsync();

      // Wait for job completion semi-synchronously
      // For long jobs, consider using a truly asynchronous execution model such as Cloud Functions
      try {
        done.get(15, TimeUnit.MINUTES);
      } catch (TimeoutException e) {
        System.out.println("Job was not completed after 15 minutes.");
        return;
      } finally {
        subscriber.stopAsync();
        subscriber.awaitTerminated();
      }

      // Build a request to get the completed job
      GetDlpJobRequest getDlpJobRequest =
          GetDlpJobRequest.newBuilder().setName(dlpJob.getName()).build();

      // Retrieve completed job status
      DlpJob completedJob = dlpServiceClient.getDlpJob(getDlpJobRequest);
      System.out.println("Job status: " + completedJob.getState());
      System.out.println("Job name: " + dlpJob.getName());

      // Get the result and parse through and process the information
      KAnonymityResult kanonymityResult = completedJob.getRiskDetails().getKAnonymityResult();
      List<KAnonymityHistogramBucket> histogramBucketList =
          kanonymityResult.getEquivalenceClassHistogramBucketsList();
      for (KAnonymityHistogramBucket result : histogramBucketList) {
        System.out.printf(
            "Bucket size range: [%d, %d]\n",
            result.getEquivalenceClassSizeLowerBound(), result.getEquivalenceClassSizeUpperBound());

        for (KAnonymityEquivalenceClass bucket : result.getBucketValuesList()) {
          List<String> quasiIdValues =
              bucket.getQuasiIdsValuesList().stream()
                  .map(Value::toString)
                  .collect(Collectors.toList());

          System.out.println("\tQuasi-ID values: " + String.join(", ", quasiIdValues));
          System.out.println("\tClass size: " + bucket.getEquivalenceClassSize());
        }
      }
    }
  }

  // handleMessage injects the job and settableFuture into the message reciever interface
  private static void handleMessage(
      DlpJob job,
      SettableApiFuture<Boolean> done,
      PubsubMessage pubsubMessage,
      AckReplyConsumer ackReplyConsumer) {
    String messageAttribute = pubsubMessage.getAttributesMap().get("DlpJobName");
    if (job.getName().equals(messageAttribute)) {
      done.set(true);
      ackReplyConsumer.ack();
    } else {
      ackReplyConsumer.nack();
    }
  }
}

Node.js

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.

// Import the Google Cloud client libraries
const DLP = require('@google-cloud/dlp');
const {PubSub} = require('@google-cloud/pubsub');

// Instantiates clients
const dlp = new DLP.DlpServiceClient();
const pubsub = new PubSub();

// The project ID to run the API call under
// const projectId = 'my-project';

// The project ID the table is stored under
// This may or (for public datasets) may not equal the calling project ID
// const tableProjectId = 'my-project';

// The ID of the dataset to inspect, e.g. 'my_dataset'
// const datasetId = 'my_dataset';

// The ID of the table to inspect, e.g. 'my_table'
// const tableId = 'my_table';

// The name of the Pub/Sub topic to notify once the job completes
// TODO(developer): create a Pub/Sub topic to use for this
// const topicId = 'MY-PUBSUB-TOPIC'

// The name of the Pub/Sub subscription to use when listening for job
// completion notifications
// TODO(developer): create a Pub/Sub subscription to use for this
// const subscriptionId = 'MY-PUBSUB-SUBSCRIPTION'

// A set of columns that form a composite key ('quasi-identifiers')
// const quasiIds = [{ name: 'age' }, { name: 'city' }];
async function kAnonymityAnalysis() {
  const sourceTable = {
    projectId: tableProjectId,
    datasetId: datasetId,
    tableId: tableId,
  };
  // Construct request for creating a risk analysis job

  const request = {
    parent: `projects/${projectId}/locations/global`,
    riskJob: {
      privacyMetric: {
        kAnonymityConfig: {
          quasiIds: quasiIds,
        },
      },
      sourceTable: sourceTable,
      actions: [
        {
          pubSub: {
            topic: `projects/${projectId}/topics/${topicId}`,
          },
        },
      ],
    },
  };

  // Create helper function for unpacking values
  const getValue = obj => obj[Object.keys(obj)[0]];

  // Run risk analysis job
  const [topicResponse] = await pubsub.topic(topicId).get();
  const subscription = await topicResponse.subscription(subscriptionId);
  const [jobsResponse] = await dlp.createDlpJob(request);
  const jobName = jobsResponse.name;
  console.log(`Job created. Job name: ${jobName}`);
  // Watch the Pub/Sub topic until the DLP job finishes
  await new Promise((resolve, reject) => {
    const messageHandler = message => {
      if (message.attributes && message.attributes.DlpJobName === jobName) {
        message.ack();
        subscription.removeListener('message', messageHandler);
        subscription.removeListener('error', errorHandler);
        resolve(jobName);
      } else {
        message.nack();
      }
    };

    const errorHandler = err => {
      subscription.removeListener('message', messageHandler);
      subscription.removeListener('error', errorHandler);
      reject(err);
    };

    subscription.on('message', messageHandler);
    subscription.on('error', errorHandler);
  });
  setTimeout(() => {
    console.log(' Waiting for DLP job to fully complete');
  }, 500);
  const [job] = await dlp.getDlpJob({name: jobName});
  const histogramBuckets =
    job.riskDetails.kAnonymityResult.equivalenceClassHistogramBuckets;

  histogramBuckets.forEach((histogramBucket, histogramBucketIdx) => {
    console.log(`Bucket ${histogramBucketIdx}:`);
    console.log(
      `  Bucket size range: [${histogramBucket.equivalenceClassSizeLowerBound}, ${histogramBucket.equivalenceClassSizeUpperBound}]`
    );

    histogramBucket.bucketValues.forEach(valueBucket => {
      const quasiIdValues = valueBucket.quasiIdsValues
        .map(getValue)
        .join(', ');
      console.log(`  Quasi-ID values: {${quasiIdValues}}`);
      console.log(`  Class size: ${valueBucket.equivalenceClassSize}`);
    });
  });
}
kAnonymityAnalysis();

Python

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.

def k_anonymity_analysis(
    project,
    table_project_id,
    dataset_id,
    table_id,
    topic_id,
    subscription_id,
    quasi_ids,
    timeout=300,
):
    """Uses the Data Loss Prevention API to compute the k-anonymity of a
        column set in a Google BigQuery table.
    Args:
        project: The Google Cloud project id to use as a parent resource.
        table_project_id: The Google Cloud project id where the BigQuery table
            is stored.
        dataset_id: The id of the dataset to inspect.
        table_id: The id of the table to inspect.
        topic_id: The name of the Pub/Sub topic to notify once the job
            completes.
        subscription_id: The name of the Pub/Sub subscription to use when
            listening for job completion notifications.
        quasi_ids: A set of columns that form a composite key.
        timeout: The number of seconds to wait for a response from the API.

    Returns:
        None; the response from the API is printed to the terminal.
    """
    import concurrent.futures

    # Import the client library.
    import google.cloud.dlp

    # This sample additionally uses Cloud Pub/Sub to receive results from
    # potentially long-running operations.
    import google.cloud.pubsub

    # Create helper function for unpacking values
    def get_values(obj):
        return int(obj.integer_value)

    # Instantiate a client.
    dlp = google.cloud.dlp_v2.DlpServiceClient()

    # Convert the project id into a full resource id.
    topic = google.cloud.pubsub.PublisherClient.topic_path(project, topic_id)
    parent = f"projects/{project}/locations/global"

    # Location info of the BigQuery table.
    source_table = {
        "project_id": table_project_id,
        "dataset_id": dataset_id,
        "table_id": table_id,
    }

    # Convert quasi id list to Protobuf type
    def map_fields(field):
        return {"name": field}

    quasi_ids = map(map_fields, quasi_ids)

    # Tell the API where to send a notification when the job is complete.
    actions = [{"pub_sub": {"topic": topic}}]

    # Configure risk analysis job
    # Give the name of the numeric column to compute risk metrics for
    risk_job = {
        "privacy_metric": {"k_anonymity_config": {"quasi_ids": quasi_ids}},
        "source_table": source_table,
        "actions": actions,
    }

    # Call API to start risk analysis job
    operation = dlp.create_dlp_job(request={"parent": parent, "risk_job": risk_job})

    def callback(message):
        if message.attributes["DlpJobName"] == operation.name:
            # This is the message we're looking for, so acknowledge it.
            message.ack()

            # Now that the job is done, fetch the results and print them.
            job = dlp.get_dlp_job(request={"name": operation.name})
            print(f"Job name: {job.name}")
            histogram_buckets = (
                job.risk_details.k_anonymity_result.equivalence_class_histogram_buckets
            )
            # Print bucket stats
            for i, bucket in enumerate(histogram_buckets):
                print("Bucket {}:".format(i))
                if bucket.equivalence_class_size_lower_bound:
                    print(
                        "   Bucket size range: [{}, {}]".format(
                            bucket.equivalence_class_size_lower_bound,
                            bucket.equivalence_class_size_upper_bound,
                        )
                    )
                    for value_bucket in bucket.bucket_values:
                        print(
                            "   Quasi-ID values: {}".format(
                                map(get_values, value_bucket.quasi_ids_values)
                            )
                        )
                        print(
                            "   Class size: {}".format(
                                value_bucket.equivalence_class_size
                            )
                        )
            subscription.set_result(None)
        else:
            # This is not the message we're looking for.
            message.drop()

    # Create a Pub/Sub client and find the subscription. The subscription is
    # expected to already be listening to the topic.
    subscriber = google.cloud.pubsub.SubscriberClient()
    subscription_path = subscriber.subscription_path(project, subscription_id)
    subscription = subscriber.subscribe(subscription_path, callback)

    try:
        subscription.result(timeout=timeout)
    except concurrent.futures.TimeoutError:
        print(
            "No event received before the timeout. Please verify that the "
            "subscription provided is subscribed to the topic provided."
        )
        subscription.close()

Go

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.

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"
)

// riskKAnonymity computes the risk of the given columns using K Anonymity.
func riskKAnonymity(w io.Writer, projectID, dataProject, pubSubTopic, pubSubSub, datasetID, tableID 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"
	// columnNames := "state_number" "county"
	ctx := context.Background()
	client, err := dlp.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("dlp.NewClient: %v", err)
	}

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

	// Create a PubSub subscription we can use to listen for messages.
	s, err := setupPubSub(projectID, pubSubTopic, pubSubSub)
	if err != nil {
		return fmt.Errorf("setupPubSub: %v", err)
	}

	// topic is the PubSub topic string where messages should be sent.
	topic := "projects/" + projectID + "/topics/" + pubSubTopic

	// Build the QuasiID slice.
	var q []*dlppb.FieldId
	for _, c := range columnNames {
		q = append(q, &dlppb.FieldId{Name: c})
	}

	// Create a configured request.
	req := &dlppb.CreateDlpJobRequest{
		Parent: fmt.Sprintf("projects/%s/locations/global", projectID),
		Job: &dlppb.CreateDlpJobRequest_RiskJob{
			RiskJob: &dlppb.RiskAnalysisJobConfig{
				// PrivacyMetric configures what to compute.
				PrivacyMetric: &dlppb.PrivacyMetric{
					Type: &dlppb.PrivacyMetric_KAnonymityConfig_{
						KAnonymityConfig: &dlppb.PrivacyMetric_KAnonymityConfig{
							QuasiIds: q,
						},
					},
				},
				// SourceTable describes where to find the data.
				SourceTable: &dlppb.BigQueryTable{
					ProjectId: dataProject,
					DatasetId: datasetID,
					TableId:   tableID,
				},
				// Send a message to PubSub using Actions.
				Actions: []*dlppb.Action{
					{
						Action: &dlppb.Action_PubSub{
							PubSub: &dlppb.Action_PublishToPubSub{
								Topic: topic,
							},
						},
					},
				},
			},
		},
	}
	// Create the risk job.
	j, err := client.CreateDlpJob(ctx, req)
	if err != nil {
		return fmt.Errorf("CreateDlpJob: %v", err)
	}
	fmt.Fprintf(w, "Created job: %v\n", j.GetName())

	// Wait for the risk job to finish by waiting for a PubSub message.
	// This only waits for 10 minutes. For long jobs, consider using a truly
	// asynchronous execution model such as Cloud Functions.
	ctx, cancel := context.WithTimeout(ctx, 10*time.Minute)
	defer cancel()
	err = s.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		// If this is the wrong job, do not process the result.
		if msg.Attributes["DlpJobName"] != j.GetName() {
			msg.Nack()
			return
		}
		msg.Ack()
		time.Sleep(500 * time.Millisecond)
		j, err := client.GetDlpJob(ctx, &dlppb.GetDlpJobRequest{
			Name: j.GetName(),
		})
		if err != nil {
			fmt.Fprintf(w, "GetDlpJob: %v", err)
			return
		}
		h := j.GetRiskDetails().GetKAnonymityResult().GetEquivalenceClassHistogramBuckets()
		for i, b := range h {
			fmt.Fprintf(w, "Histogram bucket %v\n", i)
			fmt.Fprintf(w, "  Size range: [%v,%v]\n", b.GetEquivalenceClassSizeLowerBound(), b.GetEquivalenceClassSizeUpperBound())
			fmt.Fprintf(w, "  %v unique values total\n", b.GetBucketSize())
			for _, v := range b.GetBucketValues() {
				var qvs []string
				for _, qv := range v.GetQuasiIdsValues() {
					qvs = append(qvs, qv.String())
				}
				fmt.Fprintf(w, "    QuasiID values: %s\n", strings.Join(qvs, ", "))
				fmt.Fprintf(w, "    Class size: %v\n", v.GetEquivalenceClassSize())
			}
		}
		// Stop listening for more messages.
		cancel()
	})
	if err != nil {
		return fmt.Errorf("Receive: %v", err)
	}
	return nil
}

PHP

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.

use Google\Cloud\Dlp\V2\DlpServiceClient;
use Google\Cloud\Dlp\V2\RiskAnalysisJobConfig;
use Google\Cloud\Dlp\V2\BigQueryTable;
use Google\Cloud\Dlp\V2\DlpJob\JobState;
use Google\Cloud\Dlp\V2\Action;
use Google\Cloud\Dlp\V2\Action\PublishToPubSub;
use Google\Cloud\Dlp\V2\PrivacyMetric\KAnonymityConfig;
use Google\Cloud\Dlp\V2\PrivacyMetric;
use Google\Cloud\Dlp\V2\FieldId;
use Google\Cloud\PubSub\PubSubClient;

/**
 * Computes the k-anonymity of a column set in a Google BigQuery table.
 *
 * @param string    $callingProjectId  The project ID to run the API call under
 * @param string    $dataProjectId     The project ID containing the target Datastore
 * @param string    $topicId           The name of the Pub/Sub topic to notify once the job completes
 * @param string    $subscriptionId    The name of the Pub/Sub subscription to use when listening for job
 * @param string    $datasetId         The ID of the dataset to inspect
 * @param string    $tableId           The ID of the table to inspect
 * @param string[]  $quasiIdNames      Array columns that form a composite key (quasi-identifiers)
 */
function k_anonymity(
    string $callingProjectId,
    string $dataProjectId,
    string $topicId,
    string $subscriptionId,
    string $datasetId,
    string $tableId,
    array $quasiIdNames
): void {
    // Instantiate a client.
    $dlp = new DlpServiceClient([
        'projectId' => $callingProjectId,
    ]);
    $pubsub = new PubSubClient([
        'projectId' => $callingProjectId,
    ]);
    $topic = $pubsub->topic($topicId);

    // Construct risk analysis config
    $quasiIds = array_map(
        function ($id) {
            return (new FieldId())->setName($id);
        },
        $quasiIdNames
    );

    $statsConfig = (new KAnonymityConfig())
        ->setQuasiIds($quasiIds);

    $privacyMetric = (new PrivacyMetric())
        ->setKAnonymityConfig($statsConfig);

    // Construct items to be analyzed
    $bigqueryTable = (new BigQueryTable())
        ->setProjectId($dataProjectId)
        ->setDatasetId($datasetId)
        ->setTableId($tableId);

    // Construct the action to run when job completes
    $pubSubAction = (new PublishToPubSub())
        ->setTopic($topic->name());

    $action = (new Action())
        ->setPubSub($pubSubAction);

    // Construct risk analysis job config to run
    $riskJob = (new RiskAnalysisJobConfig())
        ->setPrivacyMetric($privacyMetric)
        ->setSourceTable($bigqueryTable)
        ->setActions([$action]);

    // Listen for job notifications via an existing topic/subscription.
    $subscription = $topic->subscription($subscriptionId);

    // Submit request
    $parent = "projects/$callingProjectId/locations/global";
    $job = $dlp->createDlpJob($parent, [
        'riskJob' => $riskJob
    ]);

    // Poll Pub/Sub using exponential backoff until job finishes
    // Consider using an asynchronous execution model such as Cloud Functions
    $attempt = 1;
    $startTime = time();
    do {
        foreach ($subscription->pull() as $message) {
            if (isset($message->attributes()['DlpJobName']) &&
                $message->attributes()['DlpJobName'] === $job->getName()) {
                $subscription->acknowledge($message);
                // Get the updated job. Loop to avoid race condition with DLP API.
                do {
                    $job = $dlp->getDlpJob($job->getName());
                } while ($job->getState() == JobState::RUNNING);
                break 2; // break from parent do while
            }
        }
        printf('Waiting for job to complete' . PHP_EOL);
        // Exponential backoff with max delay of 60 seconds
        sleep(min(60, pow(2, ++$attempt)));
    } while (time() - $startTime < 600); // 10 minute timeout

    // Print finding counts
    printf('Job %s status: %s' . PHP_EOL, $job->getName(), JobState::name($job->getState()));
    switch ($job->getState()) {
        case JobState::DONE:
            $histBuckets = $job->getRiskDetails()->getKAnonymityResult()->getEquivalenceClassHistogramBuckets();

            foreach ($histBuckets as $bucketIndex => $histBucket) {
                // Print bucket stats
                printf('Bucket %s:' . PHP_EOL, $bucketIndex);
                printf(
                    '  Bucket size range: [%s, %s]' . PHP_EOL,
                    $histBucket->getEquivalenceClassSizeLowerBound(),
                    $histBucket->getEquivalenceClassSizeUpperBound()
                );

                // Print bucket values
                foreach ($histBucket->getBucketValues() as $percent => $valueBucket) {
                    // Pretty-print quasi-ID values
                    print('  Quasi-ID values:' . PHP_EOL);
                    foreach ($valueBucket->getQuasiIdsValues() as $index => $value) {
                        print('    ' . $value->serializeToJsonString() . PHP_EOL);
                    }
                    printf(
                        '  Class size: %s' . PHP_EOL,
                        $valueBucket->getEquivalenceClassSize()
                    );
                }
            }

            break;
        case JobState::FAILED:
            printf('Job %s had errors:' . PHP_EOL, $job->getName());
            $errors = $job->getErrors();
            foreach ($errors as $error) {
                var_dump($error->getDetails());
            }
            break;
        case JobState::PENDING:
            printf('Job has not completed. Consider a longer timeout or an asynchronous execution model' . PHP_EOL);
            break;
        default:
            printf('Unexpected job state. Most likely, the job is either running or has not yet started.');
    }
}

C#

Informationen zum Installieren und Verwenden der Clientbibliothek für Cloud DLP finden Sie unter Cloud DLP-Clientbibliotheken.


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 RiskAnalysisCreateKAnonymity
{
    public static AnalyzeDataSourceRiskDetails.Types.KAnonymityResult KAnonymity(
        string callingProjectId,
        string tableProjectId,
        string datasetId,
        string tableId,
        string topicId,
        string subscriptionId,
        IEnumerable<FieldId> quasiIds)
    {
        var dlp = DlpServiceClient.Create();

        // Construct + submit the job
        var KAnonymityConfig = new KAnonymityConfig
        {
            QuasiIds = { quasiIds }
        };

        var config = new RiskAnalysisJobConfig
        {
            PrivacyMetric = new PrivacyMetric
            {
                KAnonymityConfig = KAnonymityConfig
            },
            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.KAnonymityResult;

        for (var bucketIdx = 0; bucketIdx < result.EquivalenceClassHistogramBuckets.Count; bucketIdx++)
        {
            var bucket = result.EquivalenceClassHistogramBuckets[bucketIdx];
            Console.WriteLine($"Bucket {bucketIdx}");
            Console.WriteLine($"  Bucket size range: [{bucket.EquivalenceClassSizeLowerBound}, {bucket.EquivalenceClassSizeUpperBound}].");
            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}");
            }
        }

        return result;
    }

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

Abgeschlossene Risikoanalysejobs auflisten

Sie können eine Liste der Risikoanalysejobs aufrufen, die im aktuellen Projekt ausgeführt wurden.

Console

So listen Sie laufende und zuvor durchgeführte Risikoanalysejobs in der Google Cloud Console auf:

  1. Öffnen Sie Cloud DLP in der Google Cloud Console.

    Zu Cloud DLP

  2. Klicken Sie oben auf der Seite auf den Tab Jobs und Job-Trigger.

  3. Klicken Sie auf den Tab Risikojobs.

Die Liste der Risikojobs wird angezeigt.

Protokoll

Senden Sie eine GET-Anfrage an die Ressource projects.dlpJobs, um gerade ausgeführte und zuvor ausgeführte Risikoanalysejobs aufzulisten. Durch Hinzufügen eines Jobtypfilters (?type=RISK_ANALYSIS_JOB) wird die Antwort auf nur Risikoanalysejobs beschränkt.

https://dlp.googleapis.com/v2/projects/PROJECT_ID/dlpJobs?type=RISK_ANALYSIS_JOB

Die erhaltene Antwort enthält eine JSON-Darstellung aller aktuellen und vorherigen Risikoanalysejobs.

k-Anonymität-Job-Ergebnisse ansehen

Cloud DLP in der Google Cloud Console bietet integrierte Visualisierungen für abgeschlossene k-Anonymitätsjobs. Nachdem Sie der Anleitung im vorherigen Abschnitt gefolgt sind, wählen Sie aus der Liste der Risikoanalysejobs den Job aus, für den Sie Ergebnisse ansehen möchten. Wenn der Job erfolgreich ausgeführt wurde, sieht die Seite Risikoanalysedetails oben so aus:

Oben auf der Seite finden Sie Informationen zum k-Anonymitäts-Risikojob, einschließlich seiner Job-ID und unter Container seine Ressourcenstandort.

Klicken Sie auf den Tab k-Anonymität, um die Ergebnisse der k-Anonymitätsberechnung anzuzeigen. Klicken Sie zum Anzeigen der Konfiguration des Risikoanalysejobs auf den Tab Konfiguration.

Der Tab k-Anonymität listet zuerst die Entitäts-ID (falls vorhanden) und die Quasi-Kennzeichnungen auf, die zur Berechnung der k-Anonymität verwendet werden.

Risikodiagramm

Im Diagramm Re-Identifikationsrisiko-wird auf der y-Achse der potenzielle Prozentsatz des Datenverlusts sowohl für eindeutige Zeilen als auch für eindeutige Quasi-Identifikator-Kombinationen dargestellt, um auf der x-Achse einen k-Anonymitätswert zu erreichen. Die Farbe des Diagramms zeigt auch das Risikopotenzial an. Dunklere Blautöne weisen auf ein höheres Risiko hin, hellere auf ein geringeres Risiko.

Höhere k-Anonymitätswerte weisen auf ein geringeres Risiko einer Re-Identifikation hin. Um höhere k-Anonymitätswerte zu erreichen, müssten Sie jedoch höhere Prozentsätze der gesamten Zeilen und höhere eindeutige Quasi-Identifier-Kombinationen entfernen, was den Nutzen der Daten verringern könnte. Bewegen Sie den Mauszeiger über das Diagramm, um einen bestimmten potenziellen prozentualen Verlustwert für einen bestimmten k-Anonymitätswert anzuzeigen. Wie im Screenshot dargestellt, wird im Diagramm eine Kurzinfo angezeigt.

Klicken Sie auf den entsprechenden Datenpunkt, um weitere Details zu einem bestimmten k-Anonymitätswert anzuzeigen. Unter dem Diagramm wird eine detaillierte Erläuterung angezeigt und weiter unten auf der Seite wird eine Beispieldatentabelle angezeigt.

Risiko-Beispieldatentabelle

Die zweite Komponente der Ergebnisseite für Risikojobs ist die Beispieldatentabelle. Darin werden Quasi-Identifikatoren-Kombinationen für einen bestimmten Ziel-k-Anonymitätswert angezeigt.

Die erste Spalte der Tabelle enthält die k-Anonymitätswerte. Klicken Sie auf einen k-Anonymitätswert, um die entsprechenden Beispieldaten anzuzeigen, die gelöscht werden müssten, um diesen Wert zu erreichen.

Die zweite Spalte zeigt den jeweiligen potenziellen Datenverlust von einzigartigen Zeilen und Quasi-Identifikatoren-Kombinationen sowie die Anzahl der Gruppen mit mindestens k Datensätzen und die Gesamtzahl der Datensätze an.

Die letzte Spalte enthält eine Auswahl an Gruppen die eine Quasi-Identifikatoren-Kombination gemeinsam nutzen und die Anzahl der Datensätze, die für diese Kombination vorhanden sind.

Jobdetails mit REST abrufen

Wenn Sie die Ergebnisse des k-Anonymität-Risikoanalysejobs mit der REST API abrufen möchten, senden Sie die folgende GET-Anfrage an die projects.dlpJobs-Ressource. Ersetzen Sie PROJECT_ID durch Ihre Projekt-ID und JOB_ID durch die ID des Jobs, für den Sie Ergebnisse erhalten möchten. Die Job-ID wurde beim Start des Jobs zurückgegeben und kann auch durch Auflisten aller Jobs abgerufen werden.

GET https://dlp.googleapis.com/v2/projects/PROJECT_ID/dlpJobs/JOB_ID

Die Anfrage gibt ein JSON-Objekt zurück, das eine Instanz des Jobs enthält. Die Ergebnisse der Analyse befinden sich im Schlüssel "riskDetails" in einem AnalyzeDataSourceRiskDetails-Objekt. Weitere Informationen finden Sie in der API-Referenz zur Ressource DlpJob.

Nächste Schritte