データセットの k-マップの計算

k-マップは、k-匿名性とよく似ていますが、攻撃者がデータセットに含まれる人物を知らない可能性が高い点が異なります。k-マップは、データセットが比較的小規模である場合や、属性を一般化するのに必要な労力のレベルが高すぎる場合に使用します。

k-匿名性と同じように、k-マップを使用するには、データベースのどの列が準識別子であるかを決定する必要があります。この作業では、データセットに含まれる個人を特定するために攻撃者が使用する可能性が高いデータを明確にします。さらに、k-マップの値を計算するには、元のデータセット内の行と比較するためのより大きなテーブルである再識別データセットが必要です。

このトピックでは、機密データの保護を使用してデータセットの k-マップの値を計算する方法について説明します。k-マップまたはリスク分析の概要については、続行する前に、リスク分析のコンセプトのトピックをご覧ください。

はじめる前に

続行する前に、以下を行ってください。

  1. Google アカウントにログインします。
  2. Google Cloud コンソールのプロジェクト セレクタページで、 Google Cloud プロジェクトを選択または作成します。
  3. プロジェクト セレクタに移動
  4. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する
  5. Sensitive Data Protection を有効にします。
  6. 機密データの保護を有効にする

  7. 分析する BigQuery データセットを選択します。機密データの保護は、BigQuery テーブルをスキャンして k-マップ指標を見積もります。
  8. 攻撃データセットをモデル化するために使用するデータセットの種類を決定します。詳細については、KMapEstimationConfig オブジェクトのリファレンス ページ、リスク分析の用語と手法をご覧ください。

k-マップ推定値の計算

機密データの保護を使用して k-マップの値を推定できます。機密データの保護は、統計モデルを使用して再識別データセットを推定します。これは、攻撃データセットが明示的に知られている他のリスク分析手法とは対照的です。機密データの保護は、データの種類に応じて、一般に公開されているデータセット(米国国勢調査のデータセットなど)またはカスタム統計モデル(ユーザーが指定する 1 つ以上の BigQuery テーブルなど)を使用するか、ユーザーが入力したデータセット内の値の分布から推定します。詳細については、KMapEstimationConfig オブジェクトのリファレンス ページをご覧ください。

Sensitive Data Protection を使用して k-マップの推定値を計算するには、まずリスクジョブを構成します。projects.dlpJobs リソースに対するリクエストを作成します。ここで、PROJECT_IDプロジェクトの識別子を示します。

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

このリクエストには、次の項目で構成される RiskAnalysisJobConfig オブジェクトが含まれます。

  • PrivacyMetric オブジェクト。ここで、以下を含む KMapEstimationConfig オブジェクトを指定して、k-マップを計算することを指定します。

    • quasiIds[]: 必須。準識別子とみなされるフィールド(TaggedField オブジェクト)です。k-マップを計算するためにスキャンして使用されます。2 つの列に同じタグを付けることはできません。次のいずれかを指定できます。

      • infoType: これによって、機密データの保護は、関連する一般公開データセットを母集団の統計モデルとして使用します(米国の郵便番号、地域コード、年齢、性別など)。
      • カスタム infoType: この列の有効な値に関する統計情報を含む補助テーブル(AuxiliaryTable オブジェクト)を示すカスタムタグ。
      • inferred タグ: 意味のあるタグが示されない場合は、inferred を指定します。Sensitive Data Protection は入力データ内の値の分布から統計モデルを推定します。
    • regionCode: Sensitive Data Protection が統計モデリングで使用する ISO 3166-1 alpha-2 地域コード。この値は、列が地域固有の infoType(米国の郵便番号など)または地域コードでタグ付けされていない場合に必要です。

    • auxiliaryTables[]: 分析で使用する補助テーブル(AuxiliaryTable オブジェクト)。準識別子(quasiIds[])の列に付けるカスタムタグは、それぞれ 1 つの補助テーブルの 1 つの列でのみ使用する必要があります。

  • BigQueryTable オブジェクト。次のすべてを含めることで、スキャンする BigQuery テーブルを指定します。

    • projectId: テーブルを含むプロジェクトのプロジェクト ID。
    • datasetId: テーブルのデータセット ID。
    • tableId: テーブルの名前。
  • 1 つ以上の Action オブジェクトのセット。これは、ジョブの完了時に所定の順序で実行するアクションを表します。各 Action オブジェクトには、次のいずれかのアクションを含めることができます。

コードの例

以下に、機密データの保護を使用して k-マップの値を計算する方法を示すサンプルコードをいくつかの言語で示します。

Go

機密データの保護用のクライアント ライブラリをインストールして使用する方法については、機密データの保護のクライアント ライブラリをご覧ください。

機密データの保護のために認証するには、アプリケーションのデフォルト認証情報を設定します。 詳細については、ローカル開発環境の認証の設定をご覧ください。

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"
	"github.com/golang/protobuf/ptypes/empty"
)

// riskKMap runs K Map on the given data.
func riskKMap(w io.Writer, projectID, dataProject, pubSubTopic, pubSubSub, datasetID, tableID, region string, columnNames ...string) error {
	// projectID := "my-project-id"
	// dataProject := "bigquery-public-data"
	// pubSubTopic := "dlp-risk-sample-topic"
	// pubSubSub := "dlp-risk-sample-sub"
	// datasetID := "san_francisco"
	// tableID := "bikeshare_trips"
	// region := "US"
	// columnNames := "zip_code"
	ctx := context.Background()
	client, err := dlp.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("dlp.NewClient: %w", err)
	}

	// 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(ctx, pubSubTopic); err != nil {
			return err
		}
	}

	// Create the Subscription if it doesn't exist.
	s := pubsubClient.Subscription(pubSubSub)
	subExists, err := s.Exists(ctx)
	if err != nil {
		return err
	}
	if !subExists {
		if s, err = pubsubClient.CreateSubscription(ctx, pubSubSub, pubsub.SubscriptionConfig{Topic: t}); err != nil {
			return err
		}
	}

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

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

	// 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_KMapEstimationConfig_{
						KMapEstimationConfig: &dlppb.PrivacyMetric_KMapEstimationConfig{
							QuasiIds:   q,
							RegionCode: region,
						},
					},
				},
				// 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