UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

311 lines 16.3 kB
// SPDX-License-Identifier: Apache-2.0 import { expect } from 'chai'; import { describe, it } from 'mocha'; import { SensitiveDataRedactor } from '../../../../src/core/util/sensitive-data-redactor.js'; describe('SensitiveDataRedactor', () => { describe('isSensitiveKey', () => { it('should detect "password" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('password')).to.be.true; }); it('should detect "global.operator.password" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('global.operator.password')).to.be.true; }); it('should detect "secret" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('db.secret')).to.be.true; }); it('should detect "token" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('auth-token')).to.be.true; }); it('should detect "key" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('my_key')).to.be.true; }); it('should detect "credential" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('user-credential')).to.be.true; }); it('should detect "auth" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('auth')).to.be.true; }); it('should detect "api_key" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('api_key')).to.be.true; }); it('should detect "apikey" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('apikey')).to.be.true; }); it('should detect "api-key" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('api-key')).to.be.true; }); it('should detect "passphrase" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('passphrase')).to.be.true; }); it('should detect "certificate" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('tls.certificate')).to.be.true; }); it('should detect "private" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('private')).to.be.true; }); it('should detect "passwd" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('db.passwd')).to.be.true; }); it('should detect "privatekey" as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('privatekey')).to.be.true; }); it('should detect "privateKey" (camelCase) as sensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('privateKey')).to.be.true; }); it('should be case-insensitive', () => { expect(SensitiveDataRedactor.isSensitiveKey('PASSWORD')).to.be.true; expect(SensitiveDataRedactor.isSensitiveKey('Secret')).to.be.true; expect(SensitiveDataRedactor.isSensitiveKey('API_KEY')).to.be.true; }); it('should not flag non-sensitive keys', () => { expect(SensitiveDataRedactor.isSensitiveKey('name')).to.be.false; expect(SensitiveDataRedactor.isSensitiveKey('namespace')).to.be.false; expect(SensitiveDataRedactor.isSensitiveKey('values')).to.be.false; expect(SensitiveDataRedactor.isSensitiveKey('replicas')).to.be.false; }); }); describe('redactArguments', () => { describe('flag-based redaction', () => { it('should redact the value after --password', () => { const arguments_ = ['--password', 'mySecret']; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['--password'], }); expect(result).to.deep.equal(['--password', '******']); }); it('should redact the value after -p', () => { const arguments_ = ['-p', 'mySecret']; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['-p'], }); expect(result).to.deep.equal(['-p', '******']); }); it('should handle flag at end of array without a value', () => { const arguments_ = ['--password']; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['--password'], }); expect(result).to.deep.equal(['--password']); }); it('should redact multiple flag-based values', () => { const arguments_ = ['--password', 'secret1', '-p', 'secret2']; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['--password', '-p'], }); expect(result).to.deep.equal(['--password', '******', '-p', '******']); }); }); describe('set-style redaction', () => { it('should redact sensitive key=value after --set', () => { const arguments_ = ['--set', 'global.password=mySecret']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'global.password=******']); }); it('should redact sensitive key=value after --set-string', () => { const arguments_ = ['--set-string', 'auth-token=abc123']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set-string'], }); expect(result).to.deep.equal(['--set-string', 'auth-token=******']); }); it('should redact sensitive key=value after --set-file', () => { const arguments_ = ['--set-file', 'tls.certificate=/path/to/cert']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set-file'], }); expect(result).to.deep.equal(['--set-file', 'tls.certificate=******']); }); it('should not redact non-sensitive key=value after --set', () => { const arguments_ = ['--set', 'replicas=3']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'replicas=3']); }); it('should pass through --set value without = sign unchanged', () => { const arguments_ = ['--set', 'someValue']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'someValue']); }); it('should handle --set at end of array', () => { const arguments_ = ['--set']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set']); }); }); describe('inline key=value redaction', () => { it('should redact inline sensitive key=value args', () => { const arguments_ = ['some-token=abc', 'api_key=xyz']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['some-token=******', 'api_key=******']); }); it('should not redact inline non-sensitive key=value args', () => { const arguments_ = ['name=myApp', 'replicas=3']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['name=myApp', 'replicas=3']); }); }); describe('regex dynamic matching', () => { it('should redact credential via regex', () => { const arguments_ = ['--set', 'db.credential=secretValue']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'db.credential=******']); }); it('should redact passphrase via regex', () => { const arguments_ = ['ssh.passphrase=myPhrase']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['ssh.passphrase=******']); }); it('should redact api-key via regex', () => { const arguments_ = ['api-key=abc123']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['api-key=******']); }); it('should redact certificate via regex', () => { const arguments_ = ['tls.certificate=base64data']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['tls.certificate=******']); }); it('should redact auth via regex', () => { const arguments_ = ['--set', 'global.auth=bearerXYZ']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'global.auth=******']); }); it('should redact private via regex', () => { const arguments_ = ['private=data']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['private=******']); }); it('should redact privatekey via regex', () => { const arguments_ = ['privatekey=data']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['privatekey=******']); }); }); describe('nested dot-notation key redaction', () => { it('should redact deeply nested password key', () => { const arguments_ = ['--set', 'something.something.password=123456']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'something.something.password=******']); }); it('should redact deeply nested secret key', () => { const arguments_ = ['--set', 'a.b.c.secret=topSecret']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'a.b.c.secret=******']); }); it('should redact nested privatekey', () => { const arguments_ = ['tls.privatekey=base64data']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['tls.privatekey=******']); }); it('should not redact nested non-sensitive key', () => { const arguments_ = ['--set', 'config.server.replicas=3']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--set', 'config.server.replicas=3']); }); }); describe('combined options', () => { it('should handle both flag-based and set-style redaction together', () => { const arguments_ = [ 'install', 'my-release', '--password', 's3cret', '--set', 'global.operator.password=mySecretValue', '--set', 'global.db.secret=abc123', '--namespace', 'default', ]; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['--password'], setStyleFlags: ['--set'], }); expect(result).to.deep.equal([ 'install', 'my-release', '--password', '******', '--set', 'global.operator.password=******', '--set', 'global.db.secret=******', '--namespace', 'default', ]); }); }); describe('edge cases', () => { it('should return empty array for empty input', () => { const result = SensitiveDataRedactor.redactArguments([]); expect(result).to.deep.equal([]); }); it('should pass through args with no sensitive data unchanged', () => { const arguments_ = ['install', 'my-release', '--namespace', 'default', '--values', 'values.yaml']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['install', 'my-release', '--namespace', 'default', '--values', 'values.yaml']); }); it('should use default options when none provided', () => { const arguments_ = ['password=secret', 'name=test']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['password=******', 'name=test']); }); }); describe('composite argument splitting', () => { it('should split and redact composite arguments containing multiple key-value pairs', () => { const arguments_ = [ '--set foo.bar=false --set foo.privateKey=0x123456 --set foo.bar.password=123456', ]; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal([ '--set', 'foo.bar=false', '--set', 'foo.privateKey=******', '--set', 'foo.bar.password=******', ]); }); it('should split composite arguments with flags and values', () => { const arguments_ = ['--values values.yaml --set foo.bar=false']; const result = SensitiveDataRedactor.redactArguments(arguments_, { setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--values', 'values.yaml', '--set', 'foo.bar=false']); }); it('should handle composite arguments with password flag', () => { const arguments_ = ['--password secret123 --set foo.bar=false']; const result = SensitiveDataRedactor.redactArguments(arguments_, { flagsToRedactNextArgument: ['--password'], setStyleFlags: ['--set'], }); expect(result).to.deep.equal(['--password', '******', '--set', 'foo.bar=false']); }); it('should not split arguments that do not contain whitespace', () => { const arguments_ = ['install', 'my-release', '--namespace', 'default']; const result = SensitiveDataRedactor.redactArguments(arguments_); expect(result).to.deep.equal(['install', 'my-release', '--namespace', 'default']); }); }); }); }); //# sourceMappingURL=sensitive-data-redactor.test.js.map