Présentation de Cloud Data Loss Prevention

1. Présentation

Cloud Data Loss Prevention (DLP) est un service entièrement géré conçu pour aider à détecter, classer et protéger les informations sensibles. Cet atelier de programmation présente certaines des fonctionnalités de base de l'API Cloud DLP, ainsi que les différentes façons de l'utiliser pour protéger les données.

Objectifs de l'atelier

  • Utiliser la protection contre la perte de données pour inspecter les chaînes et les fichiers à la recherche de types d'informations correspondants
  • Découvrez les techniques d'anonymisation et comment utiliser la protection contre la perte de données pour supprimer l'identification des données
  • Découvrez comment restaurer l'identification des données qui ont été anonymisées à l'aide du chiffrement préservant le format (FPE).
  • Utiliser la protection contre la perte de données pour masquer les types d'informations dans les chaînes et les images

Prérequis

  • Un projet Google Cloud avec la facturation configurée Si vous n'en avez pas, vous devrez en créer un.

2. Configuration

Cet atelier de programmation peut s'exécuter entièrement sur Google Cloud Platform sans aucune installation ni configuration locale.

Cloud Shell

Tout au long de cet atelier de programmation, nous allons provisionner et gérer différents services et ressources cloud à l'aide de la ligne de commande via Cloud Shell.

Téléchargez le dépôt du projet associé:

git clone https://github.com/googleapis/nodejs-dlp

Une fois le code du projet téléchargé, accédez au répertoire des exemples et installez les packages Node.js requis:

cd samples && npm install

Assurez-vous d'utiliser le bon projet en le définissant à l'aide de la commande gcloud suivante:

gcloud config set project [PROJECT_ID]

Activer les API

Voici les API que nous devrons activer dans notre projet:

  • API Cloud Data Loss Prevention : fournit des méthodes de détection, d'analyse des risques et d'anonymisation de fragments sensibles à la confidentialité dans du texte, des images et des dépôts de stockage Google Cloud Platform.
  • API Cloud Key Management Service (KMS) : Google Cloud KMS permet aux clients de gérer les clés de chiffrement et d'effectuer des opérations de chiffrement à l'aide de ces clés.

Activez les API requises à l'aide de la commande gcloud suivante:

gcloud services enable dlp.googleapis.com cloudkms.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}

3. Inspecter les chaînes et les fichiers

Le répertoire d'exemples du projet téléchargé à l'étape précédente contient plusieurs fichiers JavaScript qui exploitent les différentes fonctionnalités de Cloud DLP. inspect.js recherche les types d'informations sensibles dans une chaîne ou un fichier fourni.

Pour tester cela, vous pouvez fournir l'option string et un exemple de chaîne contenant des informations potentiellement sensibles:

node inspect.js -c $GOOGLE_CLOUD_PROJECT \
string 'My email address is jenny@somedomain.com and you can call me at 555-867-5309'

Le résultat doit nous indiquer les résultats pour chaque type d'information correspondant, y compris:

Citation: le modèle spécifie

InfoType: le type d'information détecté pour cette partie de la chaîne. Pour consulter la liste complète des types d'informations possibles, cliquez ici. Par défaut, inspect.js ne inspecte que les types d'informations CREDIT_CARD_NUMBER, PHONE_NUMBER ET EMAIL_ADDRESS

Probabilité: les résultats sont classés en fonction de la probabilité qu'ils représentent une correspondance. La probabilité est comprise entre VERY_UNLIKELY et VERY_LIKELY.

Les résultats de la requête de commande ci-dessus sont les suivants:

Findings:
        Quote: jenny@somedomain.com
        Info type: EMAIL_ADDRESS
        Likelihood: LIKELY
        Quote: 555-867-5309
        Info type: PHONE_NUMBER
        Likelihood: VERY_LIKELY

De même, nous pouvons inspecter les fichiers à la recherche de types d'informations. Consultez l'exemple de fichier accounts.txt:

resources/accounts.txt

My credit card number is 1234 5678 9012 3456, and my CVV is 789.

Exécutez à nouveau inspect.js, cette fois avec l'option de fichier:

node inspect.js -c $GOOGLE_CLOUD_PROJECT file resources/accounts.txt

Résultats :

Findings:
        Quote: 5678 9012 3456
        Info type: CREDIT_CARD_NUMBER
        Likelihood: VERY_LIKELY

Pour l'un ou l'autre type de requête, nous pourrions limiter les résultats par probabilité ou par type d'information. Exemple :

node inspect.js -c $GOOGLE_CLOUD_PROJECT \
string 'Call 900-649-2568 or email me at anthony@somedomain.com' \
-m VERY_LIKELY

Si vous spécifiez VERY_LIKELY comme probabilité minimale, toutes les correspondances inférieures à VERY_LIKELY sont exclues:

