Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DLP image redaction sample (Take 2) #441

Merged
merged 2 commits into from
Aug 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions dlp/redact.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,59 @@ function redactString (string, replaceString, minLikelihood, infoTypes) {
// [END redact_string]
}

function redactImage (filepath, minLikelihood, infoTypes, outputPath) {
// [START redact_image]
// Imports required Node.js libraries
const mime = require('mime');
const fs = require('fs');

// Imports the Google Cloud Data Loss Prevention library
const DLP = require('@google-cloud/dlp');

// Instantiates a client
const dlp = DLP();

// The path to a local file to inspect. Can be a JPG or PNG image file.
// const fileName = 'path/to/image.png';

// The minimum likelihood required before redacting a match
// const minLikelihood = LIKELIHOOD_UNSPECIFIED;

// The infoTypes of information to redact
// const infoTypes = ['EMAIL_ADDRESS', 'PHONE_NUMBER'];

// The local path to save the resulting image to.
// const outputPath = 'result.png';

const fileItems = [{
type: mime.lookup(filepath) || 'application/octet-stream',
data: Buffer.from(fs.readFileSync(filepath)).toString('base64')
}];

const imageRedactionConfigs = infoTypes.map((infoType) => {
return { infoType: infoType };
});

const request = {
inspectConfig: {
minLikelihood: minLikelihood
},
imageRedactionConfigs: imageRedactionConfigs,
items: fileItems
};

dlp.redactContent(request)
.then((response) => {
const image = response[0].items[0].data;
fs.writeFileSync(outputPath, image);
console.log(`Saved image redaction results to path: ${outputPath}`);
})
.catch((err) => {
console.log(`Error in redactImage: ${err.message || err}`);
});
// [END redact_image]
}

const cli = require(`yargs`)
.demand(1)
.command(
Expand All @@ -72,6 +125,12 @@ const cli = require(`yargs`)
{},
(opts) => redactString(opts.string, opts.replaceString, opts.minLikelihood, opts.infoTypes)
)
.command(
`image <filepath> <outputPath>`,
`Redact sensitive data from an image using the Data Loss Prevention API.`,
{},
(opts) => redactImage(opts.filepath, opts.minLikelihood, opts.infoTypes, opts.outputPath)
)
.option('m', {
alias: 'minLikelihood',
default: 'LIKELIHOOD_UNSPECIFIED',
Expand All @@ -96,6 +155,7 @@ const cli = require(`yargs`)
})
})
.example(`node $0 string "My name is Gary" "REDACTED" -t US_MALE_NAME`)
.example(`node $0 image resources/test.png redaction_result.png -t US_MALE_NAME`)
.wrap(120)
.recommendCommands()
.epilogue(`For more information, see https://cloud.google.com/dlp/docs. Optional flags are explained at https://cloud.google.com/dlp/docs/reference/rest/v2beta1/content/inspect#InspectConfig`);
Expand Down
36 changes: 34 additions & 2 deletions dlp/system-test/redact.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@

const path = require('path');
const test = require('ava');
const fs = require('fs');
const tools = require('@google-cloud/nodejs-repo-tools');

const cmd = 'node redact';
const cwd = path.join(__dirname, `..`);

const testImage = 'resources/test.png';
const testResourcePath = 'system-test/resources';

test.before(tools.checkCredentials);

// redact_string
test(`should redact sensitive data from a string`, async (t) => {
test(`should redact multiple sensitive data types from a string`, async (t) => {
const output = await tools.runAsync(`${cmd} string "I am Gary and my phone number is (123) 456-7890." REDACTED -t US_MALE_NAME PHONE_NUMBER`, cwd);
t.is(output, 'I am REDACTED and my phone number is REDACTED.');
});

test(`should ignore unspecified type names when redacting from a string`, async (t) => {
test(`should redact a single sensitive data type from a string`, async (t) => {
const output = await tools.runAsync(`${cmd} string "I am Gary and my phone number is (123) 456-7890." REDACTED -t PHONE_NUMBER`, cwd);
t.is(output, 'I am Gary and my phone number is REDACTED.');
});
Expand All @@ -40,6 +44,34 @@ test(`should report string redaction handling errors`, async (t) => {
t.regex(output, /Error in redactString/);
});

// redact_image
test(`should redact a single sensitive data type from an image`, async (t) => {
const testName = `redact-multiple-types`;
const output = await tools.runAsync(`${cmd} image ${testImage} ${testName}.result.png -t PHONE_NUMBER EMAIL_ADDRESS`, cwd);

t.true(output.includes(`Saved image redaction results to path: ${testName}.result.png`));

const correct = fs.readFileSync(`${testResourcePath}/${testName}.correct.png`);
const result = fs.readFileSync(`${testName}.result.png`);
t.deepEqual(correct, result);
});

test(`should redact multiple sensitive data types from an image`, async (t) => {
const testName = `redact-single-type`;
const output = await tools.runAsync(`${cmd} image ${testImage} ${testName}.result.png -t PHONE_NUMBER`, cwd);

t.true(output.includes(`Saved image redaction results to path: ${testName}.result.png`));

const correct = fs.readFileSync(`${testResourcePath}/${testName}.correct.png`);
const result = fs.readFileSync(`${testName}.result.png`);
t.deepEqual(correct, result);
});

test(`should report image redaction handling errors`, async (t) => {
const output = await tools.runAsync(`${cmd} image ${testImage} nonexistent.result.png -t BAD_TYPE`, cwd);
t.regex(output, /Error in redactImage/);
});

// CLI options
test(`should have a minLikelihood option`, async (t) => {
const promiseA = tools.runAsync(`${cmd} string "My phone number is (123) 456-7890." REDACTED -t PHONE_NUMBER -m VERY_LIKELY`, cwd);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.