機密データの匿名化

Cloud Data Loss Prevention(DLP)を使用すると、テキスト コンテンツ内の機密データを匿名化できます。テーブルなどのコンテナ構造に保存されているテキストも匿名化できます。匿名化は、身元がわかる情報をデータから取り除くプロセスです。この API は、個人識別情報(PII)などの機密データを検出し、匿名化変換を使用してデータのマスキングや削除、難読化を行います。たとえば、匿名化では次のような処理を行います。

  • 文字の一部またはすべてをアスタリスク(*)やハッシュ(#)などの記号で置換し、機密データを「マスキング」します。
  • 機密データのインスタンスを「トークン」またはサロゲートで置換します。
  • ランダムに生成された鍵または事前定義の鍵で機密データを暗号化します。

CryptoReplaceFfxFpeConfigCryptoDeterministicConfig といった infoType トランスフォーメーションを使用してデータを匿名化する場合、データの匿名化に使用した CryptoKey が存在している限り、そのデータは再識別できます。

API には、JSON を使用して HTTP 経由で情報を渡します。また、CLI やプログラミング言語で DLP クライアント ライブラリを使用することもできます。CLI の設定方法については、クイックスタートをご覧ください。JSON 形式で情報を送信する方法については、JSON クイックスタートをご覧ください。

API の概要

機密データの匿名化を行うには、Cloud DLP の content.deidentify メソッドを使用します。

匿名化 API 呼び出しには 3 つの部分があります。

  • 検査するデータ: API で検査する文字列またはテーブル構造(ContentItem オブジェクト)。
  • 検査対象: 検索対象データの種類(または infoTypes)、特定の可能性しきい値を超えた結果をフィルタリングするかどうか、特定の数を超える結果は返さないかどうか、などの検出の構成情報(InspectConfig)を指定します。InspectConfig 引数に infoType を 1 つも指定しないことは、すべての組み込み infoType を指定することと同じです。この方法は、パフォーマンスの低下とコストの増加の原因となる可能性があるため、おすすめしません。
  • 検査結果の処理方法: 機密データの匿名化方法を定義する構成情報(DeidentifyConfig)。この引数については、後のセクションで詳しく説明します。

API は指定された項目を同じ形式で返しますが、機密情報が含まれるとみなされたテキストは条件に従って匿名化されます。

検出基準を指定する

情報タイプ(または「infoType」)検出器は、Cloud DLP が機密データを検出するためのメカニズムを提供します。

Cloud DLP にはいくつかの種類の infoType 検出器があります。ここではすべての種類について概要を説明します。

  • 組み込みの infoType 検出器は Cloud DLP に組み込まれています。この種類には、国や地域に固有の機密データタイプと世界のどこにも適用できるデータタイプに対応する検出器が含まれています。
  • カスタムの infoType 検出器は、ユーザー自身が作成する検出器です。カスタム infoType 検出器には、次の 3 種類があります。
    • 標準のカスタム辞書検出器は、Cloud DLP による照合の対象になる単純な単語リストです。含まれる単語やフレーズの数が数万個までのリストでは、標準のカスタム辞書検出器を使用します。単語リストが大幅に変更される予定がない場合、標準のカスタム辞書検出器の使用をおすすめします。
    • 格納されるカスタムの辞書検出器は、Cloud Storage または BigQuery に保存されている単語やフレーズの大規模なリストを使用して、Cloud DLP によって生成されます。含まれる単語やフレーズの数が数千万個までの大規模なリストでは、格納されるカスタム辞書検出器を使用します。
    • 正規表現(regex)検出器を使用すると、正規表現パターンに基づき、Cloud DLP によって一致を検出できます。

Cloud DLP には検査ルールのコンセプトも含まれています。次の検査ルールを使用してスキャン結果を細かく調整できます。

  • 除外ルールを適用すると、組み込みまたはカスタムの infoType 検出器にルールを追加することで、返される結果の数を少なくできます。
  • ホットワード ルールを適用すると、組み込みまたはカスタムの infoType 検出器にルールを追加することで、返される結果の数を増やしたり、結果の可能性の値を変更したりできます。

匿名化変換

匿名化構成(DeidentifyConfig)を設定するときは、1 つ以上の変換を指定する必要があります。変換には 2 つのカテゴリがあります。

  • InfoTypeTransformations: 送信されたテキスト内で特定の infoType として識別された値にのみ適用される変換。
  • RecordTransformations: 送信された表形式のテキストデータ内で、特定の infoType として識別された値または表形式データの列全体にのみ適用される変換。

infoType 変換

リクエストごとに 1 つ以上の infoType 変換を指定できます。各 InfoTypeTransformation オブジェクトに次の両方を指定します。

  • 変換を適用する 1 つ以上の infoTypeinfoTypes[] 配列オブジェクト)
  • プリミティブ変換(PrimitiveTransformation オブジェクト)

infoType の指定はオプションですが、InspectConfig 引数に 1 つも infoType を指定しないと、変換が指定されていないすべての組み込み infoType に変換を適用されてしまいます。この方法は、パフォーマンスの低下とコストの増加の原因となる可能性があるため、おすすめしません。

プリミティブ変換

特定の infoType に適用するのか、テキスト文字列全体に適用するのかに関係なく、入力テキストに適用するプリミティブ変換を 1 つ以上指定する必要があります。いくつかの変換オプションがあります。以下の表に概要を示します。詳細については、オブジェクト名をクリックしてください。

使用可能な変換の完全なリスト

replaceConfig

replaceConfigReplaceValueConfig オブジェクトに設定すると、一致した入力値が指定値で置換されます。

たとえば、すべての EMAIL_ADDRESS infoType で replaceConfig[email-address] に設定し、次の文字列を Cloud DLP に送信したとします。

My name is Alicia Abernathy, and my email address is aabernathy@example.com.

次の文字列が返されます。

My name is Alicia Abernathy, and my email address is [email-address].

次の JSON の例は、API リクエストの作成方法と、Cloud DLP API で返されるものを示しています。

JSON 入力:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:deidentify?key={YOUR_API_KEY}

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is aabernathy@example.com."
  },
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "infoTypes":[
            {
              "name":"EMAIL_ADDRESS"
            }
          ],
          "primitiveTransformation":{
            "replaceConfig":{
              "newValue":{
                "stringValue":"[email-address]"
              }
            }
          }
        }
      ]
    }
  },
  "inspectConfig":{
    "infoTypes":[
      {
        "name":"EMAIL_ADDRESS"
      }
    ]
  }
}

JSON 出力:

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is [email-address]."
  },
  "overview":{
    "transformedBytes":"22",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"EMAIL_ADDRESS"
        },
        "transformation":{
          "replaceConfig":{
            "newValue":{
              "stringValue":"[email-address]"
            }
          }
        },
        "results":[
          {
            "count":"1",
            "code":"SUCCESS"
          }
        ],
        "transformedBytes":"22"
      }
    ]
  }
}
redactConfig

redactConfig を指定すると、値が完全に削除されます。redactConfig メッセージに引数はありません。指定すると、変換が有効になります。

たとえば、すべての EMAIL_ADDRESS infoType に redactConfig を指定し、次の文字列を Cloud DLP に送信したとします。

My name is Alicia Abernathy, and my email address is aabernathy@example.com.

次の文字列が返されます。

My name is Alicia Abernathy, and my email address is .

次の JSON の例は、API リクエストの作成方法と、Cloud DLP API で返されるものを示しています。

JSON 入力:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:deidentify?key={YOUR_API_KEY}

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is aabernathy@example.com."
  },
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "infoTypes":[
            {
              "name":"EMAIL_ADDRESS"
            }
          ],
          "primitiveTransformation":{
            "redactConfig":{

            }
          }
        }
      ]
    }
  },
  "inspectConfig":{
    "infoTypes":[
      {
        "name":"EMAIL_ADDRESS"
      }
    ]
  }
}

JSON 出力:

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is ."
  },
  "overview":{
    "transformedBytes":"22",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"EMAIL_ADDRESS"
        },
        "transformation":{
          "redactConfig":{

          }
        },
        "results":[
          {
            "count":"1",
            "code":"SUCCESS"
          }
        ],
        "transformedBytes":"22"
      }
    ]
  }
}
characterMaskConfig

characterMaskConfigCharacterMaskConfig オブジェクトに設定すると、指定した文字数が固定文字で置換され、文字列が部分的にマスキングされます。マスキングは、文字列の先頭または末尾から開始できます。この変換は、長整数などの数値型にも対応しています。

CharacterMaskConfig オブジェクトには独自の引数があります。

  • maskingCharacter: 機密値の各文字のマスキングに使用する文字。たとえば、アスタリスク(*)またはハッシュ(#)を指定して、クレジット カード番号などの一連の番号をマスキングできます。
  • numberToMask: マスキングする文字数。この値を設定しない場合、一致する文字がすべてマスキングされます。
  • reverseOrder: 文字を逆順でマスキングするかどうかを指定します。reverseOrder を true に設定すると、一致した値の文字が、値の末尾から先頭に向かってマスキングされます。false に設定すると、値の先頭からマスキングされます。
  • charactersToIgnore[]: 値のマスキング時にスキップする、1 つ以上の文字。たとえばここでハイフンを指定すると、電話番号をマスキングする際にハイフンをそのまま残せます。また、マスキングする際に無視する共通の文字グループ(CharsToIgnore)も指定できます。

次の JSON の例は、API リクエストの作成方法と、Cloud DLP API で返されるものを示しています。

JSON 入力:

POST https://dlp.googleapis.com/v2/projects/[PROJECT_ID]/content:deidentify?key={YOUR_API_KEY}

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is aabernathy@example.com."
  },
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "infoTypes":[
            {
              "name":"EMAIL_ADDRESS"
            }
          ],
          "primitiveTransformation":{
            "characterMaskConfig":{
              "maskingCharacter":"#",
              "reverseOrder":false,
              "charactersToIgnore":[
                {
                  "charactersToSkip":".@"
                }
              ]
            }
          }
        }
      ]
    }
  },
  "inspectConfig":{
    "infoTypes":[
      {
        "name":"EMAIL_ADDRESS"
      }
    ]
  }
}