Findings:
        Quote: 900-649-2568
        Info type: PHONE_NUMBER
        Likelihood: VERY_LIKELY

Les résultats complets, sans limite, sont les suivants:

Findings:
        Quote: 900-649-2568
        Info type: PHONE_NUMBER
        Likelihood: VERY_LIKELY
        Quote: anthony@somedomain.com
        Info type: EMAIL_ADDRESS
        Likelihood: LIKELY

De même, nous pourrions spécifier le type d'informations que nous vérifions:

node inspect.js -c $GOOGLE_CLOUD_PROJECT \
string 'Call 900-649-2568 or email me at anthony@somedomain.com' \
-t EMAIL_ADDRESS

Seul le type d'informations spécifié est renvoyé s'il est trouvé:

Findings:
        Quote: anthony@somedomain.com
        Info type: EMAIL_ADDRESS
        Likelihood: LIKELY

Vous trouverez ci-dessous la fonction asynchrone qui utilise l'API pour inspecter l'entrée:

inspect.js

async function inspectString(
  callingProjectId,
  string,
  minLikelihood,
  maxFindings,
  infoTypes,
  customInfoTypes,
  includeQuote
) {
...
}

Les arguments fournis pour les paramètres ci-dessus sont utilisés pour construire un objet de requête. Cette requête est ensuite transmise à la fonction inspectContent pour obtenir une réponse qui aboutit au résultat suivant:

inspect.js

  // Construct item to inspect
  const item = {value: string};

  // Construct request
  const request = {
    parent: dlp.projectPath(callingProjectId),
    inspectConfig: {
      infoTypes: infoTypes,
      customInfoTypes: customInfoTypes,
      minLikelihood: minLikelihood,
      includeQuote: includeQuote,
      limits: {
        maxFindingsPerRequest: maxFindings,
      },
    },
    item: item,
  };
...
...
 const [response] = await dlp.inspectContent(request);

4. Anonymisation

En plus d'inspecter et de détecter les données sensibles, Cloud DLP peut effectuer l'anonymisation. L’anonymisation est le processus qui consiste à éliminer les informations d'identification des données. L'API détecte les données sensibles telles que définies par les types d'informations, puis utilise une transformation d'anonymisation pour masquer, supprimer ou dissimuler les données.

deid.js illustre la suppression de l'identification de plusieurs manières. La méthode d'anonymisation la plus simple consiste à utiliser un masque:

node deid.js deidMask -c $GOOGLE_CLOUD_PROJECT \
"My order number is F12312399. Email me at anthony@somedomain.com"

Avec un masque, l'API remplace les caractères du type d'information correspondant par un caractère différent, * par défaut. Le résultat sera le suivant:

My order number is F12312399. Email me at *****************************

Notez que l'adresse e-mail contenue dans la chaîne est obscurcie, tandis que le numéro de commande arbitraire est intact. (Les types d'informations personnalisés sont possibles, mais ils ne sont pas abordés dans cet atelier de programmation.)

Examinons la fonction qui utilise l'API DLP pour supprimer l'identification à l'aide d'un masque:

deid.js

async function deidentifyWithMask(
  callingProjectId,
  string,
  maskingCharacter,
  numberToMask
) {
...
}

Là encore, ces arguments servent à construire un objet de requête. Cette fois, elle est transmise à la fonction deidentifyContent:

deid.js

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

Anonymiser à l'aide d'un chiffrement préservant le format

L'API DLP permet également de chiffrer les valeurs de données sensibles à l'aide d'une clé cryptographique.

Nous allons commencer par créer un trousseau de clés à l'aide de Cloud KMS:

gcloud kms keyrings create dlp-keyring --location global

Nous pouvons maintenant créer une clé que nous allons utiliser pour chiffrer les données:

gcloud kms keys create dlp-key \
--purpose='encryption' \
--location=global \
--keyring=dlp-keyring

L'API DLP accepte une clé encapsulée chiffrée avec la clé KMS que nous avons créée. Nous pouvons générer une chaîne aléatoire qui sera encapsulée. Nous en aurons besoin plus tard pour restaurer l'identification:

export AES_KEY=`head -c16 < /dev/random | base64 -w 0`

Nous pouvons maintenant chiffrer la chaîne avec notre clé KMS. Un fichier binaire contenant la chaîne chiffrée est alors généré:

echo -n $AES_KEY | gcloud kms encrypt \
--location global \
--keyring dlp-keyring  \
--key dlp-key \
--plaintext-file - \
--ciphertext-file ./ciphertext.bin 

À l'aide de deid.js, nous pouvons désormais anonymiser le numéro de téléphone dans l'exemple de chaîne ci-dessous à l'aide du chiffrement:

