Cloud Data Loss Prevention 總覽

1. 總覽

Cloud Data Loss Prevention (DLP) 是一項全代管服務,可協助探索、分類及保護機密資訊。本程式碼研究室將介紹 Cloud DLP API 的一些基本功能,並示範以多種方式保護資料的方法。

執行步驟

  • 使用 DLP 檢查字串和檔案是否有相符的資訊類型
  • 瞭解去識別化技巧並使用 DLP 將資料去識別化
  • 瞭解如何使用格式保留加密 (FPE) 重新識別已去識別化的資料
  • 使用 DLP 遮蓋字串和圖片中的資訊類型

軟硬體需求

  • 已設定帳單的 Google Cloud 專案。如果沒有 Google 帳戶,請先建立帳戶

2. 開始設定

本程式碼研究室不必在本機安裝或設定,就能完全在 Google Cloud Platform 上執行。

Cloud Shell

在本程式碼研究室中,我們將透過 Cloud Shell 使用指令列,佈建及管理不同的雲端資源和服務。

下載隨附專案存放區:

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

下載專案程式碼後,請變更為 Sample 目錄,然後安裝所需的 Node.js 套件:

cd samples && npm install

請透過下列 gcloud 指令設定正確的專案:

gcloud config set project [PROJECT_ID]

啟用 API

以下是需為專案啟用的 API:

  • Cloud Data Loss Prevention API:提供偵測、風險分析和去識別化方法,用於文字、圖片和 Google Cloud Platform 儲存空間存放區中的私密敏感內容片段
  • Cloud Key Management Service (KMS) API:Google Cloud KMS 可讓客戶管理加密金鑰,並使用這些金鑰執行加密編譯作業。

使用以下 gcloud 指令啟用必要的 API:

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

3. 檢查字串和檔案

上一個步驟中下載的專案範例目錄包含數個使用 Cloud DLP 不同功能的 JavaScript 檔案。inspect.js 會檢查提供的字串或檔案是否含有機密資訊類型。

如要進行測試,您可以提供 string 選項和包含某些機密資訊的範例字串:

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

輸出結果應會說明每個相符資訊類型的發現結果,包括:

引用:範本指定

InfoType:針對該部分字串偵測到的資訊類型。請按這裡查看完整的可能資訊類型清單。根據預設,inspect.js 只會檢查類型 CREDIT_CARD_NUMBERPHONE_NUMBEREMAIL_ADDRESS 的資訊

可能性:結果會按照這些結果代表相符項目的可能性來分類。可能性介於 VERY_UNLIKELYVERY_LIKELY 之間。

上述指令要求的發現項目如下:

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

同樣地,我們可以檢查檔案是否含有資訊類型。查看 accounts.txt 範例檔案:

resources/accounts.txt

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

再次執行 inspect.js,這次使用檔案選項:

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

結果:

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

不論是哪一種查詢,我們都可以根據可能性或資訊類型來限制結果。例如:

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

將「VERY_LIKELY」指定為最低可能性,就會排除所有低於 VERY_LIKELY 的相符項目:

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

無限制的完整結果如下:

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

同樣地,我們可以指定想要檢查的資訊類型:

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

如果出現下列情況,系統只會傳回指定的資訊類型:

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

以下是使用 API 檢查輸入的非同步函式:

inspect.js

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

為上述參數提供的引數則用於建構要求物件。然後該要求會提供給 inspectContent 函式,取得輸出結果的回應:

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. 去識別化

Cloud DLP 不僅可以檢查及偵測機密資料,還能執行去識別化作業。去識別化是移除資料中識別資訊的程序。API 會偵測資訊類型定義的機密資料,然後使用去識別化轉換來遮蓋、刪除或遮蓋資料。

deid.js 會透過多種方式示範去識別化。最簡單的去識別化方法就是使用遮罩:

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

透過遮罩,API 會根據預設,將相符資訊類型的字元替換成其他字元 *。輸出內容應如下所示:

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

請注意,字串中的電子郵件地址已經過模糊處理,任意訂單號碼則保持不變。(您也可以使用自訂資訊類型,但此類型不在本程式碼研究室的涵蓋範圍內)。

接著來看看使用 DLP API 來透過遮罩去識別化的函式:

deid.js

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

再次使用這些引數建構要求物件。這次就會提供給 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);

透過格式保留加密進行去識別化

DLP API 還能使用加密編譯金鑰加密機密資料值。

我們會開始使用 Cloud KMS 建立金鑰環:

gcloud kms keyrings create dlp-keyring --location global

現在,我們可以建立用來加密資料的金鑰:

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