JSON 出力:

{
  "item":{
    "value":"My name is Alicia Abernathy, and my email address is ##########@#######.###."
  },
  "overview":{
    "transformedBytes":"22",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"EMAIL_ADDRESS"
        },
        "transformation":{
          "characterMaskConfig":{
            "maskingCharacter":"#",
            "charactersToIgnore":[
              {
                "charactersToSkip":".@"
              }
            ]
          }
        },
        "results":[
          {
            "count":"1",
            "code":"SUCCESS"
          }
        ],
        "transformedBytes":"22"
      }
    ]
  }
}

この例では、次の文字列に characterMaskConfig を設定して Cloud DLP に送信した結果を示します。

My name is Alicia Abernathy, and my email address is aabernathy@example.com.

Cloud DLP は以下を返します。

My name is Alicia Abernathy, and my email address is ##########@#######.###.

以下に、Cloud DLP API を使用して機密データの匿名化(マスキング)を行うサンプルコードをいくつかの言語で示します。

Java

/**
 * Deidentify a string by masking sensitive information with a character using the DLP API.
 *
 * @param string The string to deidentify.
 * @param maskingCharacter (Optional) The character to mask sensitive data with.
 * @param numberToMask (Optional) The number of characters' worth of sensitive data to mask.
 *     Omitting this value or setting it to 0 masks all sensitive chars.
 * @param projectId ID of Google Cloud project to run the API under.
 */
private static void deIdentifyWithMask(
    String string,
    List<InfoType> infoTypes,
    Character maskingCharacter,
    int numberToMask,
    String projectId) {

  // instantiate a client
  try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) {

    ContentItem contentItem = ContentItem.newBuilder().setValue(string).build();

    CharacterMaskConfig characterMaskConfig =
        CharacterMaskConfig.newBuilder()
            .setMaskingCharacter(maskingCharacter.toString())
            .setNumberToMask(numberToMask)
            .build();

    // Create the deidentification transformation configuration
    PrimitiveTransformation primitiveTransformation =
        PrimitiveTransformation.newBuilder().setCharacterMaskConfig(characterMaskConfig).build();

    InfoTypeTransformation infoTypeTransformationObject =
        InfoTypeTransformation.newBuilder()
            .setPrimitiveTransformation(primitiveTransformation)
            .build();

    InfoTypeTransformations infoTypeTransformationArray =
        InfoTypeTransformations.newBuilder()
            .addTransformations(infoTypeTransformationObject)
            .build();

    InspectConfig inspectConfig =
        InspectConfig.newBuilder()
            .addAllInfoTypes(infoTypes)
            .build();

    DeidentifyConfig deidentifyConfig =
        DeidentifyConfig.newBuilder()
            .setInfoTypeTransformations(infoTypeTransformationArray)
            .build();

    // Create the deidentification request object
    DeidentifyContentRequest request =
        DeidentifyContentRequest.newBuilder()
            .setParent(ProjectName.of(projectId).toString())
            .setInspectConfig(inspectConfig)
            .setDeidentifyConfig(deidentifyConfig)
            .setItem(contentItem)
            .build();

    // Execute the deidentification request
    DeidentifyContentResponse response = dlpServiceClient.deidentifyContent(request);

    // Print the character-masked input value
    // e.g. "My SSN is 123456789" --> "My SSN is *********"
    String result = response.getItem().getValue();
    System.out.println(result);
  } catch (Exception e) {
    System.out.println("Error in deidentifyWithMask: " + e.getMessage());
  }
}

Node.js

// Imports the Google Cloud Data Loss Prevention library
const DLP = require('@google-cloud/dlp');

// Instantiates a client
const dlp = new DLP.DlpServiceClient();

// The project ID to run the API call under
// const callingProjectId = process.env.GCLOUD_PROJECT;

// The string to deidentify
// const string = 'My SSN is 372819127';

// (Optional) The maximum number of sensitive characters to mask in a match
// If omitted from the request or set to 0, the API will mask any matching characters
// const numberToMask = 5;

// (Optional) The character to mask matching sensitive data with
// const maskingCharacter = 'x';

// Construct deidentification request
const item = {value: string};
const request = {
  parent: dlp.projectPath(callingProjectId),
  deidentifyConfig: {
    infoTypeTransformations: {
      transformations: [
        {
          primitiveTransformation: {
            characterMaskConfig: {
              maskingCharacter: maskingCharacter,
              numberToMask: numberToMask,
            },
          },
        },
      ],
    },
  },
  item: item,
};

try {
  // Run deidentification request
  const [response] = await dlp.deidentifyContent(request);
  const deidentifiedItem = response.item;
  console.log(deidentifiedItem.value);
} catch (err) {
  console.log(`Error in deidentifyWithMask: ${err.message || err}`);
}

Python

def deidentify_with_mask(project, string, info_types, masking_character=None,
                         number_to_mask=0):
    """Uses the Data Loss Prevention API to deidentify sensitive data in a
    string by masking it with a character.
    Args:
        project: The Google Cloud project id to use as a parent resource.
        item: The string to deidentify (will be treated as text).
        masking_character: The character to mask matching sensitive data with.
        number_to_mask: The maximum number of sensitive characters to mask in
            a match. If omitted or set to zero, the API will default to no
            maximum.
    Returns:
        None; the response from the API is printed to the terminal.
    """

    # Import the client library
    import google.cloud.dlp

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

    # Convert the project id into a full resource id.
    parent = dlp.project_path(project)

    # Construct inspect configuration dictionary
    inspect_config = {
        'info_types': [{'name': info_type} for info_type in info_types]
    }

    # Construct deidentify configuration dictionary
    deidentify_config = {
        'info_type_transformations': {
            'transformations': [
                {
                    'primitive_transformation': {
                        'character_mask_config': {
                            'masking_character': masking_character,
                            'number_to_mask': number_to_mask
                        }
                    }
                }
            ]
        }
    }

    # Construct item
    item = {'value': string}

    # Call the API
    response = dlp.deidentify_content(
        parent, inspect_config=inspect_config,
        deidentify_config=deidentify_config, item=item)

    # Print out the results.
    print(response.item.value)

Go

// mask deidentifies the input by masking all provided info types with maskingCharacter
// and prints the result to w.
func mask(w io.Writer, client *dlp.Client, project, input string, infoTypes []string, maskingCharacter string, numberToMask int32) {
	// Convert the info type strings to a list of InfoTypes.
	var i []*dlppb.InfoType
	for _, it := range infoTypes {
		i = append(i, &dlppb.InfoType{Name: it})
	}
	// Create a configured request.
	req := &dlppb.DeidentifyContentRequest{
		Parent: "projects/" + project,
		InspectConfig: &dlppb.InspectConfig{
			InfoTypes: i,
		},
		DeidentifyConfig: &dlppb.DeidentifyConfig{
			Transformation: &dlppb.DeidentifyConfig_InfoTypeTransformations{
				InfoTypeTransformations: &dlppb.InfoTypeTransformations{
					Transformations: []*dlppb.InfoTypeTransformations_InfoTypeTransformation{
						{
							InfoTypes: []*dlppb.InfoType{}, // Match all info types.
							PrimitiveTransformation: &dlppb.PrimitiveTransformation{
								Transformation: &dlppb.PrimitiveTransformation_CharacterMaskConfig{
									CharacterMaskConfig: &dlppb.CharacterMaskConfig{
										MaskingCharacter: maskingCharacter,
										NumberToMask:     numberToMask,
									},
								},
							},
						},
					},
				},
			},
		},
		// The item to analyze.
		Item: &dlppb.ContentItem{
			DataItem: &dlppb.ContentItem_Value{
				Value: input,
			},
		},
	}
	// Send the request.
	r, err := client.DeidentifyContent(context.Background(), req)
	if err != nil {
		log.Fatal(err)
	}
	// Print the result.
	fmt.Fprint(w, r.GetItem().GetValue())
}

PHP

use Google\Cloud\Dlp\V2\CharacterMaskConfig;
use Google\Cloud\Dlp\V2\DlpServiceClient;
use Google\Cloud\Dlp\V2\InfoType;
use Google\Cloud\Dlp\V2\PrimitiveTransformation;
use Google\Cloud\Dlp\V2\DeidentifyConfig;
use Google\Cloud\Dlp\V2\InfoTypeTransformations\InfoTypeTransformation;
use Google\Cloud\Dlp\V2\InfoTypeTransformations;
use Google\Cloud\Dlp\V2\ContentItem;

/**
 * Deidentify sensitive data in a string by masking it with a character.
 * @param string $callingProjectId The GCP Project ID to run the API call under
 * @param string $string The string to deidentify
 * @param int $numberToMask (Optional) The maximum number of sensitive characters to mask in a match
 * @param string $maskingCharacter (Optional) The character to mask matching sensitive data with
 */
