Créer un détecteur de dictionnaire personnalisé standard

Les dictionnaires personnalisés permettent de façon simple, mais efficace, de trouver une liste de mots ou d'expressions. Cette fonctionnalité peut agir en tant que détecteur unique et servir à créer une liste d'exceptions pour des détecteurs intégrés. Vous pouvez également utiliser des dictionnaires personnalisés pour augmenter la couverture des détecteurs d'infoTypes intégrés afin qu'ils identifient davantage de correspondances.

Anatomie d'un détecteur d'infoType de dictionnaire personnalisé

Comme résumé dans la présentation de l'API, pour créer un détecteur d'infoType de dictionnaire personnalisé, vous devez définir un objet CustomInfoType qui contient les éléments suivants :

  • Le nom que vous souhaitez attribuer au détecteur d'infoType personnalisé, dans un objet InfoType.
  • Une valeur facultative pour Likelihood. Si vous omettez cette valeur, les correspondances avec les éléments du dictionnaire indiquent la probabilité par défaut POSSIBLE (très probable).
  • Des objets DetectionRule facultatifs ou des règles relatives aux mots clés. Ces règles permettent d'ajuster la probabilité des résultats dans un espace de proximité donné avec certains mots clés spécifiés. Pour en savoir plus sur les règles relatives aux mots clés, consultez la page Personnaliser la probabilité de correspondance.
  • Un élément Dictionary au format WordList contenant une liste de mots à rechercher ou un chemin d'accès CloudStoragePath à un fichier texte unique comportant une liste de mots délimités par un retour à la ligne.

En tant qu'objet JSON, un détecteur d'infoType de dictionnaire personnalisé qui inclut tous les composants facultatifs se présente tel qu'indiqué ci-dessous. (Cet objet JSON inclut un chemin d'accès à un fichier dictionnaire de type texte stocké dans Cloud Storage. Pour afficher une liste de mots intégrée, consultez la section Exemples, plus loin dans cet article.)

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

Dictionnaires personnalisés stockés

Cloud DLP est également compatible avec les dictionnaires personnalisés stockés pour inspecter des dépôts de stockage. Avec un dictionnaire personnalisé stocké, Cloud DLP peut par exemple rechercher des centaines de millions de noms d'utilisateur, d'adresses e-mail ou tout autre type de chaîne défini dans la section Caractéristiques des correspondances avec le dictionnaire. En outre, Cloud DLP inclut une fonctionnalité intégrée qui vous permet de recréer automatiquement votre dictionnaire personnalisé stocké si nécessaire.

Les dictionnaires personnalisés stockés sont compilés à partir de collections d'expressions hébergées dans un bucket Cloud Storage ou une table BigQuery appartenant à votre organisation. La première fois que vous créez un dictionnaire personnalisé stocké, vous saisissez les expressions à rechercher dans Cloud Storage ou BigQuery, puis vous générez le dictionnaire personnalisé stocké à l'aide de Cloud DLP. Le dictionnaire personnalisé est stocké dans Cloud Storage. Lorsque vous ajoutez ou supprimez des mots du bucket Cloud Storage ou de la table BigQuery dans lesquels ils sont stockés, vous pouvez alors recréer votre dictionnaire personnalisé stocké à l'aide de Cloud DLP.

Pour en savoir plus à ce sujet, consultez la page Créer un détecteur de dictionnaire personnalisé stocké.

Caractéristiques des correspondances avec le dictionnaire