node deid.js deidFpe -c $GOOGLE_CLOUD_PROJECT \
"My client's cell is 9006492568" `base64 -w 0 ciphertext.bin` \
projects/${GOOGLE_CLOUD_PROJECT}/locations/global/keyRings/dlp-keyring/cryptoKeys/dlp-key \
-s PHONE_NUMBER

Le résultat renvoie la chaîne avec les types d'informations correspondants remplacés par une chaîne chiffrée et précédés du type d'information indiqué par l'indicateur -s:

My client's cell is PHONE_NUMBER(10):vSt55z79nR

Examinons la fonction que nous utilisons pour anonymiser la chaîne:

deid.js

async function deidentifyWithFpe(
  callingProjectId,
  string,
  alphabet,
  surrogateType,
  keyName,
  wrappedKey
) {
...
}

Les arguments permettent de construire un objet cryptoReplaceFfxFpeConfig:

deid.js

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

L'objet cryptoReplaceFfxFpeConfig est à son tour utilisé dans la requête adressée à l'API via la fonction deidentifyContent:

deid.js

  // 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);

Restaurer l'identification des données

Afin de restaurer l'identification des données, l'API DLP utilisera le texte chiffré que nous avons créé à l'étape précédente:

node deid.js reidFpe -c $GOOGLE_CLOUD_PROJECT \
"<YOUR_DEID_OUTPUT>" \
PHONE_NUMBER `base64 -w 0 ciphertext.bin`  \
projects/${GOOGLE_CLOUD_PROJECT}/locations/global/keyRings/dlp-keyring/cryptoKeys/dlp-key

Le résultat obtenu correspond à la chaîne d'origine sans aucun masquage ni type de substitution indiqué:

My client's cell is 9006492568

La fonction utilisée pour restaurer l'identification des données est semblable à celle utilisée pour les anonymiser:

deid.js

async function reidentifyWithFpe(
  callingProjectId,
  string,
  alphabet,
  surrogateType,
  keyName,
  wrappedKey
) {
...
}

Là encore, les arguments sont utilisés dans une requête adressée à l'API, cette fois à la fonction reidentifyContent:

