Obfuscate password name value pairs in log strings (#2755)

* Unit test to catch password in logs.

* Add clean to logger controller to "look for" password strings in log messages.
This commit is contained in:
Florent Vilmart
2016-09-20 21:45:24 -04:00
committed by GitHub
parent 5feceaa6d6
commit ad707457be
4 changed files with 33 additions and 7 deletions

View File

@@ -55,6 +55,24 @@ describe("Cloud Code Logger", () => {
}); });
}); });
it('trigger should obfuscate password', done => {
const logController = new LoggerController(new WinstonLoggerAdapter());
Parse.Cloud.beforeSave(Parse.User, (req, res) => {
res.success(req.object);
});
Parse.User.signUp('tester123', 'abc')
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
.then((res) => {
const entry = res[0];
expect(entry.message).not.toMatch(/password":"abc/);
expect(entry.message).toMatch(/\*\*\*\*\*\*\*\*/);
done();
})
.then(null, e => done.fail(e));
});
it("should expose log to trigger", (done) => { it("should expose log to trigger", (done) => {
var logController = new LoggerController(new WinstonLoggerAdapter()); var logController = new LoggerController(new WinstonLoggerAdapter());

View File

@@ -61,6 +61,14 @@ export class LoggerController extends AdaptableController {
return null; return null;
} }
cleanAndTruncateLogMessage(string) {
return this.truncateLogMessage(this.cleanLogMessage(string));
}
cleanLogMessage(string) {
return string.replace(/password":"[^"]*"/g, 'password":"********"');
}
truncateLogMessage(string) { truncateLogMessage(string) {
if (string && string.length > LOG_STRING_TRUNCATE_LENGTH) { if (string && string.length > LOG_STRING_TRUNCATE_LENGTH) {
const truncated = string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker; const truncated = string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker;

View File

@@ -125,10 +125,10 @@ export class FunctionsRouter extends PromiseRouter {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
const userString = (req.auth && req.auth.user) ? req.auth.user.id : undefined; const userString = (req.auth && req.auth.user) ? req.auth.user.id : undefined;
const cleanInput = logger.truncateLogMessage(JSON.stringify(params)); const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(params));
var response = FunctionsRouter.createResponseObject((result) => { var response = FunctionsRouter.createResponseObject((result) => {
try { try {
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result)); const cleanResult = logger.cleanAndTruncateLogMessage(JSON.stringify(result.response.result));
logger.info(`Ran cloud function ${functionName} for user ${userString} ` logger.info(`Ran cloud function ${functionName} for user ${userString} `
+ `with:\n Input: ${cleanInput }\n Result: ${cleanResult }`, { + `with:\n Input: ${cleanInput }\n Result: ${cleanResult }`, {
functionName, functionName,

View File

@@ -212,7 +212,7 @@ function userIdForLog(auth) {
} }
function logTriggerAfterHook(triggerType, className, input, auth) { function logTriggerAfterHook(triggerType, className, input, auth) {
const cleanInput = logger.truncateLogMessage(JSON.stringify(input)); const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}`, { logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}`, {
className, className,
triggerType, triggerType,
@@ -221,8 +221,8 @@ function logTriggerAfterHook(triggerType, className, input, auth) {
} }
function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth) { function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth) {
const cleanInput = logger.truncateLogMessage(JSON.stringify(input)); const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
const cleanResult = logger.truncateLogMessage(JSON.stringify(result)); const cleanResult = logger.cleanAndTruncateLogMessage(JSON.stringify(result));
logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Result: ${cleanResult}`, { logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Result: ${cleanResult}`, {
className, className,
triggerType, triggerType,
@@ -231,7 +231,7 @@ function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth
} }
function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) { function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) {
const cleanInput = logger.truncateLogMessage(JSON.stringify(input)); const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
logger.error(`${triggerType} failed for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Error: ${JSON.stringify(error)}`, { logger.error(`${triggerType} failed for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Error: ${JSON.stringify(error)}`, {
className, className,
triggerType, triggerType,