trentm / node-bunyan

a simple and fast JSON logging module for node.js services
Other
7.16k stars 515 forks source link

Sensitive data logging #591

Open shaucorp opened 6 years ago

shaucorp commented 6 years ago

I have sensitive info like password, cvv, pin. I want to exclude those params from logging. How to do it?

dnunes commented 6 years ago

You can do that with serializers, filtering out some data or even changing the data to "****" to indicate forced supression.

https://github.com/trentm/node-bunyan#requirements-for-serializers-functions

lev-kuznetsov commented 6 years ago

It doesn't seem to work for me, my serializer is never called. What am I doing wrong?

I create a logger like this:

const mask = token => {
  console.log({token})
  return typeof token === 'string' ? token.replace(/[^\.]+$/, 'REDACTED') : token
}
const log = context.log = createLogger({
  name: '_placeholder',
  level: process.env.LOG_LEVEL || 'info',
  serializers: {authorization: mask, bearer: mask, Authorization: mask}
})

and then I log like this:

console.log({properties})
log[!status ? 'error' : status < 500 ? 'info' : 'warn']({error: merge({message, ...properties}, status && {status})})

Output piped to bunyan:

{ properties:
   { reason: 'InvalidToken', authorization: 'Bearer foo.bar.baz' } }
[2018-08-14T14:37:11.775Z]  INFO: _placeholder/9920 on XXX: 
   error: {
      "message": "Invalid token",
      "reason": "InvalidToken",
      "authorization": "Bearer foo.bar.baz",
      "status": 401
    }
klaaz0r commented 5 years ago

@lev-kuznetsov You are mutating the actual token so your authorization layer breaks

shaunwarman commented 5 years ago

Yep, needed to do the same thing, here's a good example

const reqSerializer = (req) => {
  const maskHeader = '***';
  return Object.assign({}, req, {
    headers: {
      ...req.headers,
      authorization: maskHeader
    }
  });
}

logger.addSerializers({
  req: reqSerializer
});

This will create a copy of req, mask what you want (authorization header here) and pass that as req to the logger. This doesn't actually alter the req reference so you can still act on those values in code.

mikyoengine commented 5 years ago

You can also extend the existing serializer for request:

const reqSerializer = (req: Request) => {
  const maskHeader = "***";
  return Object.assign({}, stdSerializers.req(req), {
    headers: {
      ...req.headers,
      authorization: maskHeader
    }
  });
};

Kinda feel like the standard serializer should be doing best practices like this by default. LMK if a PR is welcome.