function deidentify_mask(
  $callingProjectId,
  $string,
  $numberToMask = 0,
  $maskingCharacter = 'x'
) {
    // Instantiate a client.
    $dlp = new DlpServiceClient();

    // The infoTypes of information to mask
    $ssnInfoType = (new InfoType())
        ->setName('US_SOCIAL_SECURITY_NUMBER');
    $infoTypes = [$ssnInfoType];

    // Create the masking configuration object
    $maskConfig = (new CharacterMaskConfig())
        ->setMaskingCharacter($maskingCharacter)
        ->setNumberToMask($numberToMask);

    // Create the information transform configuration objects
    $primitiveTransformation = (new PrimitiveTransformation())
        ->setCharacterMaskConfig($maskConfig);

    $infoTypeTransformation = (new InfoTypeTransformation())
        ->setPrimitiveTransformation($primitiveTransformation)
        ->setInfoTypes($infoTypes);

    $infoTypeTransformations = (new InfoTypeTransformations())
        ->setTransformations([$infoTypeTransformation]);

    // Create the deidentification configuration object
    $deidentifyConfig = (new DeidentifyConfig())
        ->setInfoTypeTransformations($infoTypeTransformations);

    $item = (new ContentItem())
        ->setValue($string);

    $parent = $dlp->projectName($callingProjectId);

    // Run request
    $response = $dlp->deidentifyContent($parent, [
        'deidentifyConfig' => $deidentifyConfig,
        'item' => $item
    ]);

    // Print the results
    $deidentifiedValue = $response->getItem()->getValue();
    print($deidentifiedValue);
}

C#

public static object DeidMask(
    string projectId,
    string dataValue,
    IEnumerable<InfoType> infoTypes,
    string maskingCharacter,
    int numberToMask,
    bool reverseOrder)
{
    var request = new DeidentifyContentRequest
    {
        ParentAsProjectName = new ProjectName(projectId),
        InspectConfig = new InspectConfig
        {
            InfoTypes = { infoTypes }
        },
        DeidentifyConfig = new DeidentifyConfig
        {
            InfoTypeTransformations = new InfoTypeTransformations
            {
                Transformations = {
                    new InfoTypeTransformations.Types.InfoTypeTransformation
                    {
                        PrimitiveTransformation = new PrimitiveTransformation
                        {
                            CharacterMaskConfig = new CharacterMaskConfig
                            {
                                MaskingCharacter = maskingCharacter,
                                NumberToMask = numberToMask,
                                ReverseOrder = reverseOrder
                            }
                        }
                    }
                }
            }
        },
        Item = new ContentItem
        {
            Value = dataValue
        }
    };

    DlpServiceClient dlp = DlpServiceClient.Create();
    var response = dlp.DeidentifyContent(request);

    Console.WriteLine($"Deidentified content: {response.Item.Value}");
    return 0;
}

cryptoHashConfig

CryptoHashConfig オブジェクトに cryptoHashConfig を設定すると、暗号ハッシュを使用してサロゲート値を生成することで、入力値が仮名化されます。

この方法では、暗号化された「ダイジェスト」またはハッシュ値で入力値を置き換えます。ダイジェストは、入力値の SHA-256 ハッシュを取って計算されます。ハッシュの作成で使用される暗号鍵は CryptoKey オブジェクトで、サイズは 32 バイトまたは 64 バイトでなければなりません。

この方法では、ハッシュされた出力の Base64 エンコード表現を出力します。現時点では、ハッシュできるのは文字列と整数値のみです。

たとえば、すべての cryptoHashConfig infoType に EMAIL_ADDRESS を指定し、CryptoKey オブジェクトがランダムに生成されたキー(TransientCryptoKey)から構成されているとします。次の文字列が Cloud DLP に送信されたとします。

My name is Alicia Abernathy, and my email address is aabernathy@example.com.

暗号的に生成されて返される文字列は、次のようになります。

My name is Alicia Abernathy, and my email address is 41D1567F7F99F1DC2A5FAB886DEE5BEE.

生成される 16 進文字列は暗号化されているため、上記のものとは異なります。

dateShiftConfig

DateShiftConfig オブジェクトに dateShiftConfig を設定すると、日付をランダムな日数だけシフトすることによって、日付入力値の日付シフトが行われます。

日付シフト手法では、日付のセットがランダムにシフトされますが、期間の順序と持続時間は保持されます。通常、日付シフトは、個人またはエンティティのコンテキストで行われます。特定の個人の日付はすべて同じシフト差異でシフトされますが、別の個人には異なるシフト差異が使用されます。

日付シフトの詳細については、日付シフトの概念トピックをご覧ください。

以下に、Cloud DLP API を使用して日付の匿名化(日付シフト)を行うサンプルコードをいくつかの言語で示します。

Java

/**
 * @param inputCsvPath The path to the CSV file to deidentify
 * @param outputCsvPath (Optional) path to the output CSV file
 * @param dateFields The list of (date) fields in the CSV file to date shift
 * @param lowerBoundDays The maximum number of days to shift a date backward
 * @param upperBoundDays The maximum number of days to shift a date forward
 * @param contextFieldId (Optional) The column to determine date shift, default : a random shift
 *     amount
 * @param wrappedKey (Optional) The encrypted ('wrapped') AES-256 key to use when shifting dates
 * @param keyName (Optional) The name of the Cloud KMS key used to encrypt ('wrap') the AES-256
 *     key
 * @param projectId ID of Google Cloud project to run the API under.
 */
private static void deidentifyWithDateShift(
    Path inputCsvPath,
    Path outputCsvPath,
    String[] dateFields,
    int lowerBoundDays,
    int upperBoundDays,
    String contextFieldId,
    String wrappedKey,
    String keyName,
    String projectId)
    throws Exception {
  // instantiate a client
  try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) {

    // Set the maximum days to shift a day backward (lowerbound), forward (upperbound)
    DateShiftConfig.Builder dateShiftConfigBuilder =
        DateShiftConfig.newBuilder()
            .setLowerBoundDays(lowerBoundDays)
            .setUpperBoundDays(upperBoundDays);

    // If contextFieldId, keyName or wrappedKey is set: all three arguments must be valid
    if (contextFieldId != null && keyName != null && wrappedKey != null) {
      dateShiftConfigBuilder.setContext(FieldId.newBuilder().setName(contextFieldId).build());
      KmsWrappedCryptoKey kmsWrappedCryptoKey =
          KmsWrappedCryptoKey.newBuilder()
              .setCryptoKeyName(keyName)
              .setWrappedKey(ByteString.copyFrom(BaseEncoding.base64().decode(wrappedKey)))
              .build();
      dateShiftConfigBuilder.setCryptoKey(
          CryptoKey.newBuilder().setKmsWrapped(kmsWrappedCryptoKey).build());

    } else if (contextFieldId != null || keyName != null || wrappedKey != null) {
      throw new IllegalArgumentException(
          "You must set either ALL or NONE of {contextFieldId, keyName, wrappedKey}!");
    }

    // Read and parse the CSV file
    BufferedReader br = null;
    String line;
    List<Table.Row> rows = new ArrayList<>();
    List<FieldId> headers;

    br = new BufferedReader(new FileReader(inputCsvPath.toFile()));

    // convert csv header to FieldId
    headers =
        Arrays.stream(br.readLine().split(","))
            .map(header -> FieldId.newBuilder().setName(header).build())
            .collect(Collectors.toList());

    while ((line = br.readLine()) != null) {
      // convert csv rows to Table.Row
      rows.add(convertCsvRowToTableRow(line));
    }
    br.close();

    Table table = Table.newBuilder().addAllHeaders(headers).addAllRows(rows).build();

    List<FieldId> dateFieldIds =
        Arrays.stream(dateFields)
            .map(field -> FieldId.newBuilder().setName(field).build())
            .collect(Collectors.toList());

    DateShiftConfig dateShiftConfig = dateShiftConfigBuilder.build();

    FieldTransformation fieldTransformation =
        FieldTransformation.newBuilder()
            .addAllFields(dateFieldIds)
            .setPrimitiveTransformation(
                PrimitiveTransformation.newBuilder().setDateShiftConfig(dateShiftConfig).build())
            .build();

    DeidentifyConfig deidentifyConfig =
        DeidentifyConfig.newBuilder()
            .setRecordTransformations(
                RecordTransformations.newBuilder()
                    .addFieldTransformations(fieldTransformation)
                    .build())
            .build();

    ContentItem tableItem = ContentItem.newBuilder().setTable(table).build();

    DeidentifyContentRequest request =
        DeidentifyContentRequest.newBuilder()
            .setParent(ProjectName.of(projectId).toString())
            .setDeidentifyConfig(deidentifyConfig)
            .setItem(tableItem)
            .build();

    // Execute the deidentification request
    DeidentifyContentResponse response = dlpServiceClient.deidentifyContent(request);

    // Write out the response as a CSV file
    List<FieldId> outputHeaderFields = response.getItem().getTable().getHeadersList();
    List<Table.Row> outputRows = response.getItem().getTable().getRowsList();

    List<String> outputHeaders =
        outputHeaderFields.stream().map(FieldId::getName).collect(Collectors.toList());

    File outputFile = outputCsvPath.toFile();
    if (!outputFile.exists()) {
      outputFile.createNewFile();
    }
    BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(outputFile));

    // write out headers
    bufferedWriter.append(String.join(",", outputHeaders) + "\n");

    // write out each row
    for (Table.Row outputRow : outputRows) {
      String row =
          outputRow
              .getValuesList()
              .stream()
              .map(value -> value.getStringValue())
              .collect(Collectors.joining(","));
      bufferedWriter.append(row + "\n");
    }

    bufferedWriter.flush();
    bufferedWriter.close();

    System.out.println("Successfully saved date-shift output to: " + outputCsvPath.getFileName());
  } catch (Exception e) {
    System.out.println("Error in deidentifyWithDateShift: " + e.getMessage());
  }
}