deid.js

  // Construct deidentification request
  const item = {value: string};
  const request = {
    parent: dlp.projectPath(callingProjectId),
    reidentifyConfig: {
      infoTypeTransformations: {
        transformations: [
          {
            primitiveTransformation: {
              cryptoReplaceFfxFpeConfig: {
                cryptoKey: {
                  kmsWrapped: {
                    wrappedKey: wrappedKey,
                    cryptoKeyName: keyName,
                  },
                },
                commonAlphabet: alphabet,
                surrogateInfoType: {
                  name: surrogateType,
                },
              },
            },
          },
        ],
      },
    },
    inspectConfig: {
      customInfoTypes: [
        {
          infoType: {
            name: surrogateType,
          },
          surrogateType: {},
        },
      ],
    },
    item: item,
  };

  try {
    // Run reidentification request
    const [response] = await dlp.reidentifyContent(request);

Anonymiser des dates à l'aide du changement de date

Dans certains contextes, les dates peuvent être considérées comme des données sensibles que nous souhaitons masquer. Le changement de date permet de décaler les dates d'un incrément aléatoire tout en préservant la séquence et la durée d'une période. Chaque date d'un ensemble est décalée d'une durée propre à cette entrée. Pour illustrer la suppression de l'identification via le changement de date, commencez par examiner l'exemple de fichier CSV contenant des données de date:

resources/dates.csv

name,birth_date,register_date,credit_card
Ann,01/01/1980,07/21/1996,4532908762519852
James,03/06/1988,04/09/2001,4301261899725540
Dan,08/14/1945,11/15/2011,4620761856015295
Laura,11/03/1992,01/04/2017,4564981067258901

Les données contiennent deux champs auxquels nous pourrions appliquer un décalage de date: birth_date et register_date. deid.js accepte une valeur de limite inférieure et une valeur de limite supérieure pour définir une plage permettant de sélectionner un nombre aléatoire de jours par rapport auquel les dates doivent être décalées:

node deid.js deidDateShift -c $GOOGLE_CLOUD_PROJECT resources/dates.csv datesShifted.csv 30 90 birth_date

Un fichier nommé datesShifted.csv est généré. Les dates sont décalées de manière aléatoire d'un nombre de jours compris entre 30 et 90. Voici un exemple de résultat généré:

name,birth_date,register_date,credit_card
Ann,2/6/1980,7/21/1996,4532908762519852
James,5/18/1988,4/9/2001,4301261899725540
Dan,9/16/1945,11/15/2011,4620761856015295
Laura,12/16/1992,1/4/2017,4564981067258901

Notez que nous avons également pu spécifier la colonne de date du fichier CSV que nous voulions déplacer. Le champ birth_date. Le champ register_date reste inchangé.

Examinons une fonction qui gère l'anonymisation avec un décalage de date:

deid.js

async function deidentifyWithDateShift(
  callingProjectId,
  inputCsvFile,
  outputCsvFile,
  dateFields,
  lowerBoundDays,
  upperBoundDays,
  contextFieldId,
  wrappedKey,
  keyName
) {
...
}

Notez que cette fonction peut accepter une clé encapsulée et un nom de clé, comme avec l'anonymisation avec FPE, ce qui nous permet de fournir une clé de chiffrement pour restaurer l'identification d'un changement de date. Les arguments que nous fournissons créent un objet dateShiftConfig:

deid.js

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

5. Masquer des chaînes et des images

Le masquage est une autre méthode d'obscurcissement des informations sensibles. Le masquage remplacera une correspondance par le type d'information correspondant. redact.js illustre le masquage:

node redact.js -c $GOOGLE_CLOUD_PROJECT \
string "Please refund the purchase to my credit card 4012888888881881" \
-t 'CREDIT_CARD_NUMBER'

Le résultat remplace l'exemple de numéro de carte de crédit par le type d'informations CREDIT_CARD_NUMBER:

Please refund the purchase on my credit card [CREDIT_CARD_NUMBER]

Cette fonctionnalité est utile si vous souhaitez masquer des informations sensibles tout en identifiant le type d'informations à supprimer. De la même manière, l'API DLP peut masquer des informations dans les images contenant du texte. À titre d'exemple, examinons un exemple d'image:

resources/test.png

bf3719cfeb5676ff.png

Pour masquer le numéro de téléphone et l'adresse e-mail sur l'image ci-dessus:

node redact.js -c $GOOGLE_CLOUD_PROJECT \
image resources/test.png ./redacted.png \
-t PHONE_NUMBER -t EMAIL_ADDRESS

Comme spécifié, une nouvelle image nommée redacted.png sera générée avec les informations demandées masquées:

ce023dd95cccc40f.png

Voici la fonction utilisée pour masquer une chaîne:

redact.js

async function redactText(
  callingProjectId, 
  string,
  minLikelihood,
  infoTypes
) {
...}

Voici la requête qui sera envoyée à la fonction deidentifyContent:

redact.js

const request = {
    parent: dlp.projectPath(callingProjectId),
    item: {
      value: string,
    },
    deidentifyConfig: {
      infoTypeTransformations: {
        transformations: [replaceWithInfoTypeTransformation],
      },
    },
    inspectConfig: {
      minLikelihood: minLikelihood,
      infoTypes: infoTypes,
    },
  };

De même, voici la fonction permettant de masquer une image:

redact.js

async function redactImage(
  callingProjectId,
  filepath,
  minLikelihood,
  infoTypes,
  outputPath
) {
...}

Voici la requête qui sera envoyée à la fonction redactImage:

redact.js

// Construct image redaction request
  const request = {
    parent: dlp.projectPath(callingProjectId),
    byteItem: {
      type: fileTypeConstant,
      data: fileBytes,
    },
    inspectConfig: {
      minLikelihood: minLikelihood,
      infoTypes: infoTypes,
    },
    imageRedactionConfigs: imageRedactionConfigs,
  };

6. Effectuer un nettoyage

Nous avons vu comment utiliser l'API DLP pour masquer, anonymiser et masquer les informations sensibles de nos données. Il est maintenant temps de nettoyer notre projet de toutes les ressources que nous avons créées.

Supprimer le projet

Dans la console GCP, accédez à la page Cloud Resource Manager :

Dans la liste des projets, sélectionnez celui dans lequel vous avez travaillé, puis cliquez sur Supprimer. Vous serez alors invité à saisir l'ID du projet. Saisissez-le, puis cliquez sur Arrêter.

Vous pouvez également supprimer le projet entier directement dans Cloud Shell à l'aide de gcloud:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

7. Félicitations !

Bravo ! Bravo ! Cloud DLP est un outil performant qui donne accès à une puissante plate-forme d'inspection, de classification et d'anonymisation des données sensibles.

Points abordés

  • Nous avons vu comment utiliser l'API Cloud DLP pour détecter plusieurs types d'informations dans des chaînes et des fichiers
  • Nous avons appris comment l'API DLP peut anonymiser les chaînes à l'aide d'un masque pour masquer les types d'informations correspondant à la mise en correspondance des données.
  • Nous avons utilisé l'API DLP afin d'utiliser une clé de chiffrement pour anonymiser, puis restaurer l'identification des données.
  • Nous avons utilisé l'API DLP pour masquer les données d'une chaîne et d'une image.