1. 概览
Cloud Data Loss Prevention (DLP) 是一项全托管式服务,旨在帮助发现、分类和保护敏感信息。此 Codelab 将介绍 Cloud DLP API 的一些基本功能,并演示如何使用该 API 来保护数据。
实践内容
- 使用 DLP 检查字符串和文件,找出匹配的信息类型
- 了解去标识化方法,并使用 DLP 对数据进行去标识化处理
- 了解如何重新标识使用保留格式加密 (FPE) 进行去标识化的数据
- 使用 DLP 隐去字符串和图片中的信息类型
所需条件
- 已设置结算功能的 Google Cloud 项目。如果您没有 Google 账号,则必须创建一个。
2. 准备工作
此 Codelab 可完全在 Google Cloud Platform 上运行,无需进行任何本地安装或配置。
Cloud Shell
在此 Codelab 中,我们将使用 Cloud Shell 通过命令行预配和管理不同的云资源和服务。
下载配套项目代码库:
git clone https://github.com/googleapis/nodejs-dlp
下载项目代码后,切换到 samples 目录并安装所需的 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. 检查字符串和文件
在上一步下载的项目中,目录“samples”包含多个 JavaScript 文件,这些文件使用了 Cloud DLP 的不同功能。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_NUMBER、PHONE_NUMBER 和 EMAIL_ADDRESS
Likelihood:根据匹配项的可能性进行分类。似然值可介于 VERY_UNLIKELY 到 VERY_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 *****************************
请注意,字符串中的电子邮件地址被混淆了,而任意订单号依然保持完整。(可使用自定义信息类型,但不在本 Codelab 范围内)。
我们来看看使用 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_date 和 register_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. 隐去字符串和图片中的敏感信息
混淆敏感信息的另一种方法是隐去。隐去会将匹配项替换为与之匹配的 infoType。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

如需从上面的图片中隐去电话号码和电子邮件地址,请执行以下操作:
node redact.js -c $GOOGLE_CLOUD_PROJECT \ image resources/test.png ./redacted.png \ -t PHONE_NUMBER -t EMAIL_ADDRESS
基于命令,系统会生成一张名为 redacted.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 页面:
在项目列表中,选择我们一直使用的项目,然后点击删除。此时,系统会提示您输入项目 ID。输入项目 ID,然后点击关停。
此外,您也可以使用 gcloud 直接从 Cloud Shell 中删除整个项目:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
7. 恭喜!
棒棒哒!大功告成!Cloud DLP 是一款功能强大的工具,提供了一个用于敏感数据检查、分类和去标识化的强大平台。
所学内容
- 我们了解了如何使用 Cloud DLP API 检查字符串和文件中的多种信息类型
- 我们了解了 DLP API 如何使用遮盖来对字符串进行去标识化,以隐藏与信息类型匹配的数据
- 我们使用 DLP API 通过加密密钥对数据进行去标识化处理,然后再重新标识数据
- 我们使用 DLP API 隐去了字符串和图片中的数据