Merge branch 'v1.2-dev' as v1.2.2 v1.2.2
authorJustin Wind <justin.wind+git@gmail.com>
Fri, 29 Oct 2021 20:45:46 +0000 (13:45 -0700)
committerJustin Wind <justin.wind+git@gmail.com>
Fri, 29 Oct 2021 20:45:46 +0000 (13:45 -0700)
CHANGELOG.md
lib/common.js
package.json
test/lib/common.js

index 33468ed846c43397ec19e64ab2d641cca5be759c..27a527a41322121696bc78226e65f20954a03d2d 100644 (file)
@@ -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
index ff68e9d7ac7b5ea5258ce1aab70cb99f991d037f..21070b8782918f267bf32e3adf96537df08e615a 100644 (file)
@@ -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,
index 3e24cfd173df873072459d0fc6bc4e449971789b..0d0e2bb89759f7781412a4eea310df70657236f5 100644 (file)
@@ -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": {
index a04bf614eeadac136f2df8ff44cf1519846d8221..bacd6be3d54d2aaa7e6b019c98e0e664050392dc 100644 (file)
@@ -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 = {