Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/cli-repl/src/arg-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ const OPTIONS = {
'nodb',
'norc',
'quiet',
'redactInfo',
'retryWrites',
'shell',
'smokeTests',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-repl/src/cli-repl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ describe('CliRepl', () => {

it('returns the list of available config options when asked to', () => {
expect(cliRepl.listConfigOptions()).to.deep.equal([
'batchSize', 'enableTelemetry', 'inspectCompact', 'inspectDepth', 'historyLength', 'showStackTraces'
'batchSize', 'enableTelemetry', 'inspectCompact', 'inspectDepth', 'historyLength', 'showStackTraces', 'redactHistory'
]);
});

Expand Down
51 changes: 51 additions & 0 deletions packages/cli-repl/src/mongosh-repl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,57 @@ describe('MongoshNodeRepl', () => {
input.write(`${arrowUp}`);
await tick();
});

context('redaction', () => {
it('removes sensitive commands by default', async() => {
input.write('connect\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('connection\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('db.test.insert({ email: "foo@example.org" })\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');

expect(getHistory()).to.deep.equal([
'db.test.insert({ email: "foo@example.org" })',
'connection' // connection is okay, connect is considered sensitive
]);
});

it('keeps sensitive commands when asked to', async() => {
input.write('config.set("redactHistory", "keep");\n');
await tick();
input.write('connect\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('connection\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('db.test.insert({ email: "foo@example.org" })\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');

expect(getHistory()).to.deep.equal([
'db.test.insert({ email: "foo@example.org" })',
'connection',
'connect',
'config.set("redactHistory", "keep");'
]);
});

it('removes other sensitive data when asked to', async() => {
input.write('config.set("redactHistory", "remove-redact");\n');
await tick();
input.write('connect\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('connection\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');
input.write('db.test.insert({ email: "foo@example.org" })\n');
await once(mongoshRepl.runtimeState().repl, 'flushHistory');

expect(getHistory()).to.deep.equal([
'db.test.insert({ email: "<email>" })',
'connection',
'config.set("redactHistory", "remove-redact");'
]);
});
});
});
}
});
Expand Down
21 changes: 12 additions & 9 deletions packages/cli-repl/src/mongosh-repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { LineByLineInput } from './line-by-line-input';
import { LogEntry, parseAnyLogEntry } from './log-entry';

export type MongoshCliOptions = ShellCliOptions & {
redactInfo?: boolean;
quiet?: boolean;
};

Expand Down Expand Up @@ -110,7 +109,7 @@ class MongoshNodeRepl implements EvaluationListener {
started = false;
showStackTraces = false;
loadNestingLevel = 0;

redactHistory: 'keep' | 'remove' | 'remove-redact' = 'remove';

constructor(options: MongoshNodeReplOptions) {
this.input = options.input;
Expand Down Expand Up @@ -261,15 +260,16 @@ class MongoshNodeRepl implements EvaluationListener {
(repl as Mutable<typeof repl>).line = '';

const historyFile = this.ioProvider.getHistoryFilePath();
const { redactInfo } = this.shellCliOptions;
try {
await promisify(repl.setupHistory).call(repl, historyFile);
// repl.history is an array of previous commands. We need to hijack the
// value we just typed, and shift it off the history array if the info is
// sensitive.
repl.on('flushHistory', function() {
const history: string[] = (repl as any).history;
changeHistory(history, redactInfo);
repl.on('flushHistory', () => {
if (this.redactHistory !== 'keep') {
const history: string[] = (repl as any).history;
changeHistory(history, this.redactHistory === 'remove-redact');
}
});
// We also want to group multiline history entries and .editor input into
// a single entry per evaluation, so that arrow-up functionality
Expand Down Expand Up @@ -603,13 +603,16 @@ class MongoshNodeRepl implements EvaluationListener {
(this.runtimeState().repl as any).historySize = value;
}
if (key === 'inspectCompact') {
this.inspectCompact = value as number | boolean;
this.inspectCompact = value as CliUserConfig['inspectCompact'];
}
if (key === 'inspectDepth') {
this.inspectDepth = +value;
this.inspectDepth = value as CliUserConfig['inspectDepth'];
}
if (key === 'showStackTraces') {
this.showStackTraces = !!value;
this.showStackTraces = value as CliUserConfig['showStackTraces'];
}
if (key === 'redactHistory') {
this.redactHistory = value as CliUserConfig['redactHistory'];
}
}
return result;
Expand Down
1 change: 0 additions & 1 deletion packages/service-provider-core/src/cli-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default interface CliOptions {
password?: string;
port?: string;
quiet?: boolean;
redactInfo?: boolean;
retryWrites?: boolean;
shell?: boolean;
tls?: boolean;
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ describe('config validation', () => {
expect(await validate('showStackTraces', -1)).to.equal('showStackTraces must be a boolean');
expect(await validate('showStackTraces', false)).to.equal(null);
expect(await validate('showStackTraces', true)).to.equal(null);
expect(await validate('redactHistory', 'foo')).to.equal("redactHistory must be one of 'keep', 'remove', or 'remove-redact'");
expect(await validate('redactHistory', -1)).to.equal("redactHistory must be one of 'keep', 'remove', or 'remove-redact'");
expect(await validate('redactHistory', false)).to.equal("redactHistory must be one of 'keep', 'remove', or 'remove-redact'");
expect(await validate('redactHistory', 'keep')).to.equal(null);
expect(await validate('redactHistory', 'remove')).to.equal(null);
expect(await validate('redactHistory', 'remove-redact')).to.equal(null);
expect(await validate('batchSize', 'foo')).to.equal('batchSize must be a positive integer');
expect(await validate('batchSize', -1)).to.equal('batchSize must be a positive integer');
expect(await validate('batchSize', 0)).to.equal('batchSize must be a positive integer');
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ export class CliUserConfig extends ShellUserConfig {
inspectDepth = 6;
historyLength = 1000;
showStackTraces = false;
redactHistory: 'keep' | 'remove' | 'remove-redact' = 'remove';
}

export class CliUserConfigValidator extends ShellUserConfigValidator {
Expand All @@ -267,6 +268,11 @@ export class CliUserConfigValidator extends ShellUserConfigValidator {
return `${key} must be a boolean`;
}
return null;
case 'redactHistory':
if (value !== 'keep' && value !== 'remove' && value !== 'remove-redact') {
return `${key} must be one of 'keep', 'remove', or 'remove-redact'`;
}
return null;
default:
return super.validate(key as keyof ShellUserConfig, value as any);
}
Expand Down