// Parse string to valid date, return null when invalid
private static LocalDate getValidDate(String dateString) {
  try {
    return LocalDate.parse(dateString);
  } catch (DateTimeParseException e) {
    return null;
  }
}

// convert CSV row into Table.Row
private static Table.Row convertCsvRowToTableRow(String row) {
  String[] values = row.split(",");
  Table.Row.Builder tableRowBuilder = Table.Row.newBuilder();
  for (String value : values) {
    LocalDate date = getValidDate(value);
    if (date != null) {
      // convert to com.google.type.Date
      Date dateValue =
          Date.newBuilder()
              .setYear(date.getYear())
              .setMonth(date.getMonthValue())
              .setDay(date.getDayOfMonth())
              .build();
      Value tableValue = Value.newBuilder().setDateValue(dateValue).build();
      tableRowBuilder.addValues(tableValue);
    } else {
      tableRowBuilder.addValues(Value.newBuilder().setStringValue(value).build());
    }
  }
  return tableRowBuilder.build();
}

Node.js

// Imports the Google Cloud Data Loss Prevention library
const DLP = require('@google-cloud/dlp');

// Instantiates a client
const dlp = new DLP.DlpServiceClient();

// Import other required libraries
const fs = require('fs');

// The project ID to run the API call under
// const callingProjectId = process.env.GCLOUD_PROJECT;

// The path to the CSV file to deidentify
// The first row of the file must specify column names, and all other rows
// must contain valid values
// const inputCsvFile = '/path/to/input/file.csv';

// The path to save the date-shifted CSV file to
// const outputCsvFile = '/path/to/output/file.csv';

// The list of (date) fields in the CSV file to date shift
// const dateFields = [{ name: 'birth_date'}, { name: 'register_date' }];

// The maximum number of days to shift a date backward
// const lowerBoundDays = 1;

// The maximum number of days to shift a date forward
// const upperBoundDays = 1;

// (Optional) The column to determine date shift amount based on
// If this is not specified, a random shift amount will be used for every row
// If this is specified, then 'wrappedKey' and 'keyName' must also be set
// const contextFieldId = [{ name: 'user_id' }];

// (Optional) The name of the Cloud KMS key used to encrypt ('wrap') the AES-256 key
// If this is specified, then 'wrappedKey' and 'contextFieldId' must also be set
// const keyName = 'projects/YOUR_GCLOUD_PROJECT/locations/YOUR_LOCATION/keyRings/YOUR_KEYRING_NAME/cryptoKeys/YOUR_KEY_NAME';

// (Optional) The encrypted ('wrapped') AES-256 key to use when shifting dates
// This key should be encrypted using the Cloud KMS key specified above
// If this is specified, then 'keyName' and 'contextFieldId' must also be set
// const wrappedKey = 'YOUR_ENCRYPTED_AES_256_KEY'

// Helper function for converting CSV rows to Protobuf types
const rowToProto = row => {
  const values = row.split(',');
  const convertedValues = values.map(value => {
    if (Date.parse(value)) {
      const date = new Date(value);
      return {
        dateValue: {
          year: date.getFullYear(),
          month: date.getMonth() + 1,
          day: date.getDate(),
        },
      };
    } else {
      // Convert all non-date values to strings
      return {stringValue: value.toString()};
    }
  });
  return {values: convertedValues};
};

// Read and parse a CSV file
const csvLines = fs
  .readFileSync(inputCsvFile)
  .toString()
  .split('\n')
  .filter(line => line.includes(','));
const csvHeaders = csvLines[0].split(',');
const csvRows = csvLines.slice(1);

// Construct the table object
const tableItem = {
  table: {
    headers: csvHeaders.map(header => {
      return {name: header};
    }),
    rows: csvRows.map(row => rowToProto(row)),
  },
};

// Construct DateShiftConfig
const dateShiftConfig = {
  lowerBoundDays: lowerBoundDays,
  upperBoundDays: upperBoundDays,
};

if (contextFieldId && keyName && wrappedKey) {
  dateShiftConfig.context = {name: contextFieldId};
  dateShiftConfig.cryptoKey = {
    kmsWrapped: {
      wrappedKey: wrappedKey,
      cryptoKeyName: keyName,
    },
  };
} else if (contextFieldId || keyName || wrappedKey) {
  throw new Error(
    'You must set either ALL or NONE of {contextFieldId, keyName, wrappedKey}!'
  );
}

// Construct deidentification request
const request = {
  parent: dlp.projectPath(callingProjectId),
  deidentifyConfig: {
    recordTransformations: {
      fieldTransformations: [
        {
          fields: dateFields,
          primitiveTransformation: {
            dateShiftConfig: dateShiftConfig,
          },
        },
      ],
    },
  },
  item: tableItem,
};

try {
  // Run deidentification request
  const [response] = await dlp.deidentifyContent(request);
  const tableRows = response.item.table.rows;

  // Write results to a CSV file
  tableRows.forEach((row, rowIndex) => {
    const rowValues = row.values.map(
      value =>
        value.stringValue ||
        `${value.dateValue.month}/${value.dateValue.day}/${
          value.dateValue.year
        }`
    );
    csvLines[rowIndex + 1] = rowValues.join(',');
  });
  csvLines.push('');
  fs.writeFileSync(outputCsvFile, csvLines.join('\n'));

  // Print status
  console.log(`Successfully saved date-shift output to ${outputCsvFile}`);
} catch (err) {
  console.log(`Error in deidentifyWithDateShift: ${err.message || err}`);
}

Python

def deidentify_with_date_shift(project, input_csv_file=None,
                               output_csv_file=None, date_fields=None,
                               lower_bound_days=None, upper_bound_days=None,
                               context_field_id=None, wrapped_key=None,
                               key_name=None):
    """Uses the Data Loss Prevention API to deidentify dates in a CSV file by
        pseudorandomly shifting them.
    Args:
        project: The Google Cloud project id to use as a parent resource.
        input_csv_file: The path to the CSV file to deidentify. The first row
            of the file must specify column names, and all other rows must
            contain valid values.
        output_csv_file: The path to save the date-shifted CSV file.
        date_fields: The list of (date) fields in the CSV file to date shift.
            Example: ['birth_date', 'register_date']
        lower_bound_days: The maximum number of days to shift a date backward
        upper_bound_days: The maximum number of days to shift a date forward
        context_field_id: (Optional) The column to determine date shift amount
            based on. If this is not specified, a random shift amount will be
            used for every row. If this is specified, then 'wrappedKey' and
            'keyName' must also be set. Example:
            contextFieldId = [{ 'name': 'user_id' }]
        key_name: (Optional) The name of the Cloud KMS key used to encrypt
            ('wrap') the AES-256 key. Example:
            key_name = 'projects/YOUR_GCLOUD_PROJECT/locations/YOUR_LOCATION/
            keyRings/YOUR_KEYRING_NAME/cryptoKeys/YOUR_KEY_NAME'
        wrapped_key: (Optional) The encrypted ('wrapped') AES-256 key to use.
            This key should be encrypted using the Cloud KMS key specified by
            key_name.
    Returns:
        None; the response from the API is printed to the terminal.
    """
    # Import the client library
    import google.cloud.dlp

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

    # Convert the project id into a full resource id.
    parent = dlp.project_path(project)

    # Convert date field list to Protobuf type
    def map_fields(field):
        return {'name': field}

    if date_fields:
        date_fields = map(map_fields, date_fields)
    else:
        date_fields = []

    # Read and parse the CSV file
    import csv
    from datetime import datetime
    f = []
    with open(input_csv_file, 'r') as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            f.append(row)

    #  Helper function for converting CSV rows to Protobuf types
    def map_headers(header):
        return {'name': header}

    def map_data(value):
        try:
            date = datetime.strptime(value, '%m/%d/%Y')
            return {
                'date_value': {
                    'year': date.year,
                    'month': date.month,
                    'day': date.day
                }
            }
        except ValueError:
            return {'string_value': value}

    def map_rows(row):
        return {'values': map(map_data, row)}

    # Using the helper functions, convert CSV rows to protobuf-compatible
    # dictionaries.
    csv_headers = map(map_headers, f[0])
    csv_rows = map(map_rows, f[1:])

    # Construct the table dict
    table_item = {
        'table': {
            'headers': csv_headers,
            'rows': csv_rows
        }
    }

    # Construct date shift config
    date_shift_config = {
        'lower_bound_days': lower_bound_days,
        'upper_bound_days': upper_bound_days
    }

    # If using a Cloud KMS key, add it to the date_shift_config.
    # The wrapped key is base64-encoded, but the library expects a binary
    # string, so decode it here.
    if context_field_id and key_name and wrapped_key:
        import base64
        date_shift_config['context'] = {'name': context_field_id}
        date_shift_config['crypto_key'] = {
            'kms_wrapped': {
                'wrapped_key': base64.b64decode(wrapped_key),
                'crypto_key_name': key_name
            }
        }
    elif context_field_id or key_name or wrapped_key:
        raise ValueError("""You must set either ALL or NONE of
        [context_field_id, key_name, wrapped_key]!""")

    # Construct Deidentify Config
    deidentify_config = {
        'record_transformations': {
            'field_transformations': [
                {
                    'fields': date_fields,
                    'primitive_transformation': {
                        'date_shift_config': date_shift_config
                    }
                }
            ]
        }
    }

    # Write to CSV helper methods
    def write_header(header):
        return header.name

    def write_data(data):
        return data.string_value or '%s/%s/%s' % (data.date_value.month,
                                                  data.date_value.day,
                                                  data.date_value.year)

    # Call the API
    response = dlp.deidentify_content(
        parent, deidentify_config=deidentify_config, item=table_item)

    # Write results to CSV file
    with open(output_csv_file, 'w') as csvfile:
        write_file = csv.writer(csvfile, delimiter=',')
        write_file.writerow(map(write_header, response.item.table.headers))
        for row in response.item.table.rows:
            write_file.writerow(map(write_data, row.values))
    # Print status
    print('Successfully saved date-shift output to {}'.format(
        output_csv_file))

