From d40ced693f070bb4e02aca82d1b2c2625eb98610 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Tue, 2 Mar 2021 16:37:31 +0200 Subject: [PATCH 01/11] Implemented & exposed obfuscateSecret and obfuscatePii methods --- package-lock.json | 2 +- package.json | 2 +- src/index.ts | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 156d45c..10f836c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.0.1", + "version": "3.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7b32bff..3121619 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.0.1", + "version": "3.0.2", "description": "Easy to use logger with several levels of logging as well as different adapters that can be used separately or in combinations", "author": "Luckbox", "license": "ISC", diff --git a/src/index.ts b/src/index.ts index ff0b028..67a27cb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,14 @@ import { LoggerFactory, Adapters, LogLevels, ConsoleAdapterSettings, SentryAdapterSettings } from './LoggerFactory'; import { Logger } from './Logger'; +function obfuscateSecret(value: string | number) { + return `[SECRET]${value}[/SECRET]`; +} + +function obfuscatePii(value: string | number) { + return `[PII]${value}[/PII]`; +} + export { LoggerFactory, Adapters, @@ -8,4 +16,6 @@ export { Logger, ConsoleAdapterSettings, SentryAdapterSettings, + obfuscateSecret, + obfuscatePii, }; From 154ab12271d0a8e81796fb1c9e3c570feb155f9a Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Tue, 2 Mar 2021 16:42:16 +0200 Subject: [PATCH 02/11] Bumped minor version instead of patch --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10f836c..d3006a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.0.2", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3121619..d45fa4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@luckbox/logger-factory", - "version": "3.0.2", + "version": "3.1.0", "description": "Easy to use logger with several levels of logging as well as different adapters that can be used separately or in combinations", "author": "Luckbox", "license": "ISC", From ff63a60c872429b8545b28b449a7cffbbcb0d528 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:02:48 +0200 Subject: [PATCH 03/11] Bumped lodash version. --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3006a4..29d6503 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4834,9 +4834,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.memoize": { "version": "4.1.2", diff --git a/package.json b/package.json index d45fa4a..fab45f0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@sentry/node": "^6.0.4", - "lodash": "^4.17.20" + "lodash": "^4.17.21" }, "devDependencies": { "@luckbox/eslint-rules": "^4.0.5", From e5b243bdd24b1340018ec3886c59b57c9d32bedd Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:03:06 +0200 Subject: [PATCH 04/11] Replaced exported versions with an Obfuscator class. --- src/Obfuscator.ts | 48 +++++++++++++++++++++++++ src/index.ts | 12 ++----- src/tests/unit-tests/Obfuscator.test.ts | 30 ++++++++++++++++ 3 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 src/Obfuscator.ts create mode 100644 src/tests/unit-tests/Obfuscator.test.ts diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts new file mode 100644 index 0000000..fda5261 --- /dev/null +++ b/src/Obfuscator.ts @@ -0,0 +1,48 @@ +import lodash from 'lodash'; + +class Obfuscator { + public obfuscateObject(obj: unknown, paths: Array, tag: string): Record { + const upperCasedTag = tag.toUpperCase(); + const clonedObj = lodash.cloneDeep(obj); + const allPaths: Array = this.collectPaths(obj); + + for (const path of allPaths) { + if (paths.some((propPath) => new RegExp(propPath).test(path))) { + const rawValue = lodash.get(clonedObj, path); + const transformedValue = `[${upperCasedTag}]${rawValue}[/${upperCasedTag}]`; + + lodash.set(clonedObj, path, transformedValue); + } + } + + return clonedObj; + } + + public obfuscateString(value: string, tag: string): string { + const upperCasedTag = tag.toUpperCase(); + return `[${upperCasedTag}]${value}[/${upperCasedTag}]`; + } + + private collectPaths(input: any, currentPath?: string) { + const paths = []; + + if (lodash.isPlainObject(input)) { + for (const key in input) { + const fullPath: string = this.buildPath(key, currentPath); + const value = input[key]; + + paths.push(fullPath, ...this.collectPaths(value).map((nestedPath) => this.buildPath(nestedPath, fullPath))); + } + } + + return paths; + } + + private buildPath(propPath: string, basePath?: string) { + return basePath === undefined ? String(propPath) : `${basePath}.${propPath}`; + } +} + +export { + Obfuscator, +}; diff --git a/src/index.ts b/src/index.ts index 67a27cb..5b86828 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,6 @@ import { LoggerFactory, Adapters, LogLevels, ConsoleAdapterSettings, SentryAdapterSettings } from './LoggerFactory'; import { Logger } from './Logger'; - -function obfuscateSecret(value: string | number) { - return `[SECRET]${value}[/SECRET]`; -} - -function obfuscatePii(value: string | number) { - return `[PII]${value}[/PII]`; -} +import { Obfuscator } from './Obfuscator'; export { LoggerFactory, @@ -16,6 +9,5 @@ export { Logger, ConsoleAdapterSettings, SentryAdapterSettings, - obfuscateSecret, - obfuscatePii, + Obfuscator, }; diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts new file mode 100644 index 0000000..b0e93cb --- /dev/null +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -0,0 +1,30 @@ +import { Obfuscator } from '../../Obfuscator'; + +describe('Obfuscator', () => { + const obfuscator = new Obfuscator(); + + describe('obfuscateString', () => { + it('should wrap the provided tag around the string that needs to be obfuscated', () => { + expect(obfuscator.obfuscateString('string', 'pii')).toEqual('[PII]string[/PII]'); + }); + }); + + describe('obfuscateObject', () => { + it('should wrap the provided tag around root-level elements in object', () => { + const originalObject = { name: 'Pencho' }; + const obfuscatedObject = { name: '[PII]Pencho[/PII]' }; + expect(obfuscator.obfuscateObject(originalObject, ['name'], 'pii')).toEqual(obfuscatedObject); + }); + + it('should wrap the provided tag around nested elements in object', () => { + const originalObject = { id: 1, data: { name: 'Gosho', email: 'email@example.com' } }; + const obfuscatedObject = { id: 1, data: { name: '[PII]Gosho[/PII]', email: '[PII]email@example.com[/PII]' } }; + expect(obfuscator.obfuscateObject(originalObject, ['data.name', 'data.email'], 'pii')).toEqual(obfuscatedObject); + }); + + it('should NOT wrap the provided tag around elements that are not specified for obfuscating in object', () => { + const originalObject = { favouriteColor: 'red', nested: { field: 'value' } }; + expect(obfuscator.obfuscateObject(originalObject, ['name'], 'pii')).toEqual(originalObject); + }); + }); +}); From e711d13f93bfe1353d7ebfb200f7edf4e517e870 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:30:57 +0200 Subject: [PATCH 05/11] Allowed obfuscation to be with a different tag for each of the paths. --- src/Obfuscator.ts | 36 ++++++++++++++++++++++--- src/tests/unit-tests/Obfuscator.test.ts | 8 +++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index fda5261..1c34032 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -1,14 +1,35 @@ import lodash from 'lodash'; +enum Tag { + PII = 'pii', + SECRET = 'secret' +} + class Obfuscator { - public obfuscateObject(obj: unknown, paths: Array, tag: string): Record { - const upperCasedTag = tag.toUpperCase(); + public obfuscateObject(obj: unknown, obfuscateSettings: Array<[string, Tag]>): Record { const clonedObj = lodash.cloneDeep(obj); const allPaths: Array = this.collectPaths(obj); + const pathToTagMap = new Map(); + const allPathsToObfuscate = []; + + for (const anObfuscateSetting of obfuscateSettings) { + pathToTagMap.set(anObfuscateSetting[0], anObfuscateSetting[1]); + allPathsToObfuscate.push(anObfuscateSetting[0]); + } + for (const path of allPaths) { - if (paths.some((propPath) => new RegExp(propPath).test(path))) { + const actualPath = path[0]; + if (allPathsToObfuscate.some((propPath) => new RegExp(propPath[0]).test(actualPath))) { const rawValue = lodash.get(clonedObj, path); + + let upperCasedTag; + try { + upperCasedTag = this.determineTag(pathToTagMap, path); + } catch (ex) { + continue; + } + const transformedValue = `[${upperCasedTag}]${rawValue}[/${upperCasedTag}]`; lodash.set(clonedObj, path, transformedValue); @@ -41,8 +62,17 @@ class Obfuscator { private buildPath(propPath: string, basePath?: string) { return basePath === undefined ? String(propPath) : `${basePath}.${propPath}`; } + + private determineTag(pathToTagMap: any, path: string) { + const tag = pathToTagMap.get(path); + if (!tag) { + throw new Error(); + } + return tag.toUpperCase(); + } } export { Obfuscator, + Tag, }; diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts index b0e93cb..c8f5021 100644 --- a/src/tests/unit-tests/Obfuscator.test.ts +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -1,4 +1,4 @@ -import { Obfuscator } from '../../Obfuscator'; +import { Obfuscator, Tag } from '../../Obfuscator'; describe('Obfuscator', () => { const obfuscator = new Obfuscator(); @@ -13,18 +13,18 @@ describe('Obfuscator', () => { it('should wrap the provided tag around root-level elements in object', () => { const originalObject = { name: 'Pencho' }; const obfuscatedObject = { name: '[PII]Pencho[/PII]' }; - expect(obfuscator.obfuscateObject(originalObject, ['name'], 'pii')).toEqual(obfuscatedObject); + expect(obfuscator.obfuscateObject(originalObject, [['name', Tag.PII]])).toEqual(obfuscatedObject); }); it('should wrap the provided tag around nested elements in object', () => { const originalObject = { id: 1, data: { name: 'Gosho', email: 'email@example.com' } }; const obfuscatedObject = { id: 1, data: { name: '[PII]Gosho[/PII]', email: '[PII]email@example.com[/PII]' } }; - expect(obfuscator.obfuscateObject(originalObject, ['data.name', 'data.email'], 'pii')).toEqual(obfuscatedObject); + expect(obfuscator.obfuscateObject(originalObject, [['data.name', Tag.PII], ['data.email', Tag.PII]])).toEqual(obfuscatedObject); }); it('should NOT wrap the provided tag around elements that are not specified for obfuscating in object', () => { const originalObject = { favouriteColor: 'red', nested: { field: 'value' } }; - expect(obfuscator.obfuscateObject(originalObject, ['name'], 'pii')).toEqual(originalObject); + expect(obfuscator.obfuscateObject(originalObject, [['name', Tag.PII]])).toEqual(originalObject); }); }); }); From 6e3bfc27867c433b76985386812078fea75f146b Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:33:01 +0200 Subject: [PATCH 06/11] Code readability improvements. --- src/Obfuscator.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 1c34032..5b6f7b7 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -6,9 +6,9 @@ enum Tag { } class Obfuscator { - public obfuscateObject(obj: unknown, obfuscateSettings: Array<[string, Tag]>): Record { - const clonedObj = lodash.cloneDeep(obj); - const allPaths: Array = this.collectPaths(obj); + public obfuscateObject(object: unknown, obfuscateSettings: Array<[string, Tag]>): Record { + const clonedObj = lodash.cloneDeep(object); + const allPaths: Array = this.collectPaths(object); const pathToTagMap = new Map(); const allPathsToObfuscate = []; @@ -39,7 +39,7 @@ class Obfuscator { return clonedObj; } - public obfuscateString(value: string, tag: string): string { + public obfuscateString(value: string, tag: Tag): string { const upperCasedTag = tag.toUpperCase(); return `[${upperCasedTag}]${value}[/${upperCasedTag}]`; } From c0d90bbcb06ebe2a6a21bf13b8eae875f5dfbe69 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:51:41 +0200 Subject: [PATCH 07/11] obj is `Record` --- src/Obfuscator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 5b6f7b7..789203a 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -6,7 +6,7 @@ enum Tag { } class Obfuscator { - public obfuscateObject(object: unknown, obfuscateSettings: Array<[string, Tag]>): Record { + public obfuscateObject(object: Record, obfuscateSettings: Array<[string, Tag]>): Record { const clonedObj = lodash.cloneDeep(object); const allPaths: Array = this.collectPaths(object); From 3ac170d77ec8e04e136c3a799c979220884754f5 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 15:56:25 +0200 Subject: [PATCH 08/11] Code readability improvements. --- src/Obfuscator.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 789203a..40e8b90 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -1,8 +1,8 @@ import lodash from 'lodash'; enum Tag { - PII = 'pii', - SECRET = 'secret' + PII = 'PII', + SECRET = 'SECRET' } class Obfuscator { @@ -30,9 +30,7 @@ class Obfuscator { continue; } - const transformedValue = `[${upperCasedTag}]${rawValue}[/${upperCasedTag}]`; - - lodash.set(clonedObj, path, transformedValue); + lodash.set(clonedObj, path, this.obfuscateString(rawValue, upperCasedTag)); } } @@ -68,7 +66,7 @@ class Obfuscator { if (!tag) { throw new Error(); } - return tag.toUpperCase(); + return tag; } } From 5ba9a8b81c5ee76d205863ae0447100d38c516ff Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 16:01:32 +0200 Subject: [PATCH 09/11] Fixed test not properly using correct type. --- src/tests/unit-tests/Obfuscator.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/unit-tests/Obfuscator.test.ts b/src/tests/unit-tests/Obfuscator.test.ts index c8f5021..70e164e 100644 --- a/src/tests/unit-tests/Obfuscator.test.ts +++ b/src/tests/unit-tests/Obfuscator.test.ts @@ -5,7 +5,7 @@ describe('Obfuscator', () => { describe('obfuscateString', () => { it('should wrap the provided tag around the string that needs to be obfuscated', () => { - expect(obfuscator.obfuscateString('string', 'pii')).toEqual('[PII]string[/PII]'); + expect(obfuscator.obfuscateString('string', Tag.PII)).toEqual('[PII]string[/PII]'); }); }); From 3beb1eaf2643090ad4bc39c16aaa86b00d8e48f0 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 16:42:44 +0200 Subject: [PATCH 10/11] Cleaned up redundant exception throwing. --- src/Obfuscator.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Obfuscator.ts b/src/Obfuscator.ts index 40e8b90..58057a4 100644 --- a/src/Obfuscator.ts +++ b/src/Obfuscator.ts @@ -23,14 +23,11 @@ class Obfuscator { if (allPathsToObfuscate.some((propPath) => new RegExp(propPath[0]).test(actualPath))) { const rawValue = lodash.get(clonedObj, path); - let upperCasedTag; - try { - upperCasedTag = this.determineTag(pathToTagMap, path); - } catch (ex) { + const tag = this.determineTag(pathToTagMap, path); + if (!tag) { continue; } - - lodash.set(clonedObj, path, this.obfuscateString(rawValue, upperCasedTag)); + lodash.set(clonedObj, path, this.obfuscateString(rawValue, tag)); } } @@ -63,9 +60,6 @@ class Obfuscator { private determineTag(pathToTagMap: any, path: string) { const tag = pathToTagMap.get(path); - if (!tag) { - throw new Error(); - } return tag; } } From 4056950552b75b82805185082851b18f44a08ef9 Mon Sep 17 00:00:00 2001 From: Veselin Bakov Date: Mon, 8 Mar 2021 16:57:47 +0200 Subject: [PATCH 11/11] Exported ObfuscatorTag as well. --- src/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 5b86828..48b348d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import { LoggerFactory, Adapters, LogLevels, ConsoleAdapterSettings, SentryAdapterSettings } from './LoggerFactory'; import { Logger } from './Logger'; -import { Obfuscator } from './Obfuscator'; +import { Obfuscator, Tag } from './Obfuscator'; export { LoggerFactory, @@ -10,4 +10,5 @@ export { ConsoleAdapterSettings, SentryAdapterSettings, Obfuscator, + Tag as ObfuscatorTag, };