From: Justin Wind Date: Fri, 29 Oct 2021 20:45:46 +0000 (-0700) Subject: Merge branch 'v1.2-dev' as v1.2.2 X-Git-Tag: v1.2.2 X-Git-Url: http://git.squeep.com/?p=squeep-api-dingus;a=commitdiff_plain;h=47f38ca4c67e902ccef0b7114a0d144f476258bd;hp=3cf325b9e87b66e16f05c9bcae769eea72b207ed Merge branch 'v1.2-dev' as v1.2.2 --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 33468ed..27a527a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ Releases and notable changes to this project are documented here. ## [Unreleased] +## [v1.2.2] - 2021-10-29 + +### Added + +- obscure sensitive request header data when logging + ## [v1.2.1] - 2021-10-22 ### Added @@ -32,7 +38,8 @@ Releases and notable changes to this project are documented here. --- -[Unreleased]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=HEAD;hp=v1.2.1 +[Unreleased]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=HEAD;hp=v1.2.2 +[v1.2.2]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.2;hp=v1.2.1 [v1.2.1]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.1;hp=v1.2.0 [v1.2.0]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.0;hp=v1.1.0 [v1.1.0]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.1.0;hp=v1.0.0 diff --git a/lib/common.js b/lib/common.js index ff68e9d..21070b8 100644 --- a/lib/common.js +++ b/lib/common.js @@ -158,19 +158,51 @@ const pick = (obj, props) => { /** * Return a subset of a request object, suitable for logging. + * Obscures sensitive header values. * @param {http.ClientRequest} req */ const requestLogData = (req) => { - return pick(req, [ + const data = pick(req, [ 'method', 'url', 'httpVersion', 'headers', 'trailers', ]); + scrubHeaderObject(data); + return data; }; +/** + * Remove sensitive header data. + * @param {Object} data + * @param {Object} data.headers + */ +const scrubHeaderObject = (data) => { + if (data && data.headers && 'authorization' in data.headers) { + data.headers = Object.assign({}, data.headers, { + authorization: obscureAuthorizationHeader(data.headers['authorization']), + }); + } +} + + +/** + * Hide sensitive part of an Authorization header. + * @param {String} authHeader + * @returns {String} + */ +const obscureAuthorizationHeader = (authHeader) => { + if (!authHeader) { + return authHeader; + } + const space = authHeader.indexOf(' '); + // This blurs entire string if no space found, because -1. + return authHeader.slice(0, space + 1) + '*'.repeat(authHeader.length - (space + 1)); +} + + /** * Return a subset of a response object, suitable for logging. * @param {http.ServerResponse} res @@ -272,10 +304,12 @@ module.exports = { mergeEnum, nop, nullLogger, + obscureAuthorizationHeader, pick, requestId, requestLogData, responseLogData, + scrubHeaderObject, setOptions, splitFirst, unfoldHeaderLines, diff --git a/package.json b/package.json index 3e24cfd..0d0e2bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@squeep/api-dingus", - "version": "1.2.1", + "version": "1.2.2", "description": "A minimal API server framework", "main": "index.js", "scripts": { diff --git a/test/lib/common.js b/test/lib/common.js index a04bf61..bacd6be 100644 --- a/test/lib/common.js +++ b/test/lib/common.js @@ -141,6 +141,46 @@ describe('common', function () { }); }); // requestLogData + describe('obscureAuthorizationHeader', function () { + it('obscures basic data', function () { + const authHeader = 'Basic Zm9vOmJhcg=='; + const expected = 'Basic ************'; + const result = common.obscureAuthorizationHeader(authHeader); + assert.strictEqual(result, expected); + }); + it('obscures all of other types', function () { + const authHeader = 'someWeirdAuth'; + const expected = '*************'; + const result = common.obscureAuthorizationHeader(authHeader); + assert.strictEqual(result, expected); + }); + it('does nothing when empty', function () { + const authHeader = undefined; + const expected = undefined; + const result = common.obscureAuthorizationHeader(authHeader); + assert.strictEqual(result, expected); + }); + }); // obscureAuthorizationHeader + + describe('scrubHeaderObject', function () { + it('', function () { + const data = { + headers: { + 'foo': 'bar', + 'authorization': 'Basic Zm9vOmJhcg==', + }, + }; + const expected = { + headers: { + 'foo': 'bar', + 'authorization': 'Basic ************', + }, + }; + common.scrubHeaderObject(data); + assert.deepStrictEqual(data, expected); + }); + }); // scrubHeaderObject + describe('responseLogData', function () { it('gives data', function () { const res = {