Go

// deidentifyDateShift shifts dates found in the input between lowerBoundDays and
// upperBoundDays.
func deidentifyDateShift(w io.Writer, client *dlp.Client, project string, lowerBoundDays, upperBoundDays int32, input string) {
	// Create a configured request.
	req := &dlppb.DeidentifyContentRequest{
		Parent: "projects/" + project,
		DeidentifyConfig: &dlppb.DeidentifyConfig{
			Transformation: &dlppb.DeidentifyConfig_InfoTypeTransformations{
				InfoTypeTransformations: &dlppb.InfoTypeTransformations{
					Transformations: []*dlppb.InfoTypeTransformations_InfoTypeTransformation{
						{
							InfoTypes: []*dlppb.InfoType{}, // Match all info types.
							PrimitiveTransformation: &dlppb.PrimitiveTransformation{
								Transformation: &dlppb.PrimitiveTransformation_DateShiftConfig{
									DateShiftConfig: &dlppb.DateShiftConfig{
										LowerBoundDays: lowerBoundDays,
										UpperBoundDays: upperBoundDays,
									},
								},
							},
						},
					},
				},
			},
		},
		// The InspectConfig is used to identify the DATE fields.
		InspectConfig: &dlppb.InspectConfig{
			InfoTypes: []*dlppb.InfoType{
				{
					Name: "DATE",
				},
			},
		},
		// The item to analyze.
		Item: &dlppb.ContentItem{
			DataItem: &dlppb.ContentItem_Value{
				Value: input,
			},
		},
	}
	// Send the request.
	r, err := client.DeidentifyContent(context.Background(), req)
	if err != nil {
		log.Fatal(err)
	}
	// Print the result.
	fmt.Fprint(w, r.GetItem().GetValue())
}

PHP

use Google\Cloud\Dlp\V2\ContentItem;
use Google\Cloud\Dlp\V2\CryptoKey;
use Google\Cloud\Dlp\V2\DateShiftConfig;
use Google\Cloud\Dlp\V2\DeidentifyConfig;
use Google\Cloud\Dlp\V2\DlpServiceClient;
use Google\Cloud\Dlp\V2\FieldId;
use Google\Cloud\Dlp\V2\FieldTransformation;
use Google\Cloud\Dlp\V2\KmsWrappedCryptoKey;
use Google\Cloud\Dlp\V2\PrimitiveTransformation;
use Google\Cloud\Dlp\V2\RecordTransformations;
use Google\Cloud\Dlp\V2\Table;
use Google\Cloud\Dlp\V2\Table\Row;
use Google\Cloud\Dlp\V2\Value;
use Google\Type\Date;
use DateTime;

/**
 * Deidentify dates in a CSV file by pseudorandomly shifting them.
 *
 * @param string $callingProject The GCP Project ID to run the API call under
 * @param string $inputCsvFile The path to the CSV file to deidentify
 * @param string $outputCsvFile The path to save the date-shifted CSV file to
 * @param array $dateFieldNames The list of (date) fields in the CSV file to date shift
 * @param string $lowerBoundDays The maximum number of days to shift a date backward
 * @param string $upperBoundDays The maximum number of days to shift a date forward
 * @param string contextFieldName (Optional) The column to determine date shift amount based on
 *        If this is not specified, a random shift amount will be used for every row.
 *        If this is specified, then 'wrappedKey' and 'keyName' must also be set
 * @param string keyName (Optional) The encrypted ('wrapped') AES-256 key to use when shifting dates
 *        If this is specified, then 'wrappedKey' and 'contextFieldName' must also be set
 * @param string wrappedKey (Optional) The name of the Cloud KMS key used to encrypt ('wrap') the AES-256 key
 *        If this is specified, then 'keyName' and 'contextFieldName' must also be set
 */
function deidentify_dates(
    $callingProjectId,
    $inputCsvFile,
    $outputCsvFile,
    $dateFieldNames,
    $lowerBoundDays,
    $upperBoundDays,
    $contextFieldName = '',
    $keyName = '',
    $wrappedKey = ''
) {
    // Instantiate a client.
    $dlp = new DlpServiceClient();

    // Read a CSV file
    $csvLines = file($inputCsvFile, FILE_IGNORE_NEW_LINES);
    $csvHeaders = explode(',', $csvLines[0]);
    $csvRows = array_slice($csvLines, 1);

    // Convert CSV file into protobuf objects
    $tableHeaders = array_map(function ($csvHeader) {
        return (new FieldId)->setName($csvHeader);
    }, $csvHeaders);

    $tableRows = array_map(function ($csvRow) {
        $rowValues = array_map(function ($csvValue) {
            if ($csvDate = DateTime::createFromFormat('m/d/Y', $csvValue)) {
                $date = (new Date())
                    ->setYear((int) $csvDate->format('Y'))
                    ->setMonth((int) $csvDate->format('m'))
                    ->setDay((int) $csvDate->format('d'));
                return (new Value())
                    ->setDateValue($date);
            } else {
                return (new Value())
                    ->setStringValue($csvValue);
            }
        }, explode(',', $csvRow));

        return (new Row())
            ->setValues($rowValues);
    }, $csvRows);

    // Convert date fields into protobuf objects
    $dateFields = array_map(function ($dateFieldName) {
        return (new FieldId())->setName($dateFieldName);
    }, $dateFieldNames);

    // Construct the table object
    $table = (new Table())
        ->setHeaders($tableHeaders)
        ->setRows($tableRows);

    $item = (new ContentItem())
        ->setTable($table);

    // Construct dateShiftConfig
    $dateShiftConfig = (new DateShiftConfig())
        ->setLowerBoundDays($lowerBoundDays)
        ->setUpperBoundDays($upperBoundDays);

    if ($contextFieldName && $keyName && $wrappedKey) {
        $contextField = (new FieldId())
            ->setName($contextFieldName);

        // Create the wrapped crypto key configuration object
        $kmsWrappedCryptoKey = (new KmsWrappedCryptoKey())
            ->setWrappedKey(base64_decode($wrappedKey))
            ->setCryptoKeyName($keyName);

        $cryptoKey = (new CryptoKey())
            ->setKmsWrapped($kmsWrappedCryptoKey);

        $dateShiftConfig
            ->setContext($contextField)
            ->setCryptoKey($cryptoKey);
    } elseif ($contextFieldName || $keyName || $wrappedKey) {
        throw new Exception('You must set either ALL or NONE of {$contextFieldName, $keyName, $wrappedKey}!');
    }

    // Create the information transform configuration objects
    $primitiveTransformation = (new PrimitiveTransformation())
        ->setDateShiftConfig($dateShiftConfig);

    $fieldTransformation = (new FieldTransformation())
        ->setPrimitiveTransformation($primitiveTransformation)
        ->setFields($dateFields);

    $recordTransformations = (new RecordTransformations())
        ->setFieldTransformations([$fieldTransformation]);

    // Create the deidentification configuration object
    $deidentifyConfig = (new DeidentifyConfig())
        ->setRecordTransformations($recordTransformations);

    $parent = $dlp->projectName($callingProjectId);

    // Run request
    $response = $dlp->deidentifyContent($parent, [
        'deidentifyConfig' => $deidentifyConfig,
        'item' => $item
    ]);

    // Check for errors
    foreach ($response->getOverview()->getTransformationSummaries() as $summary) {
        foreach ($summary->getResults() as $result) {
            if ($details = $result->getDetails()) {
                printf('Error: %s' . PHP_EOL, $details);
                return;
            }
        }
    }

    // Save the results to a file
    $csvRef = fopen($outputCsvFile, 'w');
    fputcsv($csvRef, $csvHeaders);
    foreach ($response->getItem()->getTable()->getRows() as $tableRow) {
        $values = array_map(function ($tableValue) {
            if ($tableValue->getStringValue()) {
                return $tableValue->getStringValue();
            }
            $protoDate = $tableValue->getDateValue();
            $date = mktime(0, 0, 0, $protoDate->getMonth(), $protoDate->getDay(), $protoDate->getYear());
            return strftime('%D', $date);
        }, iterator_to_array($tableRow->getValues()));
        fputcsv($csvRef, $values);
    };
    fclose($csvRef);
    printf('Deidentified dates written to %s' . PHP_EOL, $outputCsvFile);
}

C#

