Skip to content

Commit

Permalink
Mask sensitive information when logging (#1790)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco129 authored and drew-gross committed May 17, 2016
1 parent b40e166 commit 4096518
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
55 changes: 55 additions & 0 deletions spec/FileLoggerAdapter.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
'use strict';

var FileLoggerAdapter = require('../src/Adapters/Logger/FileLoggerAdapter').FileLoggerAdapter;
var Parse = require('parse/node').Parse;
var request = require('request');

describe('info logs', () => {

Expand Down Expand Up @@ -45,3 +48,55 @@ describe('error logs', () => {
});
});
});

describe('verbose logs', () => {

it("mask sensitive information in _User class", (done) => {
let customConfig = Object.assign({}, defaultConfiguration, {verbose: true});
setServerConfiguration(customConfig);
createTestUser().then(() => {
let fileLoggerAdapter = new FileLoggerAdapter();
return fileLoggerAdapter.query({
from: new Date(Date.now() - 500),
size: 100,
level: 'verbose'
});
}).then((results) => {
expect(results[1].message.includes('"password": "********"')).toEqual(true);
var headers = {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest'
};
request.get({
headers: headers,
url: 'http://localhost:8378/1/login?username=test&password=moon-y'
}, (error, response, body) => {
let fileLoggerAdapter = new FileLoggerAdapter();
return fileLoggerAdapter.query({
from: new Date(Date.now() - 500),
size: 100,
level: 'verbose'
}).then((results) => {
expect(results[1].message.includes('password=********')).toEqual(true);
done();
});
});
});
});

it("should not mask information in non _User class", (done) => {
let obj = new Parse.Object('users');
obj.set('password', 'pw');
obj.save().then(() => {
let fileLoggerAdapter = new FileLoggerAdapter();
return fileLoggerAdapter.query({
from: new Date(Date.now() - 500),
size: 100,
level: 'verbose'
});
}).then((results) => {
expect(results[1].message.includes('"password": "pw"')).toEqual(true);
done();
});
});
});
36 changes: 34 additions & 2 deletions src/PromiseRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// components that external developers may be modifying.

import express from 'express';
import url from 'url';
import log from './logger';

export default class PromiseRouter {
Expand Down Expand Up @@ -154,8 +155,8 @@ export default class PromiseRouter {
function makeExpressHandler(promiseHandler) {
return function(req, res, next) {
try {
log.verbose(req.method, req.originalUrl, req.headers,
JSON.stringify(req.body, null, 2));
log.verbose(req.method, maskSensitiveUrl(req), req.headers,
JSON.stringify(maskSensitiveBody(req), null, 2));
promiseHandler(req).then((result) => {
if (!result.response && !result.location && !result.text) {
log.error('the handler did not include a "response" or a "location" field');
Expand Down Expand Up @@ -194,3 +195,34 @@ function makeExpressHandler(promiseHandler) {
}
}
}

function maskSensitiveBody(req) {
let maskBody = Object.assign({}, req.body);
let shouldMaskBody = (req.method === 'POST' && req.originalUrl.endsWith('/users')
&& !req.originalUrl.includes('classes')) ||
(req.method === 'PUT' && /users\/\w+$/.test(req.originalUrl)
&& !req.originalUrl.includes('classes')) ||
(req.originalUrl.includes('classes/_User'));
if (shouldMaskBody) {
for (let key of Object.keys(maskBody)) {
if (key == 'password') {
maskBody[key] = '********';
break;
}
}
}
return maskBody;
}

function maskSensitiveUrl(req) {
let maskUrl = req.originalUrl.toString();
let shouldMaskUrl = req.method === 'GET' && req.originalUrl.includes('/login')
&& !req.originalUrl.includes('classes');
if (shouldMaskUrl) {
let password = url.parse(req.originalUrl, true).query.password;
if (password) {
maskUrl = maskUrl.replace('password=' + password, 'password=********')
}
}
return maskUrl;
}

0 comments on commit 4096518

Please sign in to comment.