diff --git a/dlp/redact.js b/dlp/redact.js index ec1c03ddf2..73f2ee3f9a 100644 --- a/dlp/redact.js +++ b/dlp/redact.js @@ -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( @@ -72,6 +125,12 @@ const cli = require(`yargs`) {}, (opts) => redactString(opts.string, opts.replaceString, opts.minLikelihood, opts.infoTypes) ) + .command( + `image `, + `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', @@ -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`); diff --git a/dlp/system-test/redact.test.js b/dlp/system-test/redact.test.js index 1b053c6307..13c60e2cb3 100644 --- a/dlp/system-test/redact.test.js +++ b/dlp/system-test/redact.test.js @@ -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.'); }); @@ -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); diff --git a/dlp/system-test/resources/redact-multiple-types.correct.png b/dlp/system-test/resources/redact-multiple-types.correct.png new file mode 100644 index 0000000000..952b768f3a Binary files /dev/null and b/dlp/system-test/resources/redact-multiple-types.correct.png differ diff --git a/dlp/system-test/resources/redact-single-type.correct.png b/dlp/system-test/resources/redact-single-type.correct.png new file mode 100644 index 0000000000..b9540f32a2 Binary files /dev/null and b/dlp/system-test/resources/redact-single-type.correct.png differ