public static object DeidDateShift(
    string projectId,
    string inputCsvFile,
    string outputCsvFile,
    int lowerBoundDays,
    int upperBoundDays,
    string dateFields,
    string contextField = "",
    string keyName = "",
    string wrappedKey = "")
{
    var dlp = DlpServiceClient.Create();

    // Read file
    string[] csvLines = File.ReadAllLines(inputCsvFile);
    string[] csvHeaders = csvLines[0].Split(',');
    string[] csvRows = csvLines.Skip(1).ToArray();

    // Convert dates to protobuf format, and everything else to a string
    var protoHeaders = csvHeaders.Select(header => new FieldId { Name = header });
    var protoRows = csvRows.Select(CsvRow =>
    {
        var rowValues = CsvRow.Split(',');
        var protoValues = rowValues.Select(RowValue =>
        {
            System.DateTime parsedDate;
            if (System.DateTime.TryParse(RowValue, out parsedDate))
            {
                return new Value
                {
                    DateValue = new Google.Type.Date
                    {
                        Year = parsedDate.Year,
                        Month = parsedDate.Month,
                        Day = parsedDate.Day
                    }
                };
            }
            else
            {
                return new Value
                {
                    StringValue = RowValue
                };
            }
        });

        var rowObject = new Table.Types.Row();
        rowObject.Values.Add(protoValues);
        return rowObject;
    });

    var dateFieldList = dateFields
        .Split(',')
        .Select(field => new FieldId { Name = field });

    // Construct + execute the request
    var dateShiftConfig = new DateShiftConfig
    {
        LowerBoundDays = lowerBoundDays,
        UpperBoundDays = upperBoundDays
    };
    bool hasKeyName = !String.IsNullOrEmpty(keyName);
    bool hasWrappedKey = !String.IsNullOrEmpty(wrappedKey);
    bool hasContext = !String.IsNullOrEmpty(contextField);
    if (hasKeyName && hasWrappedKey && hasContext)
    {
        dateShiftConfig.Context = new FieldId { Name = contextField };
        dateShiftConfig.CryptoKey = new CryptoKey
        {
            KmsWrapped = new KmsWrappedCryptoKey
            {
                WrappedKey = ByteString.FromBase64(wrappedKey),
                CryptoKeyName = keyName
            }
        };
    }
    else if (hasKeyName || hasWrappedKey || hasContext)
    {
        throw new ArgumentException("Must specify ALL or NONE of: {contextFieldId, keyName, wrappedKey}!");
    }

    var deidConfig = new DeidentifyConfig
    {
        RecordTransformations = new RecordTransformations
        {
            FieldTransformations =
            {
                new FieldTransformation
                {
                    PrimitiveTransformation = new PrimitiveTransformation
                    {
                        DateShiftConfig = dateShiftConfig
                    },
                    Fields = { dateFieldList }
                }
            }
        }
    };

    DeidentifyContentResponse response = dlp.DeidentifyContent(
        new DeidentifyContentRequest
        {
            Parent = $"projects/{projectId}",
            DeidentifyConfig = deidConfig,
            Item = new ContentItem
            {
                Table = new Table
                {
                    Headers = { protoHeaders },
                    Rows = { protoRows }
                }
            }
        });

    // Save the results
    List<String> outputLines = new List<string>();
    outputLines.Add(csvLines[0]);

    outputLines.AddRange(response.Item.Table.Rows.Select(ProtoRow =>
    {
        var Values = ProtoRow.Values.Select(ProtoValue =>
        {
            if (ProtoValue.DateValue != null)
            {
                var ProtoDate = ProtoValue.DateValue;
                System.DateTime Date = new System.DateTime(
                    ProtoDate.Year, ProtoDate.Month, ProtoDate.Day);
                return Date.ToShortDateString();
            }
            else
            {
                return ProtoValue.StringValue;
            }
        });
        return String.Join(',', Values);
    }));

    File.WriteAllLines(outputCsvFile, outputLines);

    return 0;
}

cryptoReplaceFfxFpeConfig

CryptoReplaceFfxFpeConfig オブジェクトに cryptoReplaceFfxFpeConfig を設定すると、入力値がトークンで置換され、入力値の仮名化が行われます。トークンの特長は次のとおりです。

  • 暗号化された入力値です。
  • 入力値と同じ長さです。
  • cryptoKey で指定された暗号鍵の、FFX モードのフォーマット保持暗号化(FPE)を使用して計算されます。
  • alphabet で指定された文字から構成されます。

入力値:

  • 2 文字以上にするか、空の文字列にする必要があります。
  • alphabet で指定された文字で構成する必要があります。alphabet は 2~64 文字にする必要があります。

Cloud DLP では、暗号鍵を使用して置換トークンが計算されます。この鍵は、次の 3 つの方法のいずれかで指定します。

  1. 暗号化せずに API リクエストに埋め込む。
  2. Cloud DLP で生成されるようにリクエストする。
  3. 暗号化して API リクエストに埋め込む。このオプションでは、鍵は Cloud Key Management Service(Cloud KMS)の鍵によってラップ(暗号化)されます。

Cloud KMS でラップされた鍵を作成するには、16、24、32 バイトの plaintext フィールド値を含むリクエストを Cloud KMS の projects.locations.keyRings.cryptoKeys.encrypt メソッドに送信します。ラップされた鍵は、メソッドのレスポンスの ciphertext フィールドの値です。

この値は、デフォルトでは Base64 でエンコードされた文字列です。この値を Cloud DLP で設定するには、バイト文字列にデコードする必要があります。以下のコード スニペットは、この方法をいくつかの言語で示しています。これらのスニペットに続いて、エンドツーエンドの例が示されています。

Java

KmsWrappedCryptoKey.newBuilder()
    .setWrappedKey(ByteString.copyFrom(BaseEncoding.base64().decode(wrappedKey)))

Python

# The wrapped key is Base64-encoded, but the library expects a binary
# string, so decode it here.
import base64
wrapped_key = base64.b64decode(wrapped_key)

PHP

// Create the wrapped crypto key configuration object
$kmsWrappedCryptoKey = (new KmsWrappedCryptoKey())
    ->setWrappedKey(base64_decode($wrappedKey))
    ->setCryptoKeyName($keyName);

C#

WrappedKey = ByteString.FromBase64(wrappedKey)

Cloud KMS を使用したデータの暗号化と復号の詳細については、データの暗号化と復号をご覧ください。

以下に、Cloud DLP を使用して機密データの匿名化(トークンによる入力値の置換)を行うサンプルコードをいくつかの言語で示します。

Java

/**
 * Deidentify a string by encrypting sensitive information while preserving format.
 *
 * @param string The string to deidentify.
 * @param alphabet The set of characters to use when encrypting the input. For more information,
 *     see cloud.google.com/dlp/docs/reference/rest/v2/content/deidentify
 * @param keyName The name of the Cloud KMS key to use when decrypting the wrapped key.
 * @param wrappedKey The encrypted (or "wrapped") AES-256 encryption key.
 * @param projectId ID of Google Cloud project to run the API under.
 */
private static void deIdentifyWithFpe(
    String string,
    List<InfoType> infoTypes,
    FfxCommonNativeAlphabet alphabet,
    String keyName,
    String wrappedKey,
    String projectId,
    String surrogateType) {
  // instantiate a client
  try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) {
    ContentItem contentItem = ContentItem.newBuilder().setValue(string).build();

    // Create the format-preserving encryption (FPE) configuration
    KmsWrappedCryptoKey kmsWrappedCryptoKey =
        KmsWrappedCryptoKey.newBuilder()
            .setWrappedKey(ByteString.copyFrom(BaseEncoding.base64().decode(wrappedKey)))
            .setCryptoKeyName(keyName)
            .build();

    CryptoKey cryptoKey = CryptoKey.newBuilder().setKmsWrapped(kmsWrappedCryptoKey).build();

    CryptoReplaceFfxFpeConfig cryptoReplaceFfxFpeConfig =
        CryptoReplaceFfxFpeConfig.newBuilder()
            .setCryptoKey(cryptoKey)
            .setCommonAlphabet(alphabet)
            .setSurrogateInfoType(InfoType.newBuilder().setName(surrogateType).build())
            .build();

    // Create the deidentification transformation configuration
    PrimitiveTransformation primitiveTransformation =
        PrimitiveTransformation.newBuilder()
            .setCryptoReplaceFfxFpeConfig(cryptoReplaceFfxFpeConfig)
            .build();

    InfoTypeTransformation infoTypeTransformationObject =
        InfoTypeTransformation.newBuilder()
            .setPrimitiveTransformation(primitiveTransformation)
            .build();

    InfoTypeTransformations infoTypeTransformationArray =
        InfoTypeTransformations.newBuilder()
            .addTransformations(infoTypeTransformationObject)
            .build();

    InspectConfig inspectConfig =
        InspectConfig.newBuilder()
            .addAllInfoTypes(infoTypes)
            .build();

    // Create the deidentification request object
    DeidentifyConfig deidentifyConfig =
        DeidentifyConfig.newBuilder()
            .setInfoTypeTransformations(infoTypeTransformationArray)
            .build();

    DeidentifyContentRequest request =
        DeidentifyContentRequest.newBuilder()
            .setParent(ProjectName.of(projectId).toString())
            .setInspectConfig(inspectConfig)
            .setDeidentifyConfig(deidentifyConfig)
            .setItem(contentItem)
            .build();

    // Execute the deidentification request
    DeidentifyContentResponse response = dlpServiceClient.deidentifyContent(request);

    // Print the deidentified input value
    // e.g. "My SSN is 123456789" --> "My SSN is 7261298621"
    String result = response.getItem().getValue();
    System.out.println(result);
  } catch (Exception e) {
    System.out.println("Error in deidentifyWithFpe: " + e.getMessage());
  }
}

Node.js

// Imports the Google Cloud Data Loss Prevention library
const DLP = require('@google-cloud/dlp');

// Instantiates a client
const dlp = new DLP.DlpServiceClient();

// The project ID to run the API call under
// const callingProjectId = process.env.GCLOUD_PROJECT;

// The string to deidentify
// const string = 'My SSN is 372819127';

// The set of characters to replace sensitive ones with
// For more information, see https://cloud.google.com/dlp/docs/reference/rest/v2/organizations.deidentifyTemplates#ffxcommonnativealphabet
// const alphabet = 'ALPHA_NUMERIC';

// The name of the Cloud KMS key used to encrypt ('wrap') the AES-256 key
// const keyName = 'projects/YOUR_GCLOUD_PROJECT/locations/YOUR_LOCATION/keyRings/YOUR_KEYRING_NAME/cryptoKeys/YOUR_KEY_NAME';

