diff options
77 files changed, 599 insertions, 25 deletions
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml index 34218fa2665..e09d9791c5f 100644 --- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml +++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml @@ -157,6 +157,17 @@ selector: # sync source if the RestartCatalog command kills its oplog fetching cursor, which blocks # secondary majority reads. - jstests/core/restart_catalog.js + + # These include operations the root user auth'd on the test database is not authorized to perform, + # e.g. dropping or creating system collections. + - jstests/core/cannot_create_system_dot_indexes.js + - jstests/core/list_collections_no_views.js + - jstests/core/rename8.js + - jstests/core/views/duplicate_ns.js + - jstests/core/views/invalid_system_views.js + - jstests/core/views/views_creation.js + - jstests/core/views/views_drop.js + - jstests/core/views/views_rename.js exclude_with_any_tags: - assumes_against_mongod_not_mongos ## @@ -168,7 +179,11 @@ selector: # "Cowardly refusing to run test with overridden read preference when it reads from a # non-replicated collection: ..." - assumes_read_preference_unchanged + # TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + - creates_and_authenticates_user - requires_collstats + # This suite runs as the root user, but eval requires universal privileges with authentication on. + - requires_eval_command executor: archive: @@ -192,7 +207,7 @@ executor: const res = db.runCommand({ createUser: username, pwd: password, - roles: ["dbOwner"], + roles: [{role: "root", db: jsTest.options().authenticationDatabase}] }); if (res.ok === 1) { @@ -203,7 +218,8 @@ executor: assert.commandFailedWithCode(res, ErrorCodes.DuplicateKey); } - db.logout(); + // Log out as the __system user and auth as the newly created user. + db.getSiblingDB(jsTest.options().authenticationDatabase).logout(); db.auth(username, password); })(); load("jstests/libs/override_methods/enable_causal_consistency.js"); diff --git a/buildscripts/resmokeconfig/suites/core_auth.yml b/buildscripts/resmokeconfig/suites/core_auth.yml index 0304de42ad2..d5290825547 100644 --- a/buildscripts/resmokeconfig/suites/core_auth.yml +++ b/buildscripts/resmokeconfig/suites/core_auth.yml @@ -20,6 +20,9 @@ selector: - jstests/core/**/*[aA]uth*.js # Commands using UUIDs are not compatible with name-based auth - jstests/core/commands_with_uuid.js + exclude_with_any_tags: + # TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + - creates_and_authenticates_user executor: archive: diff --git a/buildscripts/resmokeconfig/suites/jstestfuzz_replication.yml b/buildscripts/resmokeconfig/suites/jstestfuzz_replication.yml index 6c1c85d9014..6584273afa8 100644 --- a/buildscripts/resmokeconfig/suites/jstestfuzz_replication.yml +++ b/buildscripts/resmokeconfig/suites/jstestfuzz_replication.yml @@ -13,6 +13,10 @@ executor: config: shell_options: readMode: commands + global_vars: + TestData: + # Other fuzzers test commands against replica sets with logical session ids. + disableImplicitSessions: true hooks: # The CheckReplDBHash hook waits until all operations have replicated to and have been applied # on the secondaries, so we run the ValidateCollections hook after it to ensure we're diff --git a/buildscripts/resmokeconfig/suites/jstestfuzz_sharded.yml b/buildscripts/resmokeconfig/suites/jstestfuzz_sharded.yml index 394b0af4ff6..65b093116eb 100644 --- a/buildscripts/resmokeconfig/suites/jstestfuzz_sharded.yml +++ b/buildscripts/resmokeconfig/suites/jstestfuzz_sharded.yml @@ -11,6 +11,10 @@ executor: - ValidateCollections config: shell_options: + global_vars: + TestData: + # Other fuzzers test commands against sharded clusters with logical session ids. + disableImplicitSessions: true readMode: commands hooks: - class: CheckReplDBHash diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml index b0491cec3e9..f5d2c288232 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml @@ -223,6 +223,9 @@ selector: - jstests/core/json_schema/misc_validation.js - jstests/core/views/views_all_commands.js + # Fails with implicit sessions because it will use multiple sessions on the same Mongo connection. + - jstests/core/dropdb.js + # Committing a transaction when the server is fsync locked fails. - jstests/core/fsync.js diff --git a/jstests/auth/auth1.js b/jstests/auth/auth1.js index 183317414df..6eff329e341 100644 --- a/jstests/auth/auth1.js +++ b/jstests/auth/auth1.js @@ -1,6 +1,9 @@ // test read/write permissions // skip this test on 32-bit platforms +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + function setupTest() { print("START auth1.js"); baseName = "jstests_auth_auth1"; diff --git a/jstests/auth/authentication_restrictions.js b/jstests/auth/authentication_restrictions.js index ad12fd33f35..1f08b3e6d6d 100644 --- a/jstests/auth/authentication_restrictions.js +++ b/jstests/auth/authentication_restrictions.js @@ -6,6 +6,9 @@ (function() { 'use strict'; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function testConnection( conn, eventuallyConsistentConn, sleepUntilUserDataPropagated, sleepUntilUserDataRefreshed) { load("jstests/libs/host_ipaddr.js"); diff --git a/jstests/auth/authentication_restrictions_role.js b/jstests/auth/authentication_restrictions_role.js index 41e3a133cab..3f23cfdcb92 100644 --- a/jstests/auth/authentication_restrictions_role.js +++ b/jstests/auth/authentication_restrictions_role.js @@ -6,6 +6,9 @@ (function() { 'use strict'; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function testRestrictionCreationAndEnforcement( conn, eventuallyConsistentConn, sleepUntilUserDataPropagated, sleepUntilUserDataRefreshed) { load("jstests/libs/host_ipaddr.js"); diff --git a/jstests/auth/basic_role_auth.js b/jstests/auth/basic_role_auth.js index 9f8abffae40..81e1518152c 100644 --- a/jstests/auth/basic_role_auth.js +++ b/jstests/auth/basic_role_auth.js @@ -493,7 +493,7 @@ var runTests = function(conn) { testFunc.test(newConn); } catch (x) { failures.push(testFunc.name); - jsTestLog(x); + jsTestLog(tojson(x)); } }); diff --git a/jstests/auth/commands_builtin_roles.js b/jstests/auth/commands_builtin_roles.js index 93eef01bcd6..cee5957d354 100644 --- a/jstests/auth/commands_builtin_roles.js +++ b/jstests/auth/commands_builtin_roles.js @@ -9,6 +9,10 @@ in jstests/auth/commands.js. */ +// TODO SERVER-35447: This test involves killing all sessions, which will not work as expected if +// the kill command is sent with an implicit session. +TestData.disableImplicitSessions = true; + load("jstests/auth/lib/commands_lib.js"); var roles = [ diff --git a/jstests/auth/commands_user_defined_roles.js b/jstests/auth/commands_user_defined_roles.js index ad75b5e1d83..034694c96bb 100644 --- a/jstests/auth/commands_user_defined_roles.js +++ b/jstests/auth/commands_user_defined_roles.js @@ -9,6 +9,10 @@ in jstests/auth/commands.js. */ +// TODO SERVER-35447: This test involves killing all sessions, which will not work as expected if +// the kill command is sent with an implicit session. +TestData.disableImplicitSessions = true; + // constants var testUser = "userDefinedRolesTestUser"; var testRole = "userDefinedRolesTestRole"; diff --git a/jstests/auth/copyauth.js b/jstests/auth/copyauth.js index faf5badd5ff..9caa51a6e87 100644 --- a/jstests/auth/copyauth.js +++ b/jstests/auth/copyauth.js @@ -195,6 +195,10 @@ function copydbBetweenClustersTest(configObj) { assert.eq(1, target.conn.getDB(baseName)[baseName].count()); assert.eq(1, target.conn.getDB(baseName)[baseName].findOne().i); + if (configObj.isTargetUsingAuth) { + target.conn.getDB("admin").logout(); + } + // 4. Do any necessary cleanup source.stop(); target.stop(); diff --git a/jstests/auth/getMore.js b/jstests/auth/getMore.js index 999fa733be8..cbb84c4a687 100644 --- a/jstests/auth/getMore.js +++ b/jstests/auth/getMore.js @@ -3,6 +3,9 @@ (function() { "use strict"; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function runTest(conn) { let adminDB = conn.getDB("admin"); let isMaster = adminDB.runCommand("ismaster"); diff --git a/jstests/auth/kill_cursors.js b/jstests/auth/kill_cursors.js index 2fd3d7054f8..3264bbcc15b 100644 --- a/jstests/auth/kill_cursors.js +++ b/jstests/auth/kill_cursors.js @@ -3,6 +3,9 @@ (function() { 'use strict'; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function runTest(mongod) { /** * Open a cursor on `db` while authenticated as `authUsers`. diff --git a/jstests/auth/kill_sessions.js b/jstests/auth/kill_sessions.js index b2090d28609..b07364bc0c2 100644 --- a/jstests/auth/kill_sessions.js +++ b/jstests/auth/kill_sessions.js @@ -3,6 +3,10 @@ load("jstests/libs/kill_sessions.js"); (function() { 'use strict'; + // TODO SERVER-35447: This test involves killing all sessions, which will not work as expected + // if the kill command is sent with an implicit session. + TestData.disableImplicitSessions = true; + var forExec = MongoRunner.runMongod({nojournal: "", auth: ""}); var forKill = new Mongo(forExec.host); var forVerify = new Mongo(forExec.host); diff --git a/jstests/auth/list_all_local_sessions.js b/jstests/auth/list_all_local_sessions.js index 8e889feb4e2..3b7c19d1cbe 100644 --- a/jstests/auth/list_all_local_sessions.js +++ b/jstests/auth/list_all_local_sessions.js @@ -5,6 +5,10 @@ 'use strict'; load('jstests/aggregation/extras/utils.js'); + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + function runListAllLocalSessionsTest(mongod) { assert(mongod); const admin = mongod.getDB("admin"); diff --git a/jstests/auth/list_all_sessions.js b/jstests/auth/list_all_sessions.js index 35a4e3b3c06..1337fc2e94c 100644 --- a/jstests/auth/list_all_sessions.js +++ b/jstests/auth/list_all_sessions.js @@ -5,6 +5,10 @@ 'use strict'; load('jstests/aggregation/extras/utils.js'); + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + function runListAllSessionsTest(mongod) { assert(mongod); const admin = mongod.getDB("admin"); diff --git a/jstests/auth/list_local_sessions.js b/jstests/auth/list_local_sessions.js index 4693d694666..b943ba45955 100644 --- a/jstests/auth/list_local_sessions.js +++ b/jstests/auth/list_local_sessions.js @@ -4,6 +4,10 @@ 'use strict'; load('jstests/aggregation/extras/utils.js'); + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + function runListLocalSessionsTest(mongod) { assert(mongod); const admin = mongod.getDB('admin'); diff --git a/jstests/auth/list_sessions.js b/jstests/auth/list_sessions.js index e6c14a11c4c..2b6c8a0f8f1 100644 --- a/jstests/auth/list_sessions.js +++ b/jstests/auth/list_sessions.js @@ -7,6 +7,10 @@ 'use strict'; load('jstests/aggregation/extras/utils.js'); + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + function runListSessionsTest(mongod) { assert(mongod); const admin = mongod.getDB('admin'); diff --git a/jstests/auth/refresh_logical_session_cache_with_long_usernames.js b/jstests/auth/refresh_logical_session_cache_with_long_usernames.js index d9bbed5324f..e584a1b8345 100644 --- a/jstests/auth/refresh_logical_session_cache_with_long_usernames.js +++ b/jstests/auth/refresh_logical_session_cache_with_long_usernames.js @@ -4,6 +4,10 @@ (function() { 'use strict'; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + const mongod = MongoRunner.runMongod({auth: ""}); const refresh = {refreshLogicalSessionCacheNow: 1}; diff --git a/jstests/auth/rename.js b/jstests/auth/rename.js index a8120d22322..0ae3eac3113 100644 --- a/jstests/auth/rename.js +++ b/jstests/auth/rename.js @@ -1,5 +1,8 @@ // test renameCollection with auth +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + var m = MongoRunner.runMongod({auth: ""}); var db1 = m.getDB("foo"); @@ -42,4 +45,4 @@ assert.eq(db1.a.count(), 0); assert.eq(db1.b.count(), 0); assert.eq(db2.a.count(), 1); -MongoRunner.stopMongod(m, null, {user: 'admin', pwd: 'password'});
\ No newline at end of file +MongoRunner.stopMongod(m, null, {user: 'admin', pwd: 'password'}); diff --git a/jstests/auth/repl_auth.js b/jstests/auth/repl_auth.js index 17a6e13bd4b..fea8f227366 100644 --- a/jstests/auth/repl_auth.js +++ b/jstests/auth/repl_auth.js @@ -65,4 +65,8 @@ for (var x = 0; x < 20; x++) { assert.eq(1, explain.executionStats.nReturned); } +admin.logout(); +fooDB0.logout(); +barDB1.logout(); + rsTest.stopSet(); diff --git a/jstests/auth/resource_pattern_matching.js b/jstests/auth/resource_pattern_matching.js index 0fd30650982..ca3c9b50195 100644 --- a/jstests/auth/resource_pattern_matching.js +++ b/jstests/auth/resource_pattern_matching.js @@ -3,6 +3,11 @@ * @tags: [requires_replication, requires_sharding] */ +// TODO SERVER-35447: This test logs in users on the admin database, but doesn't log them out, which +// can fail with implicit sessions and ReplSetTest when the fixture attempts to verify data hashes +// at shutdown by authenticating as the __system user. +TestData.disableImplicitSessions = true; + function setup_users(granter) { var admindb = granter.getSiblingDB("admin"); admindb.runCommand({ diff --git a/jstests/auth/secondary_invalidation.js b/jstests/auth/secondary_invalidation.js index 8500322751f..16f2938ebbf 100644 --- a/jstests/auth/secondary_invalidation.js +++ b/jstests/auth/secondary_invalidation.js @@ -31,4 +31,7 @@ assert.doesNotThrow(function() { secondaryFoo.col.findOne(); }, [], "Secondary read did not work with permissions"); +admin.logout(); +secondaryFoo.logout(); + rsTest.stopSet(); diff --git a/jstests/auth/views_authz.js b/jstests/auth/views_authz.js index e22dcf86cb6..080a4b2bfcd 100644 --- a/jstests/auth/views_authz.js +++ b/jstests/auth/views_authz.js @@ -6,6 +6,9 @@ (function() { "use strict"; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function runTest(conn) { // Create the admin user. let adminDB = conn.getDB("admin"); diff --git a/jstests/core/auth1.js b/jstests/core/auth1.js index 05450d14ddc..4f2a869ab44 100644 --- a/jstests/core/auth1.js +++ b/jstests/core/auth1.js @@ -1,4 +1,9 @@ -// @tags: [requires_non_retryable_commands, requires_auth, assumes_write_concern_unchanged] +// @tags: [ +// assumes_write_concern_unchanged, +// creates_and_authenticates_user, +// requires_auth, +// requires_non_retryable_commands, +// ] var mydb = db.getSiblingDB('auth1_db'); mydb.dropAllUsers(); diff --git a/jstests/core/connection_status.js b/jstests/core/connection_status.js index df1c59ab234..33d11149657 100644 --- a/jstests/core/connection_status.js +++ b/jstests/core/connection_status.js @@ -1,7 +1,8 @@ // @tags: [ -// requires_non_retryable_commands, +// assumes_write_concern_unchanged, +// creates_and_authenticates_user, // requires_auth, -// assumes_write_concern_unchanged +// requires_non_retryable_commands, // ] // Tests the connectionStatus command diff --git a/jstests/core/evalb.js b/jstests/core/evalb.js index 92fbb81f31c..96f2bbd7358 100644 --- a/jstests/core/evalb.js +++ b/jstests/core/evalb.js @@ -2,10 +2,11 @@ // contents are logged in the profile log. // // @tags: [ +// assumes_read_preference_unchanged, +// creates_and_authenticates_user, // does_not_support_stepdowns, // requires_eval_command, // requires_non_retryable_commands, -// assumes_read_preference_unchanged // ] // Use a reserved database name to avoid a conflict in the parallel test suite. diff --git a/jstests/core/profile1.js b/jstests/core/profile1.js index 4109c3ac55d..730bb91a33a 100644 --- a/jstests/core/profile1.js +++ b/jstests/core/profile1.js @@ -1,4 +1,9 @@ -// @tags: [does_not_support_stepdowns, requires_non_retryable_commands, requires_collstats] +// @tags: [ +// creates_and_authenticates_user, +// does_not_support_stepdowns, +// requires_collstats, +// requires_non_retryable_commands, +// ] (function() { "use strict"; diff --git a/jstests/core/profile3.js b/jstests/core/profile3.js index 35e37d0917d..f55256783ab 100644 --- a/jstests/core/profile3.js +++ b/jstests/core/profile3.js @@ -1,4 +1,5 @@ // @tags: [ +// creates_and_authenticates_user // # profile command is not available on embedded // incompatible_with_embedded, // ] diff --git a/jstests/core/txns/multi_statement_transaction_command_args.js b/jstests/core/txns/multi_statement_transaction_command_args.js index fe139e2f16d..8246d1030a5 100644 --- a/jstests/core/txns/multi_statement_transaction_command_args.js +++ b/jstests/core/txns/multi_statement_transaction_command_args.js @@ -8,6 +8,9 @@ "use strict"; load('jstests/libs/uuid_util.js'); + // Makes assertions on commands run without logical session ids. + TestData.disableImplicitSessions = true; + const dbName = "test"; const collName = "multi_statement_transaction_command_args"; const testDB = db.getSiblingDB(dbName); diff --git a/jstests/core/user_management_helpers.js b/jstests/core/user_management_helpers.js index 6e3ee9187c0..3d3b1b49c68 100644 --- a/jstests/core/user_management_helpers.js +++ b/jstests/core/user_management_helpers.js @@ -1,7 +1,8 @@ // @tags: [ -// requires_non_retryable_commands, +// assumes_write_concern_unchanged, +// creates_and_authenticates_user, // requires_auth, -// assumes_write_concern_unchanged +// requires_non_retryable_commands, // ] // This test is a basic sanity check of the shell helpers for manipulating user objects diff --git a/jstests/multiVersion/mixed_storage_version_replication.js b/jstests/multiVersion/mixed_storage_version_replication.js index c67de845e77..d9f2e880e0c 100644 --- a/jstests/multiVersion/mixed_storage_version_replication.js +++ b/jstests/multiVersion/mixed_storage_version_replication.js @@ -4,6 +4,11 @@ * storage engines, do a bunch of random work, and assert that it replicates the same way on all * nodes. */ + +// This test randomly generates operations, which may include direct writes against +// config.transactions, which are not allowed to run under a session. +TestData.disableImplicitSessions = true; + load('jstests/libs/parallelTester.js'); load("jstests/replsets/rslib.js"); @@ -570,6 +575,10 @@ function assertSameData(primary, conns) { * function to pass to a thread to make it start doing random commands/CRUD operations. */ function startCmds(randomOps, host) { + // This test randomly generates operations, which may include direct writes against + // config.transactions, which are not allowed to run under a session. + TestData = {disableImplicitSessions: true}; + var ops = [ "insert", "remove", @@ -596,6 +605,10 @@ function startCmds(randomOps, host) { * function to pass to a thread to make it start doing random CRUD operations. */ function startCRUD(randomOps, host) { + // This test randomly generates operations, which may include direct writes against + // config.transactions, which are not allowed to run under a session. + TestData = {disableImplicitSessions: true}; + var m = new Mongo(host); var numOps = 500; Random.setRandomSeed(); diff --git a/jstests/noPassthrough/aggregation_cursor_invalidations.js b/jstests/noPassthrough/aggregation_cursor_invalidations.js index e35598dc2dd..ecc4fe160c9 100644 --- a/jstests/noPassthrough/aggregation_cursor_invalidations.js +++ b/jstests/noPassthrough/aggregation_cursor_invalidations.js @@ -12,6 +12,10 @@ (function() { 'use strict'; + // This test runs a getMore in a parallel shell, which will not inherit the implicit session of + // the cursor establishing command. + TestData.disableImplicitSessions = true; + // The DocumentSourceCursor which wraps PlanExecutors will batch results internally. We use the // 'internalDocumentSourceCursorBatchSizeBytes' parameter to disable this behavior so that we // can easily pause a pipeline in a state where it will need to request more results from the diff --git a/jstests/noPassthrough/count_helper_read_preference.js b/jstests/noPassthrough/count_helper_read_preference.js index 63b5faed2ce..619773c3563 100644 --- a/jstests/noPassthrough/count_helper_read_preference.js +++ b/jstests/noPassthrough/count_helper_read_preference.js @@ -19,7 +19,12 @@ commandsRan.push({db: db, cmd: cmd, opts: opts}); return {ok: 1, n: 100}; }; - var db = new DB(new MockMongo(), "test"); + + const mockMongo = new MockMongo(); + var db = new DB(mockMongo, "test"); + + // Attach a dummy implicit session because the mock connection cannot create sessions. + db._session = new _DummyDriverSession(mockMongo); assert.eq(commandsRan.length, 0); diff --git a/jstests/noPassthrough/currentop_includes_await_time.js b/jstests/noPassthrough/currentop_includes_await_time.js index 0c34999a512..a8ec126f6d7 100644 --- a/jstests/noPassthrough/currentop_includes_await_time.js +++ b/jstests/noPassthrough/currentop_includes_await_time.js @@ -5,6 +5,10 @@ (function() { "use test"; + // This test runs a getMore in a parallel shell, which will not inherit the implicit session of + // the cursor establishing command. + TestData.disableImplicitSessions = true; + const conn = MongoRunner.runMongod({}); assert.neq(null, conn, "mongod was unable to start up"); const testDB = conn.getDB("test"); diff --git a/jstests/noPassthrough/currentop_query.js b/jstests/noPassthrough/currentop_query.js index 7d39fcaed21..b05e66d1af0 100644 --- a/jstests/noPassthrough/currentop_query.js +++ b/jstests/noPassthrough/currentop_query.js @@ -6,6 +6,10 @@ (function() { "use strict"; + // This test runs manual getMores using different connections, which will not inherit the + // implicit session of the cursor establishing command. + TestData.disableImplicitSessions = true; + load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers. // Set up a 2-shard cluster. Configure 'internalQueryExecYieldIterations' on both shards such diff --git a/jstests/noPassthrough/end_sessions_command.js b/jstests/noPassthrough/end_sessions_command.js index 1ed1c471557..e4ee14b8ecb 100644 --- a/jstests/noPassthrough/end_sessions_command.js +++ b/jstests/noPassthrough/end_sessions_command.js @@ -1,6 +1,10 @@ (function() { "use script"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var res; var refresh = {refreshLogicalSessionCacheNow: 1}; var startSession = {startSession: 1}; diff --git a/jstests/noPassthrough/implicit_sessions.js b/jstests/noPassthrough/implicit_sessions.js new file mode 100644 index 00000000000..350571164b9 --- /dev/null +++ b/jstests/noPassthrough/implicit_sessions.js @@ -0,0 +1,265 @@ +/** + * Verifies behavior around implicit sessions in the mongo shell. + */ +(function() { + "use strict"; + + /** + * Runs the given function, inspecting the outgoing command object and making assertions about + * its logical session id. + */ + function inspectCommandForSessionId(func, {shouldIncludeId, expectedId, differentFromId}) { + const mongoRunCommandOriginal = Mongo.prototype.runCommand; + + const sentinel = {}; + let cmdObjSeen = sentinel; + + Mongo.prototype.runCommand = function runCommandSpy(dbName, cmdObj, options) { + cmdObjSeen = cmdObj; + return mongoRunCommandOriginal.apply(this, arguments); + }; + + try { + assert.doesNotThrow(func); + } finally { + Mongo.prototype.runCommand = mongoRunCommandOriginal; + } + + if (cmdObjSeen === sentinel) { + throw new Error("Mongo.prototype.runCommand() was never called: " + func.toString()); + } + + // If the command is in a wrapped form, then we look for the actual command object inside + // the query/$query object. + let cmdName = Object.keys(cmdObjSeen)[0]; + if (cmdName === "query" || cmdName === "$query") { + cmdObjSeen = cmdObjSeen[cmdName]; + cmdName = Object.keys(cmdObjSeen)[0]; + } + + if (shouldIncludeId) { + assert(cmdObjSeen.hasOwnProperty("lsid"), + "Expected operation " + tojson(cmdObjSeen) + " to have a logical session id."); + + if (expectedId) { + assert(bsonBinaryEqual(expectedId, cmdObjSeen.lsid), + "The sent session id did not match the expected, sent: " + + tojson(cmdObjSeen.lsid) + ", expected: " + tojson(expectedId)); + } + + if (differentFromId) { + assert(!bsonBinaryEqual(differentFromId, cmdObjSeen.lsid), + "The sent session id was not different from the expected, sent: " + + tojson(cmdObjSeen.lsid) + ", expected: " + tojson(differentFromId)); + } + + } else { + assert( + !cmdObjSeen.hasOwnProperty("lsid"), + "Expected operation " + tojson(cmdObjSeen) + " to not have a logical session id."); + } + + return cmdObjSeen.lsid; + } + + // Tests regular behavior of implicit sessions. + function runTest() { + const conn = MongoRunner.runMongod(); + + // Commands run on a database without an explicit session should use an implicit one. + const testDB = conn.getDB("test"); + const coll = testDB.getCollection("foo"); + const implicitId = inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true}); + + assert(bsonBinaryEqual(testDB.getSession().getSessionId(), implicitId), + "Expected the id of the database's implicit session to match the one sent, sent: " + + tojson(implicitId) + " db session id: " + + tojson(testDB.getSession().getSessionId())); + + // Implicit sessions are not causally consistent. + assert(!testDB.getSession().getOptions().isCausalConsistency(), + "Expected the database's implicit session to not be causally consistent"); + + // Further commands run on the same database should reuse the implicit session. + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // New collections from the same database should inherit the implicit session. + const collTwo = testDB.getCollection("bar"); + inspectCommandForSessionId(function() { + assert.writeOK(collTwo.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // Sibling databases should inherit the implicit session. + let siblingColl = testDB.getSiblingDB("foo").getCollection("bar"); + inspectCommandForSessionId(function() { + assert.writeOK(siblingColl.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // A new database from the same connection should inherit the implicit session. + const newCollSameConn = conn.getDB("testTwo").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(newCollSameConn.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // A new database from a new connection should use a different implicit session. + const newCollNewConn = new Mongo(conn.host).getDB("test").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(newCollNewConn.insert({x: 1})); + }, {shouldIncludeId: true, differentFromId: implicitId}); + + // The original implicit session should still live on the first database. + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // Databases created from an explicit session should override any implicit sessions. + const session = conn.startSession(); + const sessionColl = session.getDatabase("test").getCollection("foo"); + const explicitId = inspectCommandForSessionId(function() { + assert.writeOK(sessionColl.insert({x: 1})); + }, {shouldIncludeId: true, differentFromId: implicitId}); + + assert(bsonBinaryEqual(session.getSessionId(), explicitId), + "Expected the id of the explicit session to match the one sent, sent: " + + tojson(explicitId) + " explicit session id: " + tojson(session.getSessionId())); + assert(bsonBinaryEqual(sessionColl.getDB().getSession().getSessionId(), explicitId), + "Expected id of the database's session to match the explicit session's id, sent: " + + tojson(sessionColl.getDB().getSession().getSessionId()) + + ", explicit session id: " + tojson(session.getSessionId())); + + // The original implicit session should still live on the first database. + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + // New databases on the same connection as the explicit session should still inherit the + // original implicit session. + const newCollSameConnAfter = conn.getDB("testThree").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(newCollSameConnAfter.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + session.endSession(); + MongoRunner.stopMongod(conn); + } + + // Tests behavior when the test flag to disable implicit sessions is changed. + function runTestTransitionToDisabled() { + const conn = MongoRunner.runMongod(); + + // Existing implicit sessions should be erased when the disable flag is set. + const coll = conn.getDB("test").getCollection("foo"); + const implicitId = inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true}); + + TestData.disableImplicitSessions = true; + + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: false}); + + // After the flag is unset, databases using existing connections with implicit sessions will + // use the original implicit sessions again and new connections will create and use new + // implicit sessions. + TestData.disableImplicitSessions = false; + + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + const newColl = conn.getDB("test").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(newColl.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: implicitId}); + + const newCollNewConn = new Mongo(conn.host).getDB("test").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(newCollNewConn.insert({x: 1})); + }, {shouldIncludeId: true, differentFromId: implicitId}); + + // Explicit sessions should not be affected by the disable flag being set. + const session = conn.startSession(); + const sessionColl = session.getDatabase("test").getCollection("foo"); + const explicitId = inspectCommandForSessionId(function() { + assert.writeOK(sessionColl.insert({x: 1})); + }, {shouldIncludeId: true}); + + TestData.disableImplicitSessions = true; + + inspectCommandForSessionId(function() { + assert.writeOK(sessionColl.insert({x: 1})); + }, {shouldIncludeId: true, expectedId: explicitId}); + + session.endSession(); + MongoRunner.stopMongod(conn); + } + + // Tests for the shell parameter, and the function that exposes it, for disabling implicit + // sessions. + function runTestGlobalFlag() { + const conn = MongoRunner.runMongod(); + const testDB = conn.getDB("test"); + + // The native disabled function should return false in the mongo shell by default. + assert(_shouldUseImplicitSessions()); + + // Commands run in eval should never use implicit sessions. + const evalFunc = function() { + assert(!_shouldUseImplicitSessions(), + "expected implicit sessions to be disabled inside eval"); + + inspectCommandForSessionId(function() { + assert.writeOK(db.foo.insert({x: 1})); + }, {shouldIncludeId: false}); + }; + testDB.eval("inspectCommandForSessionId = " + inspectCommandForSessionId.toString() + + "; (" + evalFunc.toString() + ")()"); + + MongoRunner.stopMongod(conn); + } + + // Tests behavior of implicit sessions when they are disabled via a test flag. + function runTestDisabled() { + const conn = MongoRunner.runMongod(); + + // Commands run without an explicit session should not use an implicit one. + const coll = conn.getDB("test").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(coll.insert({x: 1})); + }, {shouldIncludeId: false}); + + // Explicit sessions should still include session ids. + const session = conn.startSession(); + const sessionColl = session.getDatabase("test").getCollection("foo"); + inspectCommandForSessionId(function() { + assert.writeOK(sessionColl.insert({x: 1})); + }, {shouldIncludeId: true}); + + // Commands run in a parallel shell inherit the disable flag. + TestData.inspectCommandForSessionId = inspectCommandForSessionId; + const awaitShell = startParallelShell(function() { + const parallelColl = db.getCollection("foo"); + TestData.inspectCommandForSessionId(function() { + assert.writeOK(parallelColl.insert({x: 1})); + }, {shouldIncludeId: false}); + }, conn.port); + awaitShell(); + + session.endSession(); + MongoRunner.stopMongod(conn); + } + + runTest(); + + runTestTransitionToDisabled(); + + runTestGlobalFlag(); + + TestData.disableImplicitSessions = true; + runTestDisabled(); +})(); diff --git a/jstests/noPassthrough/kill_pinned_cursor.js b/jstests/noPassthrough/kill_pinned_cursor.js index d8ecd4998d2..e70f7f98dfb 100644 --- a/jstests/noPassthrough/kill_pinned_cursor.js +++ b/jstests/noPassthrough/kill_pinned_cursor.js @@ -12,6 +12,11 @@ (function() { "use strict"; + + // This test runs manual getMores using different connections, which will not inherit the + // implicit session of the cursor establishing command. + TestData.disableImplicitSessions = true; + load("jstests/libs/fixture_helpers.js"); // For "isMongos". const st = new ShardingTest({shards: 2}); diff --git a/jstests/noPassthrough/kill_sessions.js b/jstests/noPassthrough/kill_sessions.js index bd804fa4528..16cb100d31e 100644 --- a/jstests/noPassthrough/kill_sessions.js +++ b/jstests/noPassthrough/kill_sessions.js @@ -3,6 +3,10 @@ load("jstests/libs/kill_sessions.js"); (function() { 'use strict'; + // TODO SERVER-35447: This test involves killing all sessions, which will not work as expected + // if the kill command is sent with an implicit session. + TestData.disableImplicitSessions = true; + var conn = MongoRunner.runMongod({nojournal: ""}); KillSessionsTestHelper.runNoAuth(conn, conn, [conn]); MongoRunner.stopMongod(conn); diff --git a/jstests/noPassthrough/log_format_slowms_samplerate_loglevel.js b/jstests/noPassthrough/log_format_slowms_samplerate_loglevel.js index 37afb165dd8..786f28c9d6b 100644 --- a/jstests/noPassthrough/log_format_slowms_samplerate_loglevel.js +++ b/jstests/noPassthrough/log_format_slowms_samplerate_loglevel.js @@ -7,6 +7,10 @@ (function() { "use strict"; + // This test looks for exact matches in log output, which does not account for implicit + // sessions. + TestData.disableImplicitSessions = true; + load("jstests/libs/fixture_helpers.js"); // For FixtureHelpers. load("jstests/libs/check_log.js"); // For formatAsLogLine. diff --git a/jstests/noPassthrough/refresh_logical_session_cache_now.js b/jstests/noPassthrough/refresh_logical_session_cache_now.js index 294a16043d2..59d181845fe 100644 --- a/jstests/noPassthrough/refresh_logical_session_cache_now.js +++ b/jstests/noPassthrough/refresh_logical_session_cache_now.js @@ -1,6 +1,10 @@ (function() { "use script"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var res; var refresh = {refreshLogicalSessionCacheNow: 1}; var startSession = {startSession: 1}; diff --git a/jstests/noPassthrough/refresh_sessions_command.js b/jstests/noPassthrough/refresh_sessions_command.js index 80b249faca7..1f7b1a4c301 100644 --- a/jstests/noPassthrough/refresh_sessions_command.js +++ b/jstests/noPassthrough/refresh_sessions_command.js @@ -1,6 +1,10 @@ (function() { "use strict"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var conn; var admin; var result; diff --git a/jstests/noPassthrough/sessions_collection_auto_healing.js b/jstests/noPassthrough/sessions_collection_auto_healing.js index 58c64561161..21eb3d221a3 100644 --- a/jstests/noPassthrough/sessions_collection_auto_healing.js +++ b/jstests/noPassthrough/sessions_collection_auto_healing.js @@ -3,6 +3,10 @@ load('jstests/libs/sessions_collection.js'); (function() { "use strict"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var startSession = {startSession: 1}; var conn = MongoRunner.runMongod({nojournal: ""}); diff --git a/jstests/noPassthrough/shell_can_use_read_concern.js b/jstests/noPassthrough/shell_can_use_read_concern.js index 65cf66c06cc..049e7cad818 100644 --- a/jstests/noPassthrough/shell_can_use_read_concern.js +++ b/jstests/noPassthrough/shell_can_use_read_concern.js @@ -6,6 +6,9 @@ (function() { "use strict"; + // This test makes assertions on commands run without logical session ids. + TestData.disableImplicitSessions = true; + const rst = new ReplSetTest({nodes: 1}); rst.startSet(); rst.initiate(); diff --git a/jstests/noPassthrough/snapshot_cursor_integrity.js b/jstests/noPassthrough/snapshot_cursor_integrity.js index d5d0678a641..fa1a44a6699 100644 --- a/jstests/noPassthrough/snapshot_cursor_integrity.js +++ b/jstests/noPassthrough/snapshot_cursor_integrity.js @@ -4,6 +4,9 @@ (function() { "use strict"; + // This test makes assertions on commands run without logical session ids. + TestData.disableImplicitSessions = true; + const dbName = "test"; const collName = "coll"; diff --git a/jstests/noPassthrough/start_session_command.js b/jstests/noPassthrough/start_session_command.js index 4564cf5ab54..bfdd053179d 100644 --- a/jstests/noPassthrough/start_session_command.js +++ b/jstests/noPassthrough/start_session_command.js @@ -1,5 +1,10 @@ (function() { 'use strict'; + + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var conn; var admin; var foo; diff --git a/jstests/noPassthrough/transaction_reaper.js b/jstests/noPassthrough/transaction_reaper.js index cdf58ec481e..71a0977f972 100644 --- a/jstests/noPassthrough/transaction_reaper.js +++ b/jstests/noPassthrough/transaction_reaper.js @@ -2,6 +2,10 @@ (function() { 'use strict'; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + load("jstests/libs/retryable_writes_util.js"); if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) { diff --git a/jstests/noPassthrough/verify_session_cache_updates.js b/jstests/noPassthrough/verify_session_cache_updates.js index 0f4e6cb39c1..22674cb1ecb 100644 --- a/jstests/noPassthrough/verify_session_cache_updates.js +++ b/jstests/noPassthrough/verify_session_cache_updates.js @@ -3,6 +3,10 @@ (function() { 'use strict'; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + function runTest(conn) { for (var i = 0; i < 10; ++i) { conn.getDB("test").test.save({a: i}); diff --git a/jstests/noPassthroughWithMongod/tailable_getmore_does_not_timeout.js b/jstests/noPassthroughWithMongod/tailable_getmore_does_not_timeout.js index 0e8d05db09b..19a0452febb 100644 --- a/jstests/noPassthroughWithMongod/tailable_getmore_does_not_timeout.js +++ b/jstests/noPassthroughWithMongod/tailable_getmore_does_not_timeout.js @@ -4,6 +4,10 @@ (function() { "use strict"; + // This test runs a getMore in a parallel shell, which will not inherit the implicit session of + // the cursor establishing command. + TestData.disableImplicitSessions = true; + const coll = db.tailable_getmore_no_timeout; coll.drop(); diff --git a/jstests/replsets/auth1.js b/jstests/replsets/auth1.js index 81d3ddca816..9a9f36939b2 100644 --- a/jstests/replsets/auth1.js +++ b/jstests/replsets/auth1.js @@ -6,6 +6,11 @@ load("jstests/replsets/rslib.js"); (function() { + "use strict"; + + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + var name = "rs_auth1"; var port = allocatePorts(5); var path = "jstests/libs/"; diff --git a/jstests/replsets/refresh_sessions_rs.js b/jstests/replsets/refresh_sessions_rs.js index 307915d2faa..9bd4527c7bf 100644 --- a/jstests/replsets/refresh_sessions_rs.js +++ b/jstests/replsets/refresh_sessions_rs.js @@ -1,6 +1,9 @@ (function() { "use strict"; + // This test makes assertions about the number of logical session records. + TestData.disableImplicitSessions = true; + var refresh = {refreshLogicalSessionCacheNow: 1}; var startSession = {startSession: 1}; diff --git a/jstests/replsets/retryable_writes_direct_write_to_config_transactions.js b/jstests/replsets/retryable_writes_direct_write_to_config_transactions.js index 6739915ec56..0a89dcc7390 100644 --- a/jstests/replsets/retryable_writes_direct_write_to_config_transactions.js +++ b/jstests/replsets/retryable_writes_direct_write_to_config_transactions.js @@ -2,6 +2,9 @@ (function() { 'use strict'; + // Direct writes to config.transactions cannot be part of a session. + TestData.disableImplicitSessions = true; + load("jstests/libs/retryable_writes_util.js"); if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) { diff --git a/jstests/replsets/rollback_auth.js b/jstests/replsets/rollback_auth.js index e3b03ad40b2..7d78484fdf1 100644 --- a/jstests/replsets/rollback_auth.js +++ b/jstests/replsets/rollback_auth.js @@ -20,6 +20,9 @@ // TODO SERVER-32639: remove this flag. TestData.skipGossipingClusterTime = true; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + // helper function for verifying contents at the end of the test var checkFinalResults = function(db) { assert.commandWorked(db.runCommand({dbStats: 1})); diff --git a/jstests/replsets/sessions_collection_auto_healing.js b/jstests/replsets/sessions_collection_auto_healing.js index e77b99f4059..f4f147a5dd3 100644 --- a/jstests/replsets/sessions_collection_auto_healing.js +++ b/jstests/replsets/sessions_collection_auto_healing.js @@ -3,6 +3,10 @@ load('jstests/libs/sessions_collection.js'); (function() { "use strict"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var replTest = new ReplSetTest({name: 'refresh', nodes: 3}); var nodes = replTest.startSet(); diff --git a/jstests/replsets/user_management_wc.js b/jstests/replsets/user_management_wc.js index a0796b4fcbf..e24c4c74eae 100644 --- a/jstests/replsets/user_management_wc.js +++ b/jstests/replsets/user_management_wc.js @@ -10,6 +10,10 @@ load('jstests/multiVersion/libs/auth_helpers.js'); (function() { "use strict"; + + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + var replTest = new ReplSetTest( {name: 'UserManagementWCSet', nodes: 3, settings: {chainingAllowed: false}}); replTest.startSet(); diff --git a/jstests/sharding/advance_cluster_time_action_type.js b/jstests/sharding/advance_cluster_time_action_type.js index fac7f803774..1f3f00a2abb 100644 --- a/jstests/sharding/advance_cluster_time_action_type.js +++ b/jstests/sharding/advance_cluster_time_action_type.js @@ -5,6 +5,9 @@ (function() { "use strict"; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + // TODO: Remove 'shardAsReplicaSet: false' when SERVER-32672 is fixed. let st = new ShardingTest({ mongos: 1, diff --git a/jstests/sharding/authCommands.js b/jstests/sharding/authCommands.js index 8ad74f23db3..efd285869ab 100644 --- a/jstests/sharding/authCommands.js +++ b/jstests/sharding/authCommands.js @@ -4,6 +4,9 @@ (function() { 'use strict'; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + load("jstests/replsets/rslib.js"); // Replica set nodes started with --shardsvr do not enable key generation until they are added diff --git a/jstests/sharding/auth_repl.js b/jstests/sharding/auth_repl.js index 9e1ddb06873..0c8e976bd48 100644 --- a/jstests/sharding/auth_repl.js +++ b/jstests/sharding/auth_repl.js @@ -1,3 +1,6 @@ +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + var replTest = new ReplSetTest({nodes: 3, useHostName: false, keyFile: 'jstests/libs/key1'}); replTest.startSet({oplogSize: 10}); replTest.initiate(); diff --git a/jstests/sharding/cleanup_orphaned_auth.js b/jstests/sharding/cleanup_orphaned_auth.js index 4943643c33d..f32a66ee242 100644 --- a/jstests/sharding/cleanup_orphaned_auth.js +++ b/jstests/sharding/cleanup_orphaned_auth.js @@ -5,6 +5,9 @@ (function() { 'use strict'; + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function assertUnauthorized(res, msg) { if (assert._debug && msg) print("in assert for: " + msg); diff --git a/jstests/sharding/commands_that_write_accept_wc_configRS.js b/jstests/sharding/commands_that_write_accept_wc_configRS.js index 1f436cc163b..ba2f3f559c6 100644 --- a/jstests/sharding/commands_that_write_accept_wc_configRS.js +++ b/jstests/sharding/commands_that_write_accept_wc_configRS.js @@ -17,6 +17,10 @@ load('jstests/multiVersion/libs/auth_helpers.js'); (function() { "use strict"; + + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + var st = new ShardingTest({ shards: { rs0: {nodes: 3, settings: {chainingAllowed: false}}, diff --git a/jstests/sharding/kill_pinned_cursor.js b/jstests/sharding/kill_pinned_cursor.js index 417ed66817e..d7e4017d273 100644 --- a/jstests/sharding/kill_pinned_cursor.js +++ b/jstests/sharding/kill_pinned_cursor.js @@ -9,6 +9,9 @@ (function() { "use strict"; + // This test manually simulates a session, which is not compatible with implicit sessions. + TestData.disableImplicitSessions = true; + const kFailPointName = "waitAfterPinningCursorBeforeGetMoreBatch"; const kFailpointOptions = {shouldCheckForInterrupt: true}; diff --git a/jstests/sharding/kill_sessions.js b/jstests/sharding/kill_sessions.js index d5bb39213f1..a3ad23139a0 100644 --- a/jstests/sharding/kill_sessions.js +++ b/jstests/sharding/kill_sessions.js @@ -3,6 +3,10 @@ load("jstests/libs/kill_sessions.js"); (function() { 'use strict'; + // TODO SERVER-35447: This test involves killing all sessions, which will not work as expected + // if the kill command is sent with an implicit session. + TestData.disableImplicitSessions = true; + function runTests(needAuth) { var other = { rs: true, diff --git a/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js b/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js index b9ac2deda07..8cb8fe8f7fb 100644 --- a/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js +++ b/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js @@ -9,6 +9,10 @@ (function() { "use strict"; + // This test uses authentication and runs commands without authenticating, which is not + // compatible with implicit sessions. + TestData.disableImplicitSessions = true; + load("jstests/multiVersion/libs/multi_rs.js"); // TODO SERVER-32672: remove this flag. @@ -46,6 +50,7 @@ priRSConn.auth(rUser.username, rUser.password); const resWithKeys = priRSConn.runCommand({isMaster: 1}); assertContainsValidLogicalTime(resWithKeys); + priRSConn.logout(); // Enable the failpoint, remove all keys, and restart the config servers with the failpoint // still enabled to guarantee there are no keys. @@ -60,6 +65,7 @@ }); assert(adminDB.system.keys.count() == 0, "expected there to be no keys on the config server"); + adminDB.logout(); st.configRS.stopSet(null /* signal */, true /* forRestart */); st.configRS.startSet( @@ -72,6 +78,7 @@ priRSConn = st.rs0.getPrimary().getDB("admin"); priRSConn.auth(rUser.username, rUser.password); const resNoKeys = assert.commandWorked(priRSConn.runCommand({isMaster: 1})); + priRSConn.logout(); assert.eq(resNoKeys.hasOwnProperty("$clusterTime"), false); assert.eq(resNoKeys.hasOwnProperty("operationTime"), false); diff --git a/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js b/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js index 774c1d7dd01..5ce56f9f546 100644 --- a/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js +++ b/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js @@ -24,6 +24,9 @@ TestData.skipCheckingUUIDsConsistentAcrossCluster = true; // TODO SERVER-32672: remove this flag. TestData.skipGossipingClusterTime = true; +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + var options = {rs: true, rsOptions: {nodes: 2}, keyFile: "jstests/libs/key1"}; var st = new ShardingTest({shards: 3, mongos: 1, other: options}); diff --git a/jstests/sharding/mrShardedOutputAuth.js b/jstests/sharding/mrShardedOutputAuth.js index 3dc02da7072..0536c6a51b9 100644 --- a/jstests/sharding/mrShardedOutputAuth.js +++ b/jstests/sharding/mrShardedOutputAuth.js @@ -6,6 +6,9 @@ (function() { + // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. + TestData.disableImplicitSessions = true; + function doMapReduce(connection, outputDb) { // clean output db and run m/r outputDb.numbers_out.drop(); diff --git a/jstests/sharding/refresh_sessions.js b/jstests/sharding/refresh_sessions.js index 8199ffb4563..ee4ee125db3 100644 --- a/jstests/sharding/refresh_sessions.js +++ b/jstests/sharding/refresh_sessions.js @@ -1,6 +1,9 @@ (function() { "use strict"; + // This test makes assumptions about the number of logical sessions. + TestData.disableImplicitSessions = true; + var sessionsDb = "config"; var refresh = {refreshLogicalSessionCacheNow: 1}; var startSession = {startSession: 1}; diff --git a/jstests/sharding/sessions_collection_auto_healing.js b/jstests/sharding/sessions_collection_auto_healing.js index 5dcf6d66590..61271bd8dc5 100644 --- a/jstests/sharding/sessions_collection_auto_healing.js +++ b/jstests/sharding/sessions_collection_auto_healing.js @@ -3,6 +3,10 @@ load('jstests/libs/sessions_collection.js'); (function() { "use strict"; + // This test makes assertions about the number of sessions, which are not compatible with + // implicit sessions. + TestData.disableImplicitSessions = true; + var st = new ShardingTest({shards: 0}); var configSvr = st.configRS.getPrimary(); var configAdmin = configSvr.getDB("admin"); diff --git a/jstests/sharding/sharding_options.js b/jstests/sharding/sharding_options.js index 8af7bf01c53..190d78a1e94 100644 --- a/jstests/sharding/sharding_options.js +++ b/jstests/sharding/sharding_options.js @@ -1,3 +1,6 @@ +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + var baseName = "jstests_sharding_sharding_options"; load('jstests/libs/command_line/test_parsed_options.js'); diff --git a/jstests/sharding/snapshot_aggregate_mongos.js b/jstests/sharding/snapshot_aggregate_mongos.js index b0480fc534c..43ce65a7672 100644 --- a/jstests/sharding/snapshot_aggregate_mongos.js +++ b/jstests/sharding/snapshot_aggregate_mongos.js @@ -3,6 +3,10 @@ (function() { "use strict"; + // This test intentionally runs commands without a logical session id, which is not compatible + // with implicit sessions. + TestData.disableImplicitSessions = true; + load("jstests/libs/global_snapshot_reads_util.js"); const dbName = "test"; diff --git a/jstests/sharding/snapshot_find_mongos.js b/jstests/sharding/snapshot_find_mongos.js index 92b5b679730..0c7bf4c59f4 100644 --- a/jstests/sharding/snapshot_find_mongos.js +++ b/jstests/sharding/snapshot_find_mongos.js @@ -4,6 +4,10 @@ (function() { "use strict"; + // This test intentionally runs commands without a logical session id, which is not compatible + // with implicit sessions. + TestData.disableImplicitSessions = true; + load("jstests/libs/global_snapshot_reads_util.js"); const dbName = "test"; diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js index bfb1e04f7cf..0a78e9db761 100644 --- a/src/mongo/shell/mongo.js +++ b/src/mongo/shell/mongo.js @@ -58,7 +58,9 @@ Mongo.prototype.getDB = function(name) { Mongo.prototype.getDBs = function(driverSession = this._getDefaultSession()) { var cmdObj = {listDatabases: 1}; - cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) { + cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + } var res = this.adminCommand(cmdObj); if (!res.ok) @@ -75,7 +77,9 @@ Mongo.prototype.adminCommand = function(cmd) { */ Mongo.prototype.getLogComponents = function(driverSession = this._getDefaultSession()) { var cmdObj = {getParameter: 1, logComponentVerbosity: 1}; - cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) { + cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + } var res = this.adminCommand(cmdObj); if (!res.ok) @@ -106,7 +110,9 @@ Mongo.prototype.setLogLevel = function( } var cmdObj = {setParameter: 1, logComponentVerbosity: vDoc}; - cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) { + cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + } var res = this.adminCommand(cmdObj); if (!res.ok) @@ -426,11 +432,14 @@ Mongo.prototype.startSession = function startSession(options = {}) { }; Mongo.prototype._getDefaultSession = function getDefaultSession() { - // We implicitly associate a Mongo connection object with a DriverSession so that tests which - // call DB.prototype.getMongo() and then Mongo.prototype.getDB() to get a different DB instance - // are still causally consistent. + // We implicitly associate a Mongo connection object with a real session so all requests include + // a logical session id. These implicit sessions are intentionally not causally consistent. If + // implicit sessions have been globally disabled, a dummy session is used instead of a real one. if (!this.hasOwnProperty("_defaultSession")) { - this._defaultSession = new _DummyDriverSession(this); + this._defaultSession = _shouldUseImplicitSessions() + ? this.startSession({causalConsistency: false}) + : new _DummyDriverSession(this); + this._defaultSession._isExplicit = false; } return this._defaultSession; }; diff --git a/src/mongo/shell/query.js b/src/mongo/shell/query.js index fcbcd5a39b3..60785e4b417 100644 --- a/src/mongo/shell/query.js +++ b/src/mongo/shell/query.js @@ -112,10 +112,11 @@ DBQuery.prototype._exec = function() { var cmdRes = this._db.runReadCommand(findCmd, null, this._options); this._cursor = new DBCommandCursor(this._db, cmdRes, this._batchSize); } else { - // Note that depending on how SERVER-32064 is implemented, we may need to alter this - // check to account for implicit sessions, so that exhaust cursors can still be used in - // the shell. - if (this._db.getSession().getSessionId() !== null) { + // The exhaust cursor option is disallowed under a session because it doesn't work as + // expected, but all requests from the shell use implicit sessions, so to allow users + // to continue using exhaust cursors through the shell, they are only disallowed with + // explicit sessions. + if (this._db.getSession()._isExplicit) { throw new Error("Cannot run a legacy query on a session."); } diff --git a/src/mongo/shell/session.js b/src/mongo/shell/session.js index b7e77d8e9f2..07720d49047 100644 --- a/src/mongo/shell/session.js +++ b/src/mongo/shell/session.js @@ -209,7 +209,14 @@ var { } function prepareCommandRequest(driverSession, cmdObj) { - if (serverSupports(kWireVersionSupportingLogicalSession)) { + if (serverSupports(kWireVersionSupportingLogicalSession) && + // Always attach sessionId from explicit sessions. + (driverSession._isExplicit || + // Check that implicit sessions are not disabled. The client must be using read + // commands because aggregations always use runCommand() to establish cursors but + // may use OP_GET_MORE (and therefore not have a session id attached) to retrieve + // subsequent batches. + (!jsTest.options().disableImplicitSessions && client.useReadCommands()))) { cmdObj = driverSession._serverSession.injectSessionId(cmdObj); } @@ -836,6 +843,8 @@ var { this._serverSession = implMethods.createServerSession(client); + this._isExplicit = true; + this.getClient = function getClient() { return client; }; diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp index 5a9742d3935..f441f0ba4ab 100644 --- a/src/mongo/shell/shell_utils.cpp +++ b/src/mongo/shell/shell_utils.cpp @@ -253,6 +253,10 @@ BSONObj shouldRetryWrites(const BSONObj&, void* data) { return BSON("" << shellGlobalParams.shouldRetryWrites); } +BSONObj shouldUseImplicitSessions(const BSONObj&, void* data) { + return BSON("" << true); +} + BSONObj interpreterVersion(const BSONObj& a, void* data) { uassert(16453, "interpreterVersion accepts no arguments", a.nFields() == 0); return BSON("" << getGlobalScriptEngine()->getInterpreterVersionString()); @@ -290,6 +294,7 @@ void initScope(Scope& scope) { scope.injectNative("_writeMode", writeMode); scope.injectNative("_readMode", readMode); scope.injectNative("_shouldRetryWrites", shouldRetryWrites); + scope.injectNative("_shouldUseImplicitSessions", shouldUseImplicitSessions); scope.externalSetup(); mongo::shell_utils::installShellUtils(scope); scope.execSetup(JSFiles::servers); diff --git a/src/mongo/shell/utils.js b/src/mongo/shell/utils.js index 3820eac4f36..79c5433b892 100644 --- a/src/mongo/shell/utils.js +++ b/src/mongo/shell/utils.js @@ -313,7 +313,8 @@ jsTestOptions = function() { skipCheckDBHashes: TestData.skipCheckDBHashes || false, traceExceptions: TestData.hasOwnProperty("traceExceptions") ? TestData.traceExceptions : true, - transactionLifetimeLimitSeconds: TestData.transactionLifetimeLimitSeconds + transactionLifetimeLimitSeconds: TestData.transactionLifetimeLimitSeconds, + disableImplicitSessions: TestData.disableImplicitSessions || false, }); } return _jsTestOptions; @@ -559,6 +560,16 @@ if (typeof _shouldRetryWrites === 'undefined') { }; } +if (typeof _shouldUseImplicitSessions === 'undefined') { + // We ensure the _shouldUseImplicitSessions() function is always defined, in case the JavaScript + // engine is being used from someplace other than the mongo shell (e.g. map-reduce). If the + // function was not defined, implicit sessions are disabled to prevent unnecessary sessions from + // being created. + _shouldUseImplicitSessions = function _shouldUseImplicitSessions() { + return false; + }; +} + shellPrintHelper = function(x) { if (typeof(x) == "undefined") { // Make sure that we have a db var before we use it |