Vous trouverez ci-dessous des indications sur la manière dont Cloud DLP identifie des correspondances avec les mots et les expressions du dictionnaire. Ces points s'appliquent aux dictionnaires personnalisés standards et stockés :

  • Les mots du dictionnaire sont insensibles à la casse. Si votre dictionnaire inclut le nom Abby, il y aura correspondance avec les noms abby, ABBY, Abby, etc.
  • Tous les caractères (dans les dictionnaires ou dans les contenus à analyser) autres que les lettres et les chiffres figurant dans le plan multilingue de base d'Unicode sont considérés comme des espaces lors de la recherche de correspondances. Si votre dictionnaire recherche le nom Abby Abernathy, il y aura correspondance avec abby abernathy, Abby, Abernathy, Abby (ABERNATHY), etc.
  • Les caractères entourant une correspondance doivent être d'un type différent (lettres ou chiffres) des caractères adjacents au sein du mot. Si votre dictionnaire recherche le nom Abi, il y aura correspondance avec les trois premiers caractères de Abi904, mais pas de Abigail.
  • Les mots du dictionnaire contenant un grand nombre de caractères autres que des lettres ou des chiffres peuvent générer des résultats inattendus, car ces caractères sont traités comme des espaces.

Exemples

Liste simple de mots

Supposons que vous disposiez de données indiquant la chambre d'hôpital dans laquelle des patients ont été traités lors d'une visite. Ces informations de localisation peuvent être considérées comme sensibles dans un ensemble de données particulier, mais ne sont pas identifiées par les détecteurs intégrés de Cloud DLP.

Les chambres sont répertoriées comme suit :

  • "RM-Orange"
  • "RM-Yellow"
  • "RM-Green"

Protocole

L'exemple JSON suivant définit un dictionnaire personnalisé qui vous permet de supprimer l'identification des numéros de chambre.

Entrée 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"
            ]
          }
        }
      }
    ]
  }
}

Sortie JSON :

Si vous envoyez cette entrée JSON via la méthode POST à content:deidentify, vous obtenez la réponse JSON suivante :

{
  "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"
      }
    ]
  }
}

Cloud DLP a correctement identifié les numéros de chambre spécifiés dans le message WordList du dictionnaire personnalisé. Vous remarquerez que les éléments sont correctement identifiés même lorsque le trait d'union - est absent, ce qui est le cas pour la valeur "rm green".

Java


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#


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;
    }
}

Liste d'exceptions

Supposons que vous disposiez de données de journaux comprenant des identifiants client (comme des adresses e-mail) et que vous souhaitiez masquer ces informations. Cependant, ces journaux incluent également les adresses e-mail de vos développeurs, et vous ne voulez pas les masquer.

Protocole

L'exemple JSON suivant crée un dictionnaire personnalisé répertoriant un sous-ensemble d'adresses e-mail dans le message WordList (Jack@example.org et jill@example.org) et leur attribue le nom d'infoType personnalisé DEVELOPER_EMAIL. Ce code JSON indique à Cloud DLP d'ignorer les adresses e-mail spécifiées, mais de remplacer les autres adresses détectées par une chaîne correspondant à son infoType (EMAIL_ADDRESS dans le cas présent) :

Entrée 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"
      }
    ]
  }
}

Sortie JSON :

Si vous envoyez cette entrée JSON via la méthode POST à content:deidentify, vous obtenez la réponse JSON suivante :

{
  "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"
      }
    ]
  }
}

L'adresse e-mail user1@example.com a correctement été identifiée comme correspondant à l'infoType EMAIL_ADDRESS et jack@example.org comme une adresse e-mail correspondant à l'infoType personnalisé DEVELOPER_EMAIL. Notez que l'adresse e-mail jack@example.org est restée intacte, car il a été demandé de ne transformer que l'infoType EMAIL_ADDRESS.

Java


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#


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;
    }
}

Étendre le champ d'application d'un détecteur d'infoType intégré

Imaginons une situation dans laquelle un détecteur d'infoType intégré ne renvoie pas les bonnes valeurs. Par exemple, vous souhaitez renvoyer des correspondances avec des noms de personnes, mais le détecteur PERSON_NAME intégré de Cloud DLP ne parvient pas à renvoyer les correspondances sur certains noms courants dans votre ensemble de données.

Cloud DLP vous permet d'étendre le champ d'application des détecteurs d'infoTypes intégrés en incluant un détecteur intégré dans la déclaration d'un détecteur d'infoType personnalisé, comme illustré dans l'exemple suivant. Cet extrait montre comment configurer Cloud DLP pour que le détecteur d'infoType intégré PERSON_NAME identifie également le nom "Quasimodo" :

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