// The encrypted ('wrapped') AES-256 key to use
// This key should be encrypted using the Cloud KMS key specified above
// const wrappedKey = 'YOUR_ENCRYPTED_AES_256_KEY'

// (Optional) The name of the surrogate custom info type to use
// Only necessary if you want to reverse the deidentification process
// Can be essentially any arbitrary string, as long as it doesn't appear
// in your dataset otherwise.
// const surrogateType = 'SOME_INFO_TYPE_DEID';

// Construct FPE config
const cryptoReplaceFfxFpeConfig = {
  cryptoKey: {
    kmsWrapped: {
      wrappedKey: wrappedKey,
      cryptoKeyName: keyName,
    },
  },
  commonAlphabet: alphabet,
};
if (surrogateType) {
  cryptoReplaceFfxFpeConfig.surrogateInfoType = {
    name: surrogateType,
  };
}

// Construct deidentification request
const item = {value: string};
const request = {
  parent: dlp.projectPath(callingProjectId),
  deidentifyConfig: {
    infoTypeTransformations: {
      transformations: [
        {
          primitiveTransformation: {
            cryptoReplaceFfxFpeConfig: cryptoReplaceFfxFpeConfig,
          },
        },
      ],
    },
  },
  item: item,
};

try {
  // Run deidentification request
  const [response] = await dlp.deidentifyContent(request);
  const deidentifiedItem = response.item;
  console.log(deidentifiedItem.value);
} catch (err) {
  console.log(`Error in deidentifyWithFpe: ${err.message || err}`);
}

Python

def deidentify_with_fpe(project, string, info_types, alphabet=None,
                        surrogate_type=None, key_name=None, wrapped_key=None):
    """Uses the Data Loss Prevention API to deidentify sensitive data in a
    string using Format Preserving Encryption (FPE).
    Args:
        project: The Google Cloud project id to use as a parent resource.
        item: The string to deidentify (will be treated as text).
        alphabet: The set of characters to replace sensitive ones with. For
            more information, see https://cloud.google.com/dlp/docs/reference/
            rest/v2beta2/organizations.deidentifyTemplates#ffxcommonnativealphabet
        surrogate_type: The name of the surrogate custom info type to use. Only
            necessary if you want to reverse the deidentification process. Can
            be essentially any arbitrary string, as long as it doesn't appear
            in your dataset otherwise.
        key_name: The name of the Cloud KMS key used to encrypt ('wrap') the
            AES-256 key. Example:
            key_name = 'projects/YOUR_GCLOUD_PROJECT/locations/YOUR_LOCATION/
            keyRings/YOUR_KEYRING_NAME/cryptoKeys/YOUR_KEY_NAME'
        wrapped_key: The encrypted ('wrapped') AES-256 key to use. This key
            should be encrypted using the Cloud KMS key specified by key_name.
    Returns:
        None; the response from the API is printed to the terminal.
    """
    # Import the client library
    import google.cloud.dlp

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

    # Convert the project id into a full resource id.
    parent = dlp.project_path(project)

    # The wrapped key is base64-encoded, but the library expects a binary
    # string, so decode it here.
    import base64
    wrapped_key = base64.b64decode(wrapped_key)

    # Construct FPE configuration dictionary
    crypto_replace_ffx_fpe_config = {
        'crypto_key': {
            'kms_wrapped': {
                'wrapped_key': wrapped_key,
                'crypto_key_name': key_name
            }
        },
        'common_alphabet': alphabet
    }

    # Add surrogate type
    if surrogate_type:
        crypto_replace_ffx_fpe_config['surrogate_info_type'] = {
            'name': surrogate_type
        }

    # Construct inspect configuration dictionary
    inspect_config = {
        'info_types': [{'name': info_type} for info_type in info_types]
    }

    # Construct deidentify configuration dictionary
    deidentify_config = {
        'info_type_transformations': {
            'transformations': [
                {
                    'primitive_transformation': {
                        'crypto_replace_ffx_fpe_config':
                            crypto_replace_ffx_fpe_config
                    }
                }
            ]
        }
    }

    # Convert string to item
    item = {'value': string}

    # Call the API
    response = dlp.deidentify_content(
        parent, inspect_config=inspect_config,
        deidentify_config=deidentify_config, item=item)

    # Print results
    print(response.item.value)

Go

// deidentifyFPE deidentifies the input with FPE (Format Preserving Encryption).
// keyFileName is the file name with the KMS wrapped key and cryptoKeyName is the
// full KMS key resource name used to wrap the key. surrogateInfoType is an
// optional identifier needed for reidentification. surrogateInfoType can be any
// value not found in your input.
func deidentifyFPE(w io.Writer, client *dlp.Client, project, input string, infoTypes []string, keyFileName, cryptoKeyName, surrogateInfoType string) {
	// Convert the info type strings to a list of InfoTypes.
	var i []*dlppb.InfoType
	for _, it := range infoTypes {
		i = append(i, &dlppb.InfoType{Name: it})
	}
	// Read the key file.
	keyBytes, err := ioutil.ReadFile(keyFileName)
	if err != nil {
		log.Fatalf("error reading file: %v", err)
	}
	// Create a configured request.
	req := &dlppb.DeidentifyContentRequest{
		Parent: "projects/" + project,
		InspectConfig: &dlppb.InspectConfig{
			InfoTypes: i,
		},
		DeidentifyConfig: &dlppb.DeidentifyConfig{
			Transformation: &dlppb.DeidentifyConfig_InfoTypeTransformations{
				InfoTypeTransformations: &dlppb.InfoTypeTransformations{
					Transformations: []*dlppb.InfoTypeTransformations_InfoTypeTransformation{
						{
							InfoTypes: []*dlppb.InfoType{}, // Match all info types.
							PrimitiveTransformation: &dlppb.PrimitiveTransformation{
								Transformation: &dlppb.PrimitiveTransformation_CryptoReplaceFfxFpeConfig{
									CryptoReplaceFfxFpeConfig: &dlppb.CryptoReplaceFfxFpeConfig{
										CryptoKey: &dlppb.CryptoKey{
											Source: &dlppb.CryptoKey_KmsWrapped{
												KmsWrapped: &dlppb.KmsWrappedCryptoKey{
													WrappedKey:    keyBytes,
													CryptoKeyName: cryptoKeyName,
												},
											},
										},
										// Set the alphabet used for the output.
										Alphabet: &dlppb.CryptoReplaceFfxFpeConfig_CommonAlphabet{
											CommonAlphabet: dlppb.CryptoReplaceFfxFpeConfig_ALPHA_NUMERIC,
										},
										// Set the surrogate info type, used for reidentification.
										SurrogateInfoType: &dlppb.InfoType{
											Name: surrogateInfoType,
										},
									},
								},
							},
						},
					},
				},
			},
		},
		// The item to analyze.
		Item: &dlppb.ContentItem{
			DataItem: &dlppb.ContentItem_Value{
				Value: input,
			},
		},
	}
	// Send the request.
	r, err := client.DeidentifyContent(context.Background(), req)
	if err != nil {
		log.Fatal(err)
	}
	// Print the result.
	fmt.Fprint(w, r.GetItem().GetValue())
}

PHP

use Google\Cloud\Dlp\V2\CryptoReplaceFfxFpeConfig;
use Google\Cloud\Dlp\V2\CryptoReplaceFfxFpeConfig\FfxCommonNativeAlphabet;
use Google\Cloud\Dlp\V2\CryptoKey;
use Google\Cloud\Dlp\V2\DlpServiceClient;
use Google\Cloud\Dlp\V2\PrimitiveTransformation;
use Google\Cloud\Dlp\V2\KmsWrappedCryptoKey;
use Google\Cloud\Dlp\V2\InfoType;
use Google\Cloud\Dlp\V2\DeidentifyConfig;
use Google\Cloud\Dlp\V2\InfoTypeTransformations\InfoTypeTransformation;
use Google\Cloud\Dlp\V2\InfoTypeTransformations;
use Google\Cloud\Dlp\V2\ContentItem;

/**
 * Deidentify a string using Format-Preserving Encryption (FPE).
 *
 * @param string $callingProjectId The GCP Project ID to run the API call under
 * @param string $string The string to deidentify
 * @param string $keyName The name of the Cloud KMS key used to encrypt ('wrap') the AES-256 key
 * @param wrappedKey $wrappedKey The AES-256 key to use, encrypted ('wrapped') with the KMS key
 *        defined by $keyName.
 * @param string $surrogateTypeName Optional surrogate custom info type to enable
 *        reidentification. Can be essentially any arbitrary string that doesn't
 *        appear in your dataset'
 */
function deidentify_fpe(
    $callingProjectId,
    $string,
    $keyName,
    $wrappedKey,
    $surrogateTypeName = ''
) {
    // Instantiate a client.
    $dlp = new DlpServiceClient();

    // The infoTypes of information to mask
    $ssnInfoType = (new InfoType())
        ->setName('US_SOCIAL_SECURITY_NUMBER');
    $infoTypes = [$ssnInfoType];

    // Create the wrapped crypto key configuration object
    $kmsWrappedCryptoKey = (new KmsWrappedCryptoKey())
        ->setWrappedKey(base64_decode($wrappedKey))
        ->setCryptoKeyName($keyName);

    // The set of characters to replace sensitive ones with
    // For more information, see https://cloud.google.com/dlp/docs/reference/rest/V2/organizations.deidentifyTemplates#ffxcommonnativealphabet
    $commonAlphabet = FfxCommonNativeAlphabet::NUMERIC;

    // Create the crypto key configuration object
    $cryptoKey = (new CryptoKey())
        ->setKmsWrapped($kmsWrappedCryptoKey);

    // Create the crypto FFX FPE configuration object
    $cryptoReplaceFfxFpeConfig = (new CryptoReplaceFfxFpeConfig())
        ->setCryptoKey($cryptoKey)
        ->setCommonAlphabet($commonAlphabet);
    if ($surrogateTypeName) {
        $surrogateType = (new InfoType())
            ->setName($surrogateTypeName);
        $cryptoReplaceFfxFpeConfig->setSurrogateInfoType($surrogateType);
    }

    // Create the information transform configuration objects
    $primitiveTransformation = (new PrimitiveTransformation())
        ->setCryptoReplaceFfxFpeConfig($cryptoReplaceFfxFpeConfig);

    $infoTypeTransformation = (new InfoTypeTransformation())
        ->setPrimitiveTransformation($primitiveTransformation)
        ->setInfoTypes($infoTypes);

    $infoTypeTransformations = (new InfoTypeTransformations())
        ->setTransformations([$infoTypeTransformation]);

    // Create the deidentification configuration object
    $deidentifyConfig = (new DeidentifyConfig())
        ->setInfoTypeTransformations($infoTypeTransformations);

    $content = (new ContentItem())
        ->setValue($string);

    $parent = $dlp->projectName($callingProjectId);

    // Run request
    $response = $dlp->deidentifyContent($parent, [
        'deidentifyConfig' => $deidentifyConfig,
        'item' => $content
    ]);

    // Print the results
    $deidentifiedValue = $response->getItem()->getValue();
    print($deidentifiedValue);
}

C#

public static object DeidFpe(
    string projectId,
    string dataValue,
    IEnumerable<InfoType> infoTypes,
    string keyName,
    string wrappedKey,
    string alphabet)
{
    var deidentifyConfig = new DeidentifyConfig
    {
        InfoTypeTransformations = new InfoTypeTransformations
        {
            Transformations =
            {
                new InfoTypeTransformations.Types.InfoTypeTransformation
                {
                    PrimitiveTransformation = new PrimitiveTransformation
                    {
                        CryptoReplaceFfxFpeConfig = new CryptoReplaceFfxFpeConfig
                        {
                            CommonAlphabet = (FfxCommonNativeAlphabet) Enum.Parse(typeof(FfxCommonNativeAlphabet), alphabet),
                            CryptoKey = new CryptoKey
                            {
                                KmsWrapped = new KmsWrappedCryptoKey
                                {
                                    CryptoKeyName = keyName,
                                    WrappedKey = ByteString.FromBase64(wrappedKey)
                                }
                            },
                            SurrogateInfoType = new InfoType
                            {
                                Name = "TOKEN"
                            }
                        }
                    }
                }
            }
        }
    };

    DlpServiceClient dlp = DlpServiceClient.Create();
    var response = dlp.DeidentifyContent(
        new DeidentifyContentRequest
        {
            ParentAsProjectName = new ProjectName(projectId),
            InspectConfig = new InspectConfig
            {
                InfoTypes = { infoTypes }
            },
            DeidentifyConfig = deidentifyConfig,
            Item = new ContentItem { Value = dataValue }
        });

    Console.WriteLine($"Deidentified content: {response.Item.Value}");
    return 0;
}

fixedSizeBucketingConfig

バケット変換(この変換と bucketingConfig)では、数値データを範囲にバケット化し、データをマスキングします。結果の数値範囲は、下限、ハイフン、上限から構成されるハイフン付きの文字列になります。

FixedSizeBucketingConfig オブジェクトに fixedSizeBucketingConfig を設定すると、固定サイズの範囲に基づいて入力値がバケット化されます。FixedSizeBucketingConfig オブジェクトは次のものから構成されます。

  • lowerBound: すべてのバケットの下限値。これより小さい値は 1 つのバケットにグループ化されます。
  • upperBound: すべてのバケットの上限値。これより大きい値は 1 つのバケットにグループ化されます。
  • bucketSize: 最小バケットと最大バケット以外の、各バケットのサイズ。

たとえば、lowerBound を 10、upperBound を 89、bucketSize を 10 に設定すると、次のバケットが使用されます。-10、10-20、20-30、30-40、40-50、50-60、60-70、70-80、,80-89、89+。

バケット化の概念の詳細については、一般化とバケット化をご覧ください。

bucketingConfig

bucketingConfig 変換は、もう 1 つのバケット変換 fixedSizeBucketingConfig よりも柔軟性があります。上限値、下限値、均等サイズのバケットを作成する間隔値を指定せずに、作成するバケットの最大値と最小値を指定します。最大値と最小値のペアは同じ型でなければなりません。

BucketingConfig オブジェクトに bucketingConfig を設定すると、カスタム バケットが指定されます。BucketingConfig オブジェクトは、buckets[] オブジェクトの Bucket 配列から構成されます。各 Bucket オブジェクトは次のものから構成されます。

  • min: バケットの範囲の下限。下限のないバケットを作成する場合、この値は省略します。
  • max: バケットの範囲の上限。上限のないバケットを作成する場合、この値は省略します。
  • replacementValue: 元の値が下限と上限の範囲内の場合に置換する値。replacementValue を指定しない場合、代わりにハイフン付きの min-max 範囲が使用されます。

定義された範囲外の値の場合は、戻り値の TransformationSummary にエラー メッセージが含まれます。

たとえば、次の設定の bucketingConfig 変換について考えてみましょう。

"bucketingConfig":{
  "buckets":[
    {
      "min":{
        "integerValue":"1"
      },
      "max":{
        "integerValue":"30"
      },
      "replacementValue":{
        "stringValue":"LOW"
      }
    },
    {
      "min":{
        "integerValue":"31"
      },
      "max":{
        "integerValue":"65"
      },
      "replacementValue":{
        "stringValue":"MEDIUM"
      }
    },
    {
      "min":{
        "integerValue":"66"
      },
      "max":{
        "integerValue":"100"
      },
      "replacementValue":{
        "stringValue":"HIGH"
      }
    }
  ]
}

これにより、次のような動作が定義されます。

  • 1〜30 の整数値は、LOW で置換することでマスキングされます。
  • 31〜65 の整数値は、MEDIUM で置換することでマスキングされます。
  • 66~100 の整数値は、HIGH で置換することでマスキングされます。

バケット化の概念の詳細については、一般化とバケット化をご覧ください。

replaceWithInfoTypeConfig

replaceWithInfoTypeConfig を指定すると、一致した値が infoType 名に置換されます。replaceWithInfoTypeConfig メッセージに引数はありません。指定すると、変換が有効になります。

たとえば、すべての EMAIL_ADDRESS infoType に replaceWithInfoTypeConfig を指定し、次の文字列を Cloud DLP に送信したとします。

My name is Alicia Abernathy, and my email address is aabernathy@example.com.

次の文字列が返されます。

My name is Alicia Abernathy, and my email address is EMAIL_ADDRESS.
timePartConfig

TimePartConfig オブジェクトに timePartConfig を設定すると、一致した値のうち DateTimestampTimeOfDay の値を含む部分が保持されます。TimePartConfig オブジェクトは partToExtract 引数で構成され、TimePart で列挙された値(年、月、日にちなど)に設定できます。

たとえば、partToExtractYEAR に設定して timePartConfig 変換を構成したとします。以下の最初の列のデータを Cloud DLP に送信すると、2 番目の列の値に変換されます。

元の値 変換後の値
9/21/1976 1976
6/7/1945 1945
1/20/2009 2009
7/4/1776 1776
8/1/1984 1984
4/21/1982 1982

レコード変換

レコード変換(RecordTransformations オブジェクト)は、特定の infoType と識別された表形式データ内の値にのみ適用されます。RecordTransformations には、さらに 2 つのサブカテゴリがあります。

  • fieldTransformations[]: さまざまなフィールド変換を適用する変換。
  • recordSuppressions[]: 完全に抑止されるレコードを定義するルール。recordSuppressions[] 内で抑止ルールに一致するレコードは、出力から除外されます。

フィールド変換

FieldTransformation オブジェクトには次の 3 つの引数があります。

  • fields: 変換が適用される 1 つ以上の入力フィールド(FieldID オブジェクト)。
  • condition: 変換の適用で true と評価される条件(RecordCondition オブジェクト)。たとえば、あるレコードの郵便番号列が特定の範囲にある場合に限り、同じレコードの年齢列にバケット変換を適用します。または、誕生日フィールドの年齢が 85 歳以上の場合に限り、フィールドを削除します。
  • 以下のいずれかの変換型引数。次のいずれか 1 つを指定する必要があります。

レコードの抑止

フィールド データに変換を適用するだけでなく、特定の抑止条件が true と評価されたときにレコードを抑止し、データを匿名化するように Cloud DLP に指示することもできます。同じリクエストでフィールド変換とレコード抑止の両方を適用できます。

RecordTransformations オブジェクトの recordSuppressions メッセージを、1 つ以上の RecordSuppression オブジェクトの配列に設定します。

RecordSuppression オブジェクトには RecordCondition オブジェクトが 1 つ含まれ、このオブジェクトには同様に Expressions オブジェクトが 1 つ含まれます。

Expressions オブジェクトには次のものが含まれます。

  • logicalOperator: LogicalOperator 列挙型の 1 つ。
  • conditions: 1 つ以上の Condition オブジェクトの配列を含む Conditions オブジェクト。Condition は、フィールド値と他の値の比較です(値の型はどちらも stringbooleanintegerdoubleTimestamp または TimeofDay)。

比較条件が true と評価されると、レコードが抑止されます。その逆も同じです。比較値の型が異なる場合、警告が表示され、条件が false と評価されます。

再識別

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Data Loss Prevention のドキュメント