diff options
-rw-r--r-- | jstests/aggregation/sources/out/bypass_doc_validation.js | 64 | ||||
-rw-r--r-- | jstests/auth/commands_builtin_roles.js | 2 | ||||
-rw-r--r-- | jstests/auth/commands_user_defined_roles.js | 4 | ||||
-rw-r--r-- | jstests/auth/lib/commands_lib.js | 195 |
4 files changed, 182 insertions, 83 deletions
diff --git a/jstests/aggregation/sources/out/bypass_doc_validation.js b/jstests/aggregation/sources/out/bypass_doc_validation.js index 3b67647ef14..41d5ac4d41d 100644 --- a/jstests/aggregation/sources/out/bypass_doc_validation.js +++ b/jstests/aggregation/sources/out/bypass_doc_validation.js @@ -55,7 +55,7 @@ }()); function assertDocValidationFailure(cmdOptions) { - targetColl.remove({}); + assert.commandWorked(targetColl.remove({})); assertErrorCode(sourceColl, [{$out: targetColl.getName()}], ErrorCodes.DocumentValidationFailure, @@ -119,7 +119,7 @@ // Test that the bypassDocumentValidation is casted to true if the value is non-boolean. (function testNonBooleanBypassDocValidationFlag() { - targetColl.remove({}); + assert.commandWorked(targetColl.remove({})); assert.commandWorked(testDB.runCommand({collMod: targetColl.getName(), validator: {a: 1}})); sourceColl.drop(); assert.commandWorked(sourceColl.insert({_id: 0, a: 1})); @@ -132,4 +132,64 @@ {bypassDocumentValidation: "false"}); assert.eq([{_id: 0, a: 3}], targetColl.find().toArray()); }()); + + // Test bypassDocumentValidation with $out to a collection in a foreign database. + (function testForeignDb() { + const foreignDB = db.getSiblingDB("foreign_db"); + const foreignColl = foreignDB.foreign_coll; + foreignColl.drop(); + assert.commandWorked( + foreignDB.createCollection(foreignColl.getName(), {validator: {a: 2}})); + + sourceColl.aggregate( + [ + {$addFields: {a: 3}}, + { + $out: { + db: foreignDB.getName(), + to: foreignColl.getName(), + mode: "replaceDocuments" + } + } + ], + {bypassDocumentValidation: true}); + assert.eq([{_id: 0, a: 3}], foreignColl.find().toArray()); + + sourceColl.aggregate( + [ + {$replaceRoot: {newRoot: {_id: 1, a: 4}}}, + { + $out: + {db: foreignDB.getName(), to: foreignColl.getName(), mode: "insertDocuments"} + } + ], + {bypassDocumentValidation: true}); + assert.eq([{_id: 0, a: 3}, {_id: 1, a: 4}], foreignColl.find().sort({_id: 1}).toArray()); + + assert.commandWorked(foreignColl.remove({})); + assertErrorCode(sourceColl, + [ + {$addFields: {a: 3}}, + { + $out: { + db: foreignDB.getName(), + to: foreignColl.getName(), + mode: "replaceDocuments" + } + } + ], + ErrorCodes.DocumentValidationFailure); + + assertErrorCode( + sourceColl, + [ + {$replaceRoot: {newRoot: {_id: 1, a: 4}}}, + { + $out: + {db: foreignDB.getName(), to: foreignColl.getName(), mode: "insertDocuments"} + } + ], + ErrorCodes.DocumentValidationFailure); + assert.eq(0, foreignColl.find().itcount()); + }()); }()); diff --git a/jstests/auth/commands_builtin_roles.js b/jstests/auth/commands_builtin_roles.js index 92a21ec4096..f309435d6d6 100644 --- a/jstests/auth/commands_builtin_roles.js +++ b/jstests/auth/commands_builtin_roles.js @@ -59,7 +59,7 @@ function testProperAuthorization(conn, t, testcase, r) { authCommandsLib.authenticatedSetup(t, runOnDb); var command = t.command; if (typeof(command) === "function") { - command = t.command(state); + command = t.command(state, testcase.commandArgs); } var res = runOnDb.runCommand(command); diff --git a/jstests/auth/commands_user_defined_roles.js b/jstests/auth/commands_user_defined_roles.js index 686d4d381e3..049034f4c86 100644 --- a/jstests/auth/commands_user_defined_roles.js +++ b/jstests/auth/commands_user_defined_roles.js @@ -41,7 +41,7 @@ function testProperAuthorization(conn, t, testcase, privileges) { var command = t.command; if (typeof(command) === "function") { - command = t.command(state); + command = t.command(state, testcase.commandArgs); } var res = runOnDb.runCommand(command); @@ -79,7 +79,7 @@ function testInsufficientPrivileges(conn, t, testcase, privileges) { var command = t.command; if (typeof(command) === "function") { - command = t.command(state); + command = t.command(state, testcase.commandArgs); } var res = runOnDb.runCommand(command); diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index b61ab47137a..0a485990027 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -79,6 +79,11 @@ privileges causes an authorization failure. If an individual privilege specifies "removeWhenTestingAuthzFailure: false", then that privilege will not be removed when testing for authorization failure. +9) commandArgs + +Set of options to be passed to your 'command' function. Can be used to send different versions of +the command depending on the testcase being run. + */ // constants @@ -1052,10 +1057,18 @@ var authCommandsLib = { }, { testname: "aggregate_out_legacy", - command: {aggregate: "foo", pipeline: [{$out: "foo_out"}], cursor: {}}, + command: function(state, args) { + return { + aggregate: "foo", + pipeline: [{$out: "foo_out"}], + cursor: {}, + bypassDocumentValidation: args.bypassDocumentValidation, + }; + }, testcases: [ { runOnDb: firstDbName, + commandArgs: {bypassDocumentValidation: false}, roles: {readWrite: 1, readWriteAnyDatabase: 1, dbOwner: 1, root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, @@ -1065,6 +1078,7 @@ var authCommandsLib = { }, { runOnDb: secondDbName, + commandArgs: {bypassDocumentValidation: false}, roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, privileges: [ {resource: {db: secondDbName, collection: "foo"}, actions: ["find"]}, @@ -1072,18 +1086,35 @@ var authCommandsLib = { {resource: {db: secondDbName, collection: "foo_out"}, actions: ["remove"]} ] }, + { + runOnDb: firstDbName, + commandArgs: {bypassDocumentValidation: true}, + // Note that the built-in role must have 'bypassDocumentValidation' for this test. + roles: {dbOwner: 1, root: 1, __system: 1}, + privileges: [ + {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, + { + resource: {db: firstDbName, collection: "foo_out"}, + actions: ["insert", "remove", "bypassDocumentValidation"] + }, + ] + }, ] }, { testname: "aggregate_out_replace_collection", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "replaceCollection"}}], - cursor: {} + command: function(state, args) { + return { + aggregate: "foo", + pipeline: [{$out: {db: args.targetDB, to: "foo_out", mode: "replaceCollection"}}], + cursor: {}, + bypassDocumentValidation: args.bypassDocumentValidation, + }; }, testcases: [ { runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: false}, roles: {readWrite: 1, readWriteAnyDatabase: 1, dbOwner: 1, root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, @@ -1093,6 +1124,7 @@ var authCommandsLib = { }, { runOnDb: secondDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: false}, roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, privileges: [ {resource: {db: secondDbName, collection: "foo"}, actions: ["find"]}, @@ -1100,18 +1132,36 @@ var authCommandsLib = { {resource: {db: secondDbName, collection: "foo_out"}, actions: ["remove"]} ] }, + { + runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: true}, + // Note that the built-in role must have 'bypassDocumentValidation' for this test. + roles: {dbOwner: 1, root: 1, __system: 1}, + privileges: [ + {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, + { + resource: {db: firstDbName, collection: "foo_out"}, + actions: ["insert", "remove", "bypassDocumentValidation"] + }, + ] + }, + // TODO SERVER-36832: Test with mode "replaceCollection" to a foreign database. ] }, { testname: "aggregate_out_insert_documents", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "insertDocuments"}}], - cursor: {} + command: function(state, args) { + return { + aggregate: "foo", + pipeline: [{$out: {db: args.targetDB, to: "foo_out", mode: "insertDocuments"}}], + cursor: {}, + bypassDocumentValidation: args.bypassDocumentValidation, + }; }, testcases: [ { runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: false}, roles: {readWrite: 1, readWriteAnyDatabase: 1, dbOwner: 1, root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, @@ -1120,99 +1170,97 @@ var authCommandsLib = { }, { runOnDb: secondDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: false}, roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, privileges: [ {resource: {db: secondDbName, collection: "foo"}, actions: ["find"]}, {resource: {db: secondDbName, collection: "foo_out"}, actions: ["insert"]}, ] }, - ] - }, - { - testname: "aggregate_out_replace_documents", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "replaceDocuments"}}], - cursor: {} - }, - testcases: [ { runOnDb: firstDbName, - roles: {readWrite: 1, readWriteAnyDatabase: 1, dbOwner: 1, root: 1, __system: 1}, - privileges: [ - {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, - {resource: {db: firstDbName, collection: "foo_out"}, actions: ["insert"]}, - {resource: {db: firstDbName, collection: "foo_out"}, actions: ["update"]}, - ] - }, - { - runOnDb: secondDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: false}, roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, privileges: [ - {resource: {db: secondDbName, collection: "foo"}, actions: ["find"]}, + {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, {resource: {db: secondDbName, collection: "foo_out"}, actions: ["insert"]}, - {resource: {db: secondDbName, collection: "foo_out"}, actions: ["update"]}, ] }, - ] - }, - { - testname: "aggregate_out_legacy_bypass_doc_validation", - command: { - aggregate: "foo", - pipeline: [{$out: "foo_out"}], - cursor: {}, - bypassDocumentValidation: true, - }, - testcases: [ + // Test for bypassDocumentValidation. { runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: true}, // Note that the built-in role must have 'bypassDocumentValidation' for this test. roles: {dbOwner: 1, root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, { resource: {db: firstDbName, collection: "foo_out"}, - actions: ["insert", "remove", "bypassDocumentValidation"] + actions: ["insert", "bypassDocumentValidation"] }, ] }, - ] - }, - { - testname: "aggregate_out_replace_collection_bypass_doc_validation", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "replaceCollection"}}], - cursor: {}, - bypassDocumentValidation: true, - }, - testcases: [ + // Test for bypassDocumentValidation to a foreign database. { runOnDb: firstDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: true}, // Note that the built-in role must have 'bypassDocumentValidation' for this test. - roles: {dbOwner: 1, root: 1, __system: 1}, + roles: {root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, { - resource: {db: firstDbName, collection: "foo_out"}, - actions: ["insert", "remove", "bypassDocumentValidation"] + resource: {db: secondDbName, collection: "foo_out"}, + actions: ["insert", "bypassDocumentValidation"] }, ] }, ] }, { - testname: "aggregate_out_replace_documents_bypass_doc_validation", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "replaceDocuments"}}], - cursor: {}, - bypassDocumentValidation: true, + testname: "aggregate_out_replace_documents", + command: function(state, args) { + return { + aggregate: "foo", + pipeline: [{$out: {db: args.targetDB, to: "foo_out", mode: "replaceDocuments"}}], + cursor: {}, + bypassDocumentValidation: args.bypassDocumentValidation, + }; }, testcases: [ { runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: false}, + roles: {readWrite: 1, readWriteAnyDatabase: 1, dbOwner: 1, root: 1, __system: 1}, + privileges: [ + {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, + {resource: {db: firstDbName, collection: "foo_out"}, actions: ["insert"]}, + {resource: {db: firstDbName, collection: "foo_out"}, actions: ["update"]}, + ] + }, + { + runOnDb: secondDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: false}, + roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, + privileges: [ + {resource: {db: secondDbName, collection: "foo"}, actions: ["find"]}, + {resource: {db: secondDbName, collection: "foo_out"}, actions: ["insert"]}, + {resource: {db: secondDbName, collection: "foo_out"}, actions: ["update"]}, + ] + }, + { + runOnDb: firstDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: false}, + roles: {readWriteAnyDatabase: 1, root: 1, __system: 1}, + privileges: [ + {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, + {resource: {db: secondDbName, collection: "foo_out"}, actions: ["insert"]}, + {resource: {db: secondDbName, collection: "foo_out"}, actions: ["update"]}, + ] + }, + // Test for bypassDocumentValidation. + { + runOnDb: firstDbName, + commandArgs: {targetDB: firstDbName, bypassDocumentValidation: true}, // Note that the built-in role must have 'bypassDocumentValidation' for this test. roles: {dbOwner: 1, root: 1, __system: 1}, privileges: [ @@ -1223,26 +1271,17 @@ var authCommandsLib = { }, ] }, - ] - }, - { - testname: "aggregate_out_insert_documents_bypass_doc_validation", - command: { - aggregate: "foo", - pipeline: [{$out: {to: "foo_out", mode: "insertDocuments"}}], - cursor: {}, - bypassDocumentValidation: true, - }, - testcases: [ + // Test for bypassDocumentValidation to a foreign database. { runOnDb: firstDbName, + commandArgs: {targetDB: secondDbName, bypassDocumentValidation: true}, // Note that the built-in role must have 'bypassDocumentValidation' for this test. - roles: {dbOwner: 1, root: 1, __system: 1}, + roles: {root: 1, __system: 1}, privileges: [ {resource: {db: firstDbName, collection: "foo"}, actions: ["find"]}, { - resource: {db: firstDbName, collection: "foo_out"}, - actions: ["insert", "bypassDocumentValidation"] + resource: {db: secondDbName, collection: "foo_out"}, + actions: ["insert", "update", "bypassDocumentValidation"] }, ] }, @@ -5965,11 +6004,11 @@ var authCommandsLib = { return impls.runOneTest(conn, t); }, - setup: function(conn, t, runOnDb) { + setup: function(conn, t, runOnDb, testcase) { var adminDb = conn.getDB(adminDbName); if (t.setup) { adminDb.auth("admin", "password"); - var state = t.setup(runOnDb); + var state = t.setup(runOnDb, testcase); runOnDb.getLastError(); adminDb.logout(); return state; |