From caa91ebecdfa006d62b9b099cfd89e6818d9053c Mon Sep 17 00:00:00 2001 From: Adam Bretz Date: Mon, 13 Apr 2015 10:39:05 -0400 Subject: [PATCH] Updates to filtering. --- README.md | 2 +- lib/utils.js | 46 +++++++++++++++++++++++----------------------- package.json | 3 ++- test/monitor.js | 33 +++++++++++++++++++++++++-------- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 7094953..6f1b7a0 100755 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ set `options` to an object with the following optional settings: - "remove" - `delete`s the value - a valid regular express string. Only supports a single group. Ex: `"(\\d{4})$"` will replace the last four digits with "X"s. Take extra care when creating this string. You will need to make sure that the resultant RegExp object is what you need. - `filter` can be used to remove potentially sensitive information (credit card numbers, social security numbers, etc.) from the log payloads before they are sent out to reporters. This setting only impacts `response` events and only if payloads are included via `requestPayload` and `responsePayload`. `filter` is intended to impact the reporting of ALL downstream reporters. If you want filtering in only one, you will need to create a customized reporter. + `filter` can be used to remove potentially sensitive information (credit card numbers, social security numbers, etc.) from the log payloads before they are sent out to reporters. This setting only impacts `response` events and only if payloads are included via `requestPayload` and `responsePayload`. `filter` is intended to impact the reporting of ALL downstream reporters. If you want filtering in only one, you will need to create a customized reporter. The filtering is done recursively so if you want to "censor" `ccn`, anywhere `ccn` appears in request or response bodies will be "censor"ed. Currently, you can only filter leaf nodes; nothing with children. ## Reporter Interface diff --git a/lib/utils.js b/lib/utils.js index 64e88a9..0203326 100755 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,6 @@ // Load modules var Hoek = require('hoek'); +var Traverse = require('traverse'); // Declare internals @@ -76,35 +77,34 @@ exports.GreatResponse = function (request, options, filterRules) { var req = request.raw.req; var res = request.raw.res; - var replacer = function (match, group1) { + var replacer = function (match, group) { - return (new Array(group1.length + 1).join('X')); + return (new Array(group.length + 1).join('X')); }; var applyFilter = function (data) { - for (var key in data) { - if (typeof data[key] === 'object') { - return applyFilter(data[key]); - } - - // there is a filer for this key, so we are going to update the data - if (filterRules[key]) { - var filter = filterRules[key].toLowerCase(); - - if (filter === 'censor') { - data[key] = ('' + data[key]).replace(/./gi, 'X'); - } - else if (filter === 'remove') { - delete data[key]; - } - // Means this is a string that needs to be turned into a RegEx - else { - var regex = new RegExp(filter); - data[key] = ('' + data[key]).replace(regex, replacer); + Traverse(data).forEach(function (value) { + + if (this.isLeaf) { + if (filterRules[this.key] || filterRules[this.parent.key]) { + + var filter = (filterRules[this.key] || filterRules[this.parent.key]).toLowerCase(); + + if (filter === 'censor') { + this.update(('' + value).replace(/./g, 'X')); + } + else if (filter === 'remove') { + this.delete(); + } + // Means this is a string that needs to be turned into a RegEx + else { + var regex = new RegExp(filter); + this.update(('' + value).replace(regex, replacer)); + } } } - } + }); }; this.event = 'response'; @@ -139,7 +139,7 @@ exports.GreatResponse = function (request, options, filterRules) { } if (Object.keys(filterRules).length) { - + applyFilter(this.requestPayload); applyFilter(this.responsePayload); } diff --git a/package.json b/package.json index 8ffd9c3..33fc412 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,10 @@ "node": ">=0.10.x" }, "dependencies": { - "items": "1.x.x", "hoek": "2.x.x", + "items": "1.x.x", "joi": "5.x.x", + "traverse": "0.6.6", "wreck": "5.4.x" }, "peerDependencies": { diff --git a/test/monitor.js b/test/monitor.js index 90afbe5..104256d 100644 --- a/test/monitor.js +++ b/test/monitor.js @@ -488,13 +488,22 @@ describe('good', function () { reply({ first: 'John', last: 'Smith', - ssn: 'ABCDEFG', ccn: '9999999999', + line: 'foo', userId: 555645465, address: { - street: '123 Main Street', + line: ['123 Main street', 'Apt 200', 'Suite 100'], + bar: { + line: '123', + extra: 123456 + }, city: 'Pittsburgh', - last: 'Jones' + last: 'Jones', + foo: [{ + email: 'adam@hapijs.com', + baz: 'another string', + line: 'another string' + }] } }); } @@ -508,14 +517,13 @@ describe('good', function () { requestPayload: true, responsePayload: true, filter: { - ssn: 'remove', last: 'censor', password: 'censor', email: 'remove', ccn: '(\\d{4})$', userId: '(645)', - street: 'censor', - city: '(\\w?)' + city: '(\\w?)', + line: 'censor' } } }; @@ -547,10 +555,19 @@ describe('good', function () { last: 'XXXXX', ccn: '999999XXXX', userId: '555XXX465', + line: 'XXX', address: { - street: 'XXXXXXXXXXXXXXX', + line: ['XXXXXXXXXXXXXXX', 'XXXXXXX', 'XXXXXXXXX'], + bar: { + line: 'XXX', + extra: 123456 + }, city: 'Xittsburgh', - last: 'XXXXX' + last: 'XXXXX', + foo: [{ + baz: 'another string', + line: 'XXXXXXXXXXXXXX' + }] } }); done();