DLP API 接受以我們建立的 KMS 金鑰加密的包裝金鑰。我們可以產生隨機要包裝的字串。稍後需要這項資訊才能重新識別:

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

現在,我們可以使用 KMS 金鑰加密字串。這會產生二進位檔案,其中包含以加密字串形式的加密字串:

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

使用 deid.js 後,我們現在可以透過加密的方式,將下方範例字串中的電話號碼去識別化:

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

輸出會傳回字串,其中包含相符的資訊類型,該類型會由加密字串取代,且前面會加上 -s 旗標指定的資訊類型:

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

我們來看看用來將字串去識別化的函式:

deid.js

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

這些引數可用來建構 cryptoReplaceFfxFpeConfig 物件:

deid.js

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

接著,透過 deidentifyContent 函式向 API 傳送要求時,會使用 cryptoReplaceFfxFpeConfig 物件:

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

重新識別資料

為了重新識別資料,DLP API 會使用我們在上一步建立的密文:

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

輸出結果會是原始字串,且不含遮蓋或代理類型:

My client's cell is 9006492568

用於重新識別資料的函式與用來去識別化資料的函式類似:

deid.js

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

同時,引數也會用於對 API 的要求中,這次是 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);

使用日期轉移將日期去識別化

在某些情況下,日期可能會視為機密資料,我們可能需進行模糊處理。日期轉移功能可讓我們以隨機遞增的方式調整日期,同時保留一段時間的順序和時間長度。集合中的每個日期都會依項目專屬的時間長度進行轉移。如要透過日期轉移示範去識別化,請先查看含有日期資料的 CSV 範例檔案:

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

此資料包含兩個欄位,可用來套用日期偏移值:birth_dateregister_date。deid.js 接受下限值和上限值,藉此定義用於選取轉移日期的隨機天數的範圍:

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

系統會產生一個名為 datesShifted.csv 的檔案,其中包含日期介於 30 至 90 之間的天數隨機調整。以下是產生的輸出內容範例:

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

您會發現,我們還能指定要轉移 CSV 檔案中的哪個日期欄。birth_date 欄位「register_date」欄位會保持不變。

我們來看看可使用日期偏移進行去識別化的函式:

deid.js

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

請注意,這個函式可能會接受經過包裝的金鑰和金鑰名稱,與使用 FPE 進行去識別化相似,因此我們可以選擇提供加密金鑰來重新識別日期偏移。我們提供 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. 遮蓋字串和圖片

另一種模糊處理機密資訊的方法為遮蓋。遮蓋功能會以系統識別出相符的資訊類型取代相符項目。redact.js 會示範遮蓋作業:

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

輸出結果會以資訊類型 CREDIT_CARD_NUMBER 取代樣本信用卡號碼:

Please refund the purchase on my credit card [CREDIT_CARD_NUMBER]

如果您想隱藏機密資訊,但同時又想找出要移除的資訊類型,這個方法就很實用。DLP API 同樣可以遮蓋含有文字的圖片中的資訊。我們來看看範例圖片:

resources/test.png

bf3719cfeb5676ff.png

如要遮蓋上圖中的電話號碼和電子郵件地址,請按照下列步驟操作:

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

如已指定,系統會產生一個名為 redacted.png 的新圖片,並將所要求的資訊塗黑:

ce023dd95cccc40f.png

以下函式可用於遮蓋字串:

redact.js

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

下列是將提供給 deidentifyContent 函式的要求:

redact.js

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

以下是遮蓋圖片的函式:

redact.js

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

下列是將提供給 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. 清除所用資源

我們已探索如何使用 DLP API 遮蓋、去識別化及遮蓋資料中的機密資訊。現在就可以開始清除我們已建立的任何資源專案了。

刪除專案

前往 GCP Console 的「Cloud Resource Manager」頁面。

在專案清單中,選取處理中的專案,然後按一下「Delete」(刪除)。系統會提示您輸入專案 ID。輸入 PIN 碼,然後按一下「關閉」

或者,您也可以透過 gcloud 直接從 Cloud Shell 刪除整個專案:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

7. 恭喜!

太厲害了!您做到了!Cloud DLP 是一項功能強大的工具,可讓您存取功能強大的機密資料檢查、分類和去識別化平台。

涵蓋內容

  • 我們瞭解如何使用 Cloud DLP API 檢查字串和檔案,檢查多種資訊類型
  • 我們已瞭解 DLP API 如何使用遮罩將字串去識別化,以隱藏與資訊類型相符的資料類型
  • 我們使用 DLP API 將加密金鑰去識別化,然後重新識別資料
  • 我們使用 DLP API 來遮蓋字串和圖片中的資料