You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.2 KiB

'use strict';
const Msg = require('./core/connection/msg').Msg;
const KillCursor = require('./core/connection/commands').KillCursor;
const GetMore = require('./core/connection/commands').GetMore;
const deepCopy = require('./utils').deepCopy;
/** Commands that we want to redact because of the sensitive nature of their contents */
const SENSITIVE_COMMANDS = new Set([
'authenticate',
'saslStart',
'saslContinue',
'getnonce',
'createUser',
'updateUser',
'copydbgetnonce',
'copydbsaslstart',
'copydb'
]);
const HELLO_COMMANDS = new Set(['hello', 'ismaster', 'isMaster']);
const LEGACY_FIND_QUERY_MAP = {
$query: 'filter',
$orderby: 'sort',
$hint: 'hint',
$comment: 'comment',
$maxScan: 'maxScan',
$max: 'max',
$min: 'min',
$returnKey: 'returnKey',
$showDiskLoc: 'showRecordId',
$maxTimeMS: 'maxTimeMS',
$snapshot: 'snapshot'
};
const LEGACY_FIND_OPTIONS_MAP = {
numberToSkip: 'skip',
numberToReturn: 'batchSize',
returnFieldsSelector: 'projection'
};
const OP_QUERY_KEYS = [
'tailable',
'oplogReplay',
'noCursorTimeout',
'awaitData',
'partial',
'exhaust'
];
const collectionName = command => command.ns.split('.')[1];
const shouldRedactCommand = (commandName, cmd) =>
SENSITIVE_COMMANDS.has(commandName) ||
(HELLO_COMMANDS.has(commandName) && !!cmd.speculativeAuthenticate);
/**
* Extract the actual command from the query, possibly upconverting if it's a legacy
* format
*
* @param {Object} command the command
*/
const extractCommand = command => {
let extractedCommand;
if (command instanceof GetMore) {
extractedCommand = {
getMore: deepCopy(command.cursorId),
collection: collectionName(command),
batchSize: command.numberToReturn
};
} else if (command instanceof KillCursor) {
extractedCommand = {
killCursors: collectionName(command),
cursors: deepCopy(command.cursorIds)
};
} else if (command instanceof Msg) {
extractedCommand = deepCopy(command.command);
} else if (command.query && command.query.$query) {
let result;
if (command.ns === 'admin.$cmd') {
// upconvert legacy command
result = Object.assign({}, command.query.$query);
} else {
// upconvert legacy find command
result = { find: collectionName(command) };
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
if (typeof command.query[key] !== 'undefined')
result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
});
}
Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
if (typeof command[key] !== 'undefined')
result[LEGACY_FIND_OPTIONS_MAP[key]] = deepCopy(command[key]);
});
OP_QUERY_KEYS.forEach(key => {
if (command[key]) result[key] = command[key];
});
if (typeof command.pre32Limit !== 'undefined') {
result.limit = command.pre32Limit;
}
if (command.query.$explain) {
extractedCommand = { explain: result };
} else {
extractedCommand = result;
}
} else {
extractedCommand = deepCopy(command.query || command);
}
const commandName = Object.keys(extractedCommand)[0];
return {
cmd: extractedCommand,
name: commandName,
shouldRedact: shouldRedactCommand(commandName, extractedCommand)
};
};
module.exports = {
extractCommand
};