標準のカスタム辞書検出器の作成

カスタム辞書は、語句のリストを照合するシンプルで強力な機能を提供します。これは、独自の検出器として機能し、組み込みの検出器の例外リストの作成にも使用できます。さらに、カスタム辞書を使用して組み込みの infoType 検出器を拡張することで、結果に対して追加の照合を実施できます。

辞書のカスタム infoType 検出器の詳細

辞書のカスタム infoType 検出器を作成するには、API の概要で説明されているように以下を指定して CustomInfoType オブジェクトを定義します。

  • カスタム infoType 検出器に付ける名前。InfoType オブジェクト内に指定します。
  • オプションの Likelihood 値。指定しない場合、辞書項目と一致したものについて、デフォルトの可能性の値 POSSIBLE が返されます。
  • オプションの DetectionRule オブジェクト、またはホットワード ルール。こうしたルールを適用すると、指定したホットワードの所定の近接範囲内にある結果の可能性を調整できます。ホットワード ルールの詳細については、一致の可能性のカスタマイズをご覧ください。
  • スキャンする単語のリストを含む WordList、またはスキャンする改行区切りのリストを含む単一のテキスト ファイルへの CloudStoragePath としての Dictionary

辞書のカスタム infoType 検出器は JSON オブジェクトとしてすべての任意指定コンポーネントを含み、次のようになります(この JSON には、Cloud Storage に保存されている辞書テキスト ファイルへのパスが含まれています。インラインの単語リストを表示するには、このトピックの後半のをご覧ください)。

{
  "customInfoTypes":[
    {
      "infoType":{
        "name":"[CUSTOM_INFOTYPE_NAME]"
      },
      "likelihood":"[LIKELIHOOD_VALUE]",
      "detectionRules":[
        {
          "hotwordRule":{
            [HOTWORDRULE_OBJECT]
          }
        },
        ...
      ],
      "dictionary":
      {
        "cloudStoragePath":
        {
          "path": "gs://[PATH_TO_TXT_FILE]"
        }
      }
    }
  ],
  ...
}

格納されるカスタム辞書

Cloud DLP では、ストレージ リポジトリを検査するための、格納されるカスタム辞書もサポートされます。格納されるカスタム辞書を使用すると、Cloud DLP では、たとえば、数億個ものユーザー名やメールアドレス、辞書での照合についてに定義されているその他の文字列をスキャンできます。さらに Cloud DLP には、格納されるカスタム辞書を必要に応じてプログラムで再構築するための機能も組み込まれています。

格納されるカスタム辞書は、ユーザーの組織が所有する Cloud Storage バケットまたは BigQuery テーブルに格納されているフレーズ コレクションから作成されます。格納されるカスタム辞書を初めて作成するときに、Cloud Storage または BigQuery に検索対象のフレーズを入力してから、Cloud DLP を使用して格納されるカスタム辞書を生成します。このカスタム辞書は Cloud Storage に保存されます。単語を保存する Cloud Storage バケットまたは BigQuery テーブルに対して単語を追加または削除する場合は、Cloud DLP を使用して格納されるカスタム辞書を再構築します。

格納されるカスタム辞書の作成方法については、格納されるカスタム辞書検出器の作成をご覧ください。

辞書での照合について

以下は、Cloud DLP でどのように辞書の単語やフレーズが照合されるかについて説明したガイダンスです。ここに示す内容は、標準カスタム辞書と格納されるカスタム辞書の両方に適用されます。

  • 辞書の単語では大文字と小文字が区別されません。辞書に Abby が含まれている場合、abbyABBYAbby などと一致します。
  • スキャン対象の辞書やコンテンツ内のすべての文字(Unicode 基本多言語面に含まれる英字と数字以外)は、照合のためのスキャン時に空白と見なされます。辞書で Abby Abernathy をスキャンすると、abby abernathyAbby, AbernathyAbby (ABERNATHY) などと一致します。
  • 一致する文字の前後の文字は、その単語内の隣接する文字とは異なるタイプ(文字または数字)でなければなりません。辞書で Abi をスキャンすると、Abi904 の最初の 3 文字と一致しますが、Abigail の最初の 3 文字とは一致しません。
  • 辞書の単語に英字や数字ではない文字が大量に含まれる場合、それらの文字は空白として扱われるため、予期しない結果になることがあります。

単純な単語リスト

通院患者の治療に使用された病室の情報を含むデータがあるとします。こうした場所は特定のデータセットで機密扱いになる可能性がありますが、Cloud DLP の組み込みの検出器では検出されません。

病室のリストは次のようなものでした。

  • "RM-ORANGE"
  • "RM-YELLOW"
  • "RM-GREEN"

プロトコル

次の JSON の例では、カスタムの病室番号を匿名化するためのカスタム辞書を定義しています。

JSON 入力:

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

{
  "item":{
    "value":"Patient was seen in RM-YELLOW then transferred to rm green."
  },
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "primitiveTransformation":{
            "replaceWithInfoTypeConfig":{

            }
          }
        }
      ]
    }
  },
  "inspectConfig":{
    "customInfoTypes":[
      {
        "infoType":{
          "name":"CUSTOM_ROOM_ID"
        },
        "dictionary":{
          "wordList":{
            "words":[
              "RM-GREEN",
              "RM-YELLOW",
              "RM-ORANGE"
            ]
          }
        }
      }
    ]
  }
}

JSON 出力:

POST でこの JSON を content:deidentify に送信すると、次の JSON レスポンスが返されます。

{
  "item":{
    "value":"Patient was seen in [CUSTOM_ROOM_ID] then transferred to [CUSTOM_ROOM_ID]."
  },
  "overview":{
    "transformedBytes":"17",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"CUSTOM_ROOM_ID"
        },
        "transformation":{
          "replaceWithInfoTypeConfig":{

          }
        },
        "results":[
          {
            "count":"2",
            "code":"SUCCESS"
          }
        ],
        "transformedBytes":"17"
      }
    ]
  }
}

カスタム辞書の WordList メッセージで指定された病室番号が Cloud DLP によって正しく識別されました。2 番目の例「rm green」のように、大文字とハイフン(-)が見つからない場合でも項目が一致することに注意してください。

Java

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


import com.google.cloud.dlp.v2.DlpServiceClient;
import com.google.privacy.dlp.v2.ContentItem;
import com.google.privacy.dlp.v2.CustomInfoType;
import com.google.privacy.dlp.v2.CustomInfoType.Dictionary;
import com.google.privacy.dlp.v2.CustomInfoType.Dictionary.WordList;
import com.google.privacy.dlp.v2.DeidentifyConfig;
import com.google.privacy.dlp.v2.DeidentifyContentRequest;
import com.google.privacy.dlp.v2.DeidentifyContentResponse;
import com.google.privacy.dlp.v2.InfoType;
import com.google.privacy.dlp.v2.InfoTypeTransformations;
import com.google.privacy.dlp.v2.InfoTypeTransformations.InfoTypeTransformation;
import com.google.privacy.dlp.v2.InspectConfig;
import com.google.privacy.dlp.v2.LocationName;
import com.google.privacy.dlp.v2.PrimitiveTransformation;
import com.google.privacy.dlp.v2.ReplaceWithInfoTypeConfig;
import java.io.IOException;

public class DeIdentifyWithSimpleWordList {

  public static void main(String[] args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String textToDeIdentify = "Patient was seen in RM-YELLOW then transferred to rm green.";
    deidentifyWithSimpleWordList(projectId, textToDeIdentify);
  }

  public static void deidentifyWithSimpleWordList(String projectId, String textToDeIdentify)
      throws 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 dlp = DlpServiceClient.create()) {

      // Specify what content you want the service to DeIdentify.
      ContentItem contentItem = ContentItem.newBuilder().setValue(textToDeIdentify).build();

      // Construct the word list to be detected
      Dictionary wordList =
          Dictionary.newBuilder()
              .setWordList(
                  WordList.newBuilder()
                      .addWords("RM-GREEN")
                      .addWords("RM-YELLOW")
                      .addWords("RM-ORANGE")
                      .build())
              .build();

      // Specify the word list custom info type the inspection will look for.
      InfoType infoType = InfoType.newBuilder().setName("CUSTOM_ROOM_ID").build();
      CustomInfoType customInfoType =
          CustomInfoType.newBuilder().setInfoType(infoType).setDictionary(wordList).build();
      InspectConfig inspectConfig =
          InspectConfig.newBuilder().addCustomInfoTypes(customInfoType).build();

      // Define type of deidentification as replacement.
      PrimitiveTransformation primitiveTransformation =
          PrimitiveTransformation.newBuilder()
              .setReplaceWithInfoTypeConfig(ReplaceWithInfoTypeConfig.getDefaultInstance())
              .build();

      // Associate deidentification type with info type.
      InfoTypeTransformation transformation =
          InfoTypeTransformation.newBuilder()
              .addInfoTypes(infoType)
              .setPrimitiveTransformation(primitiveTransformation)
              .build();

      // Construct the configuration for the Redact request and list all desired transformations.
      DeidentifyConfig deidentifyConfig =
          DeidentifyConfig.newBuilder()
              .setInfoTypeTransformations(
                  InfoTypeTransformations.newBuilder().addTransformations(transformation))
              .build();

      // Combine configurations into a request for the service.
      DeidentifyContentRequest request =
          DeidentifyContentRequest.newBuilder()
              .setParent(LocationName.of(projectId, "global").toString())
              .setItem(contentItem)
              .setInspectConfig(inspectConfig)
              .setDeidentifyConfig(deidentifyConfig)
              .build();

      // Send the request and receive response from the service
      DeidentifyContentResponse response = dlp.deidentifyContent(request);

      // Print the results
      System.out.println(
          "Text after replace with infotype config: " + response.getItem().getValue());
    }
  }
}

C#

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


using System;
using Google.Api.Gax.ResourceNames;
using Google.Cloud.Dlp.V2;

public class DeidentifyWithSimpleWordList
{
    public static DeidentifyContentResponse Deidentify(string projectId, string text)
    {
        // Instantiate a client.
        var dlp = DlpServiceClient.Create();

        var contentItem = new ContentItem { Value = text };

        var wordList = new CustomInfoType.Types.Dictionary.Types.WordList
        {
            Words = { new string[] { "RM-GREEN", "RM-YELLOW", "RM-ORANGE" } }
        };

        var infoType = new InfoType
        {
            Name = "CUSTOM_ROOM_ID"
        };

        var customInfoType = new CustomInfoType
        {
            InfoType = infoType,
            Dictionary = new CustomInfoType.Types.Dictionary
            {
                WordList = wordList
            }
        };

        var inspectConfig = new InspectConfig
        {
            CustomInfoTypes =
            {
                customInfoType,
            }
        };
        var primitiveTransformation = new PrimitiveTransformation
        {
            ReplaceWithInfoTypeConfig = new ReplaceWithInfoTypeConfig { }
        };

        var transformation = new InfoTypeTransformations.Types.InfoTypeTransformation
        {
            InfoTypes = { infoType },
            PrimitiveTransformation = primitiveTransformation
        };

        var deidentifyConfig = new DeidentifyConfig
        {
            InfoTypeTransformations = new InfoTypeTransformations
            {
                Transformations = { transformation }
            }
        };

        var request = new DeidentifyContentRequest
        {
            Parent = new LocationName(projectId, "global").ToString(),
            InspectConfig = inspectConfig,
            DeidentifyConfig = deidentifyConfig,
            Item = contentItem
        };

        // Call the API.
        var response = dlp.DeidentifyContent(request);

        // Inspect the results.
        Console.WriteLine($"Deidentified content: {response.Item.Value}");
        return response;
    }
}

例外リスト

メールアドレスなどの顧客識別子を含むログデータがあり、この情報を編集するとします。ただし、これらのログには内部開発者のメールアドレスも含まれており、これらを編集する必要はありません。

プロトコル

次の JSON の例では、WordList メッセージ内のメールアドレスのサブセット(jack@example.org と jill@example.org)をリストするカスタム辞書を作成し、カスタム infoType 名 DEVELOPER_EMAIL を割り当てています。この JSON は Cloud DLP に対し、指定されたメールアドレスを無視して、検出した他のメールアドレスをその infoType(この場合は EMAIL_ADDRESS)に対応する文字列に置き換えるよう指示します。

JSON 入力:

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

{
  "item":{
    "value":"jack@example.org accessed customer record of user5@example.com"
  },
  "deidentifyConfig":{
    "infoTypeTransformations":{
      "transformations":[
        {
          "primitiveTransformation":{
            "replaceWithInfoTypeConfig":{

            }
          },
          "infoTypes":[
            {
              "name":"EMAIL_ADDRESS"
            }
          ]
        }
      ]
    }
  },
  "inspectConfig":{
    "customInfoTypes":[
      {
        "infoType":{
          "name":"DEVELOPER_EMAIL"
        },
        "dictionary":{
          "wordList":{
            "words":[
              "jack@example.org",
              "jill@example.org"
            ]
          }
        }
      }
    ],
    "infoTypes":[
      {
        "name":"EMAIL_ADDRESS"
      }
    ]
    "ruleSet": [
      {
        "infoTypes": [
          {
            "name": "EMAIL_ADDRESS"
          }
        ],
        "rules": [
          {
            "exclusionRule": {
              "excludeInfoTypes": {
                "infoTypes": [
                  {
                    "name": "DEVELOPER_EMAIL"
                  }
                ]
              },
              "matchingType": "MATCHING_TYPE_FULL_MATCH"
            }
          }
        ]
      }
    ]
  }
}

JSON 出力:

POST でこの JSON を content:deidentify に送信すると、次の JSON レスポンスが返されます。

{
  "item":{
    "value":"jack@example.org accessed customer record of [EMAIL_ADDRESS]"
  },
  "overview":{
    "transformedBytes":"17",
    "transformationSummaries":[
      {
        "infoType":{
          "name":"EMAIL_ADDRESS"
        },
        "transformation":{
          "replaceWithInfoTypeConfig":{

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

この出力では、user1@example.com が EMAIL_ADDRESS infoType 検出器に一致するものとして、jack@example.org は DEVELOPER_EMAIL カスタム infoType 検出器に一致するものとして、それぞれ正しく識別されています。EMAIL_ADDRESS だけを変換することにしたため、jack@example.org は変更されていません。

Java

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


import com.google.cloud.dlp.v2.DlpServiceClient;
import com.google.privacy.dlp.v2.ContentItem;
import com.google.privacy.dlp.v2.CustomInfoType;
import com.google.privacy.dlp.v2.CustomInfoType.Dictionary;
import com.google.privacy.dlp.v2.CustomInfoType.Dictionary.WordList;
import com.google.privacy.dlp.v2.DeidentifyConfig;
import com.google.privacy.dlp.v2.DeidentifyContentRequest;
import com.google.privacy.dlp.v2.DeidentifyContentResponse;
import com.google.privacy.dlp.v2.InfoType;
import com.google.privacy.dlp.v2.InfoTypeTransformations;
import com.google.privacy.dlp.v2.InfoTypeTransformations.InfoTypeTransformation;
import com.google.privacy.dlp.v2.InspectConfig;
import com.google.privacy.dlp.v2.LocationName;
import com.google.privacy.dlp.v2.PrimitiveTransformation;
import com.google.privacy.dlp.v2.ReplaceWithInfoTypeConfig;
import java.io.IOException;

public class DeIdentifyWithExceptionList {

  public static void main(String[] args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String textToDeIdentify = "jack@example.org accessed customer record of user5@example.com";
    deIdentifyWithExceptionList(projectId, textToDeIdentify);
  }

  public static void deIdentifyWithExceptionList(String projectId, String textToDeIdentify)
      throws 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 dlp = DlpServiceClient.create()) {

      // Specify what content you want the service to DeIdentify.
      ContentItem contentItem = ContentItem.newBuilder().setValue(textToDeIdentify).build();

      // Construct the custom word list to be detected.
      Dictionary wordList =
          Dictionary.newBuilder()
              .setWordList(
                  WordList.newBuilder()
                      .addWords("jack@example.org")
                      .addWords("jill@example.org")
                      .build())
              .build();

      // Construct the custom dictionary detector associated with the word list.
      InfoType developerEmail = InfoType.newBuilder().setName("DEVELOPER_EMAIL").build();
      CustomInfoType customInfoType =
          CustomInfoType.newBuilder().setInfoType(developerEmail).setDictionary(wordList).build();

      // Specify the word list custom info type and build-in info type the inspection will look for.
      InfoType emailAddress = InfoType.newBuilder().setName("EMAIL_ADDRESS").build();
      InspectConfig inspectConfig =
          InspectConfig.newBuilder()
              .addInfoTypes(emailAddress)
              .addCustomInfoTypes(customInfoType)
              .build();

      // Define type of deidentification as replacement.
      PrimitiveTransformation primitiveTransformation =
          PrimitiveTransformation.newBuilder()
              .setReplaceWithInfoTypeConfig(ReplaceWithInfoTypeConfig.getDefaultInstance())
              .build();

      // Associate de-identification type with info type.
      InfoTypeTransformation transformation =
          InfoTypeTransformation.newBuilder()
              .addInfoTypes(emailAddress)
              .setPrimitiveTransformation(primitiveTransformation)
              .build();

      // Construct the configuration for the de-id request and list all desired transformations.
      DeidentifyConfig deidentifyConfig =
          DeidentifyConfig.newBuilder()
              .setInfoTypeTransformations(
                  InfoTypeTransformations.newBuilder().addTransformations(transformation))
              .build();

      // Combine configurations into a request for the service.
      DeidentifyContentRequest request =
          DeidentifyContentRequest.newBuilder()
              .setParent(LocationName.of(projectId, "global").toString())
              .setItem(contentItem)
              .setInspectConfig(inspectConfig)
              .setDeidentifyConfig(deidentifyConfig)
              .build();

      // Send the request and receive response from the service
      DeidentifyContentResponse response = dlp.deidentifyContent(request);

      // Print the results
      System.out.println(
          "Text after replace with infotype config: " + response.getItem().getValue());
    }
  }
}

C#

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


using System;
using Google.Api.Gax.ResourceNames;
using Google.Cloud.Dlp.V2;

public class DeidentifyWithExceptionList
{
    public static DeidentifyContentResponse Deidentify(string projectId, string text)
    {
        // Instantiate a client.
        var dlp = DlpServiceClient.Create();

        var contentItem = new ContentItem { Value = text };

        var wordList = new CustomInfoType.Types.Dictionary.Types.WordList
        {
            Words = { new string[] { "jack@example.org", "jill@example.org" } }
        };

        var exclusionRule = new ExclusionRule
        {
            MatchingType = MatchingType.FullMatch,
            Dictionary = new CustomInfoType.Types.Dictionary
            {
                WordList = wordList
            }
        };

        var infoType = new InfoType { Name = "EMAIL_ADDRESS" };

        var inspectionRuleSet = new InspectionRuleSet
        {
            InfoTypes = { infoType },
            Rules = { new InspectionRule { ExclusionRule = exclusionRule } }
        };

        var inspectConfig = new InspectConfig
        {
            InfoTypes = { infoType },
            RuleSet = { inspectionRuleSet }
        };
        var primitiveTransformation = new PrimitiveTransformation
        {
            ReplaceWithInfoTypeConfig = new ReplaceWithInfoTypeConfig { }
        };

        var transformation = new InfoTypeTransformations.Types.InfoTypeTransformation
        {
            InfoTypes = { infoType },
            PrimitiveTransformation = primitiveTransformation
        };

        var deidentifyConfig = new DeidentifyConfig
        {
            InfoTypeTransformations = new InfoTypeTransformations
            {
                Transformations = { transformation }
            }
        };

        var request = new DeidentifyContentRequest
        {
            Parent = new LocationName(projectId, "global").ToString(),
            InspectConfig = inspectConfig,
            DeidentifyConfig = deidentifyConfig,
            Item = contentItem
        };

        // Call the API.
        var response = dlp.DeidentifyContent(request);

        // Inspect the results.
        Console.WriteLine($"Deidentified content: {response.Item.Value}");
        return response;
    }
}

組み込みの infoType 検出器の拡張

組み込みの infoType 検出器で正しい値が返されない場合について考えてみます。たとえば、個人名の一致を返したいときに、データセットに共通の個人名の一部が Cloud DLP の組み込み PERSON_NAME 検出器で返されないとします。

Cloud DLP では、次の例のようにカスタム infoType 検出器の宣言に組み込み検出器を追加することで、組み込みの infoType 検出器を強化できます。このスニペットは、組み込みの PERSON_NAME infoType 検出器で名前「Quasimodo」が照合されるように Cloud DLP を構成する方法を示しています。

...
  "inspectConfig":{
    "customInfoTypes":[
      {
        "infoType":{
          "name":"PERSON_NAME"
        },
        "dictionary":{
          "wordList":{
            "words":[
              "quasimodo"
            ]
          }
        }
      }
    ]
  }
...