diff options
28 files changed, 221 insertions, 59 deletions
diff --git a/buildscripts/resmokeconfig/suites/ssl.yml b/buildscripts/resmokeconfig/suites/ssl.yml index a9e91a695a8..708ff0c3805 100644 --- a/buildscripts/resmokeconfig/suites/ssl.yml +++ b/buildscripts/resmokeconfig/suites/ssl.yml @@ -3,10 +3,6 @@ test_kind: js_test selector: roots: - jstests/ssl/*.js - exclude_files: - # TODO SERVER-55273: remove once x509 authentication is available for ReplSetTest - - jstests/ssl/sharding_with_x509.js - - jstests/ssl/speculative-auth-sharding.js # ssl tests start their own mongod's. executor: diff --git a/buildscripts/resmokeconfig/suites/ssl_x509.yml b/buildscripts/resmokeconfig/suites/ssl_x509.yml new file mode 100644 index 00000000000..83e29d34b7a --- /dev/null +++ b/buildscripts/resmokeconfig/suites/ssl_x509.yml @@ -0,0 +1,23 @@ +test_kind: js_test + +selector: + roots: + - jstests/ssl_x509/*.js + +# ssl tests start their own mongod's. +executor: + config: + shell_options: + nodb: '' + ssl: '' + sslAllowInvalidCertificates: '' + sslCAFile: jstests/libs/ca.pem + # We use server.pem so that shell can auth as __system. + sslPEMKeyFile: jstests/libs/server.pem + readMode: commands + global_vars: + TestData: + setParameters: + logComponentVerbosity: "{network:2}" + setParametersMongos: + logComponentVerbosity: "{network:2}" diff --git a/etc/evergreen.yml b/etc/evergreen.yml index a83aa63f153..48f8b7ac16f 100644 --- a/etc/evergreen.yml +++ b/etc/evergreen.yml @@ -6366,6 +6366,15 @@ tasks: resmoke_args: --storageEngine=wiredTiger fallback_num_sub_suites: 3 +- name: ssl_x509_gen + tags: ["encrypt", "ssl"] + commands: + - func: "generate resmoke tasks" + vars: + suite: ssl_x509 + resmoke_args: --storageEngine=wiredTiger + fallback_num_sub_suites: 3 + - <<: *task_template name: jsCore_decimal tags: ["jscore", "common", "decimal"] diff --git a/jstests/ssl/ssl_x509_roles.js b/jstests/ssl/ssl_x509_roles.js index a0097bb5978..0a6fde1f0bc 100644 --- a/jstests/ssl/ssl_x509_roles.js +++ b/jstests/ssl/ssl_x509_roles.js @@ -69,10 +69,18 @@ function authAndTest(port, expectSuccess) { runTest(CLIENT_EMAIL_CERT, "jstests/ssl/libs/ssl_x509_role_auth_email.js"); } +function isConnAuthenticated(conn) { + const connStatus = conn.adminCommand({connectionStatus: 1, showPrivileges: true}); + const connIsAuthenticated = connStatus.authInfo.authenticatedUsers.length > 0; + return connIsAuthenticated; +} + const prepConn = function(conn) { - const admin = conn.getDB('admin'); - admin.createUser({user: "admin", pwd: "admin", roles: ["root"]}); - assert(admin.auth('admin', 'admin')); + if (!isConnAuthenticated(conn)) { + const admin = conn.getDB('admin'); + admin.createUser({user: "admin", pwd: "admin", roles: ["root"]}); + assert(admin.auth('admin', 'admin')); + } const external = conn.getDB('$external'); external.createUser({user: CLIENT_USER_NO_ROLES, roles: [{'role': 'readWrite', 'db': 'test'}]}); diff --git a/jstests/ssl_x509/cluster_x509_restart.js b/jstests/ssl_x509/cluster_x509_restart.js new file mode 100644 index 00000000000..e1c002709d2 --- /dev/null +++ b/jstests/ssl_x509/cluster_x509_restart.js @@ -0,0 +1,37 @@ +/** + * This test does a simple restart of a replica set with X.509 cluster auth. + * + * @tags: [requires_persistence, requires_replication] + */ + +(function() { +'use strict'; + +const rst = new ReplSetTest({ + nodes: 3, + waitForKeys: false, + nodeOptions: { + sslMode: "requireSSL", + clusterAuthMode: "x509", + keyFile: "jstests/libs/key1", + sslPEMKeyFile: "jstests/libs/server.pem", + sslCAFile: "jstests/libs/ca.pem", + sslAllowInvalidHostnames: "" + } +}); +rst.startSet(); + +rst.initiate(); + +rst.awaitReplication(3000); + +// Create a user to login as when auth is enabled later +rst.getPrimary().getDB('admin').createUser({user: 'root', pwd: 'root', roles: ['root']}, {w: 3}); + +let primary = rst.getPrimary(); + +assert.commandWorked(primary.getDB("admin").runCommand({hello: 1})); +assert.commandWorked(primary.getDB('test').a.insert({a: 1, str: 'TESTTESTTEST'})); + +rst.stopSet(); +})(); diff --git a/jstests/ssl/initial_sync1_x509.js b/jstests/ssl_x509/initial_sync1_x509.js index 7a8621ef55b..b9d66693f6b 100644 --- a/jstests/ssl/initial_sync1_x509.js +++ b/jstests/ssl_x509/initial_sync1_x509.js @@ -30,23 +30,19 @@ function runInitialSyncTest() { }); var conns = replTest.startSet(); - // ReplSetTest.initiate() requires all nodes to be to be authorized to run replSetGetStatus. - // TODO(SERVER-14017): Remove this in favor of using initiate() everywhere. - replTest.initiateWithAnyNodeAsPrimary( - Object.extend(replTest.getReplSetConfig(), - {writeConcernMajorityJournalDefault: wcMajorityJournalDefault})); + replTest.initiate(); var primary = replTest.getPrimary(); var foo = primary.getDB("foo"); var admin = primary.getDB("admin"); var secondary1 = replTest.getSecondary(); - var admin_s1 = secondary1.getDB("admin"); print("2. Create a root user."); admin.createUser({user: "root", pwd: "pass", roles: ["root"]}); - admin.auth("root", "pass"); - admin_s1.auth("root", "pass"); + authutil.assertAuthenticate(replTest.getPrimary(), '$external', { + mechanism: 'MONGODB-X509', + }); print("3. Insert some data"); var bulk = foo.bar.initializeUnorderedBulkOp(); @@ -70,6 +66,7 @@ function runInitialSyncTest() { print("6. Everyone happy eventually"); replTest.awaitReplication(300000); + admin.logout(); replTest.stopSet(); } @@ -105,4 +102,11 @@ var conns = replTest.startSet(); assert.throws(function() { replTest.initiate(); }); -replTest.stopSet(); + +// stopSet will also fail because we cannot authenticate to stop it properly. +// Ignore the error around unterminated processes. +TestData.failIfUnterminatedProcesses = false; + +assert.throws(function() { + replTest.stopSet(); +}); diff --git a/jstests/ssl/mixed_mode_sharded_transition.js b/jstests/ssl_x509/mixed_mode_sharded_transition.js index 39756785b38..39756785b38 100644 --- a/jstests/ssl/mixed_mode_sharded_transition.js +++ b/jstests/ssl_x509/mixed_mode_sharded_transition.js diff --git a/jstests/ssl/sharding_with_x509.js b/jstests/ssl_x509/sharding_with_x509.js index f1ab60cd3e4..1bf668dcbab 100644 --- a/jstests/ssl/sharding_with_x509.js +++ b/jstests/ssl_x509/sharding_with_x509.js @@ -75,13 +75,5 @@ if (st.configRS) { }); } -// Index consistency check during shutdown needs a privileged user to auth as. -const x509User = 'CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US'; -st.s.getDB('$external').createUser({user: x509User, roles: [{role: '__system', db: 'admin'}]}); - -// Orphan checks needs a privileged user to auth as. -st.shard0.getDB('$external').createUser({user: x509User, roles: [{role: '__system', db: 'admin'}]}); -st.shard1.getDB('$external').createUser({user: x509User, roles: [{role: '__system', db: 'admin'}]}); - st.stop(); })(); diff --git a/jstests/ssl/shell_x509_system_user.js b/jstests/ssl_x509/shell_x509_system_user.js index f404b6b7b3b..0f7af04d95a 100644 --- a/jstests/ssl/shell_x509_system_user.js +++ b/jstests/ssl_x509/shell_x509_system_user.js @@ -28,10 +28,7 @@ const rst = new ReplSetTest({nodes: 1, nodeOptions: x509Options, waitForKeys: fa rst.startSet(); -// ReplSetTest.initiate() requires all nodes to be to be authorized to run replSetGetStatus. -// TODO(SERVER-14017): Remove this in favor of using initiate() everywhere. -rst.initiateWithAnyNodeAsPrimary(Object.extend( - rst.getReplSetConfig(), {writeConcernMajorityJournalDefault: wcMajorityJournalDefault})); +rst.initiate(); const primaryConnString = rst.getPrimary().host; diff --git a/jstests/ssl/speculative-auth-replset.js b/jstests/ssl_x509/speculative-auth-replset.js index 23930c4811a..4d761ba22b0 100644 --- a/jstests/ssl/speculative-auth-replset.js +++ b/jstests/ssl_x509/speculative-auth-replset.js @@ -27,13 +27,16 @@ rst.initiate(); const admin = rst.getPrimary().getDB('admin'); admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']}); -admin.auth('admin', 'pwd'); function getMechStats(db) { return assert.commandWorked(db.runCommand({serverStatus: 1})) .security.authentication.mechanisms; } +authutil.assertAuthenticate(rst.getPrimary(), '$external', { + mechanism: 'MONGODB-X509', +}); + // Capture statistics after a fresh instantiation of a 1-node replica set. const initialMechStats = getMechStats(admin); printjson(initialMechStats); @@ -47,9 +50,7 @@ Object.keys(initialMechStats).forEach(function(mech) { const clusterStats = initialMechStats[mech].clusterAuthenticate; if (mech === 'MONGODB-X509') { - // It appears that replication helpers use SCRAM-SHA-1, preventing SCRAM-SHA-256 cluster - // stats from being incremented during test setup. - assert.eq(clusterStats.received, 0); + assert.eq(clusterStats.received, 1); } // No speculation has occured @@ -72,7 +73,7 @@ Object.keys(initialMechStats).forEach(function(mech) { rst.stop(newNode); rst.remove(newNode); - admin.auth('admin', 'pwd'); + singleNodeConfig.version = rst.getReplSetConfigFromNode(0).version + 1; assert.commandWorked(admin.runCommand({replSetReconfig: singleNodeConfig, force: true})); } diff --git a/jstests/ssl/speculative-auth-sharding.js b/jstests/ssl_x509/speculative-auth-sharding.js index 418dd996224..f553aa120c8 100644 --- a/jstests/ssl/speculative-auth-sharding.js +++ b/jstests/ssl_x509/speculative-auth-sharding.js @@ -108,9 +108,5 @@ if (st.configRS) { }); } -// Orphan checks needs a privileged user to auth as. -st.shard0.getDB('$external') - .createUser({user: CLIENT_NAME, roles: [{role: '__system', db: 'admin'}]}); - st.stop(); }()); diff --git a/jstests/ssl/ssl_get_more.js b/jstests/ssl_x509/ssl_get_more.js index f7cf987d660..f7cf987d660 100644 --- a/jstests/ssl/ssl_get_more.js +++ b/jstests/ssl_x509/ssl_get_more.js diff --git a/jstests/ssl/upgrade_noauth_to_x509_ssl.js b/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js index 17b6ab30f21..17b6ab30f21 100644 --- a/jstests/ssl/upgrade_noauth_to_x509_ssl.js +++ b/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js diff --git a/jstests/ssl/upgrade_to_x509_ssl.js b/jstests/ssl_x509/upgrade_to_x509_ssl.js index 51c5418713c..4fce4143725 100644 --- a/jstests/ssl/upgrade_to_x509_ssl.js +++ b/jstests/ssl_x509/upgrade_to_x509_ssl.js @@ -48,10 +48,7 @@ var rst = new ReplSetTest({ }); rst.startSet(); -// ReplSetTest.initiate() requires all nodes to be to be authorized to run replSetGetStatus. -// TODO(SERVER-14017): Remove this in favor of using initiate() everywhere. -rst.initiateWithAnyNodeAsPrimary(Object.extend( - rst.getReplSetConfig(), {writeConcernMajorityJournalDefault: wcMajorityJournalDefault})); +rst.initiate(); // Connect to master and do some basic operations var rstConn1 = rst.getPrimary(); diff --git a/src/mongo/client/dbclient_base.h b/src/mongo/client/dbclient_base.h index 3d78e628a2f..8cb9288e771 100644 --- a/src/mongo/client/dbclient_base.h +++ b/src/mongo/client/dbclient_base.h @@ -780,6 +780,12 @@ public: virtual bool isUsingTransientSSLParams() const { return false; } + + virtual bool isTLS() = 0; +#else + virtual bool isTLS() { + return false; + } #endif const ClientAPIVersionParameters& getApiParameters() const { diff --git a/src/mongo/client/dbclient_connection.cpp b/src/mongo/client/dbclient_connection.cpp index c6625a2ecf2..a42865be5be 100644 --- a/src/mongo/client/dbclient_connection.cpp +++ b/src/mongo/client/dbclient_connection.cpp @@ -858,6 +858,10 @@ bool DBClientConnection::isUsingTransientSSLParams() const { return _transientSSLParams.has_value(); } +bool DBClientConnection::isTLS() { + return SSLPeerInfo::forSession(_session).isTLS; +} + #endif AtomicWord<int> DBClientConnection::_numConnections; diff --git a/src/mongo/client/dbclient_connection.h b/src/mongo/client/dbclient_connection.h index f8f0c6ca76e..a4ea1c299e2 100644 --- a/src/mongo/client/dbclient_connection.h +++ b/src/mongo/client/dbclient_connection.h @@ -306,6 +306,8 @@ public: const SSLConfiguration* getSSLConfiguration() override; bool isUsingTransientSSLParams() const override; + + bool isTLS(); #endif protected: diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp index a1dab200294..8659ac795f8 100644 --- a/src/mongo/client/dbclient_rs.cpp +++ b/src/mongo/client/dbclient_rs.cpp @@ -1219,6 +1219,11 @@ void DBClientReplicaSet::resetSecondaryOkConn() { const SSLConfiguration* DBClientReplicaSet::getSSLConfiguration() { return checkPrimary()->getSSLConfiguration(); } + +bool DBClientReplicaSet::isTLS() { + return checkPrimary()->isTLS(); +} + #endif } // namespace mongo diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h index 414e5190226..38eae4bdb34 100644 --- a/src/mongo/client/dbclient_rs.h +++ b/src/mongo/client/dbclient_rs.h @@ -262,6 +262,8 @@ public: #ifdef MONGO_CONFIG_SSL const SSLConfiguration* getSSLConfiguration() override; + + bool isTLS() override; #endif protected: diff --git a/src/mongo/db/dbdirectclient.h b/src/mongo/db/dbdirectclient.h index 7b27481d540..b9097e9c5fd 100644 --- a/src/mongo/db/dbdirectclient.h +++ b/src/mongo/db/dbdirectclient.h @@ -107,6 +107,10 @@ public: return false; } + bool isTLS() final { + return false; + } + #ifdef MONGO_CONFIG_SSL const SSLConfiguration* getSSLConfiguration() override { invariant(false); diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp index 0358c15ba2d..b97e8e8e3d5 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -83,6 +83,7 @@ const JSFunctionSpec MongoBase::methods[] = { MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(getMaxWireVersion, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(isReplicaSetMember, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(isMongos, MongoExternalInfo), + MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(isTLS, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(getApiParameters, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(_startSession, MongoExternalInfo), JS_FS_END, @@ -836,6 +837,12 @@ void MongoBase::Functions::isMongos::call(JSContext* cx, JS::CallArgs args) { args.rval().setBoolean(conn->isMongos()); } +void MongoBase::Functions::isTLS::call(JSContext* cx, JS::CallArgs args) { + auto conn = getConnection(args); + + args.rval().setBoolean(conn->isTLS()); +} + void MongoBase::Functions::getApiParameters::call(JSContext* cx, JS::CallArgs args) { auto conn = getConnection(args); ValueReader(cx, args.rval()).fromBSON(conn->getApiParameters().toBSON(), nullptr, false); diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h index 644ea06ecbd..1b86e323d51 100644 --- a/src/mongo/scripting/mozjs/mongo.h +++ b/src/mongo/scripting/mozjs/mongo.h @@ -77,11 +77,12 @@ struct MongoBase : public BaseInfo { MONGO_DECLARE_JS_FUNCTION(getMaxWireVersion); MONGO_DECLARE_JS_FUNCTION(isReplicaSetMember); MONGO_DECLARE_JS_FUNCTION(isMongos); + MONGO_DECLARE_JS_FUNCTION(isTLS); MONGO_DECLARE_JS_FUNCTION(getApiParameters); MONGO_DECLARE_JS_FUNCTION(_startSession); }; - static const JSFunctionSpec methods[28]; + static const JSFunctionSpec methods[29]; static const char* const className; static const unsigned classFlags = JSCLASS_HAS_PRIVATE; diff --git a/src/mongo/shell/encrypted_dbclient_base.cpp b/src/mongo/shell/encrypted_dbclient_base.cpp index dd20a63e9cf..5eb9f8f8c7e 100644 --- a/src/mongo/shell/encrypted_dbclient_base.cpp +++ b/src/mongo/shell/encrypted_dbclient_base.cpp @@ -662,6 +662,10 @@ std::shared_ptr<SymmetricKey> EncryptedDBClientBase::getDataKeyFromDisk(const UU const SSLConfiguration* EncryptedDBClientBase::getSSLConfiguration() { return _conn->getSSLConfiguration(); } + +bool EncryptedDBClientBase::isTLS() { + return _conn->isTLS(); +} #endif namespace { diff --git a/src/mongo/shell/encrypted_dbclient_base.h b/src/mongo/shell/encrypted_dbclient_base.h index 4281513cada..5062dfa8266 100644 --- a/src/mongo/shell/encrypted_dbclient_base.h +++ b/src/mongo/shell/encrypted_dbclient_base.h @@ -143,6 +143,8 @@ public: #ifdef MONGO_CONFIG_SSL const SSLConfiguration* getSSLConfiguration() override; + + bool isTLS() final; #endif protected: diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index 623e653318d..1ebcb0f06a5 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -198,7 +198,25 @@ var ReplSetTest = function(opts) { return !connIsAuthenticated; }); - if (keyFileParam && unauthenticatedConns.length > 0) { + const connOptions = connArray[0].fullOptions || {}; + const authMode = connOptions.clusterAuthMode || connArray[0].clusterAuthMode || + jsTest.options().clusterAuthMode; + + let needsAuth = (keyFileParam || authMode === "x509" || authMode === "sendX509" || + authMode === "sendKeyFile") && + unauthenticatedConns.length > 0; + + // There are few cases where we do not auth + // 1. When transitiong to auth + // 2. When cluster is running in x509 but shell was not started with TLS (i.e. sslSpecial + // suite) + if (needsAuth && + (connOptions.transitionToAuth !== undefined || + (authMode === "x509" && !connArray[0].isTLS()))) { + needsAuth = false; + } + + if (needsAuth) { return authutil.asCluster(unauthenticatedConns, keyFileParam, fn); } else { return fn(); @@ -1525,9 +1543,14 @@ var ReplSetTest = function(opts) { } // Setup authentication if running test with authentication - if ((jsTestOptions().keyFile) && cmdKey == 'replSetInitiate') { + if ((jsTestOptions().keyFile || self.clusterAuthMode === "x509") && + cmdKey === 'replSetInitiate') { primary = this.getPrimary(); - jsTest.authenticateNodes(this.nodes); + // The sslSpecial suite sets up cluster with x509 but the shell was not started with TLS + // so we need to rely on the test to auth if needed. + if (!(self.clusterAuthMode === "x509" && !primary.isTLS())) { + jsTest.authenticateNodes(this.nodes); + } } // Wait for initial sync to complete on all nodes. Use a faster polling interval so we can @@ -3207,6 +3230,12 @@ var ReplSetTest = function(opts) { self.oplogSize = opts.oplogSize || 40; self.useSeedList = opts.useSeedList || false; self.keyFile = opts.keyFile; + + self.clusterAuthMode = undefined; + if (opts.clusterAuthMode) { + self.clusterAuthMode = opts.clusterAuthMode; + } + self.protocolVersion = opts.protocolVersion; self.waitForKeys = opts.waitForKeys; @@ -3253,6 +3282,13 @@ var ReplSetTest = function(opts) { numNodes = opts.nodes; } + for (let i = 0; i < numNodes; i++) { + if (self.nodeOptions["n" + i] !== undefined && + self.nodeOptions["n" + i].clusterAuthMode == "x509") { + self.clusterAuthMode = "x509"; + } + } + if (_useBridge) { let makeAllocatePortFn = (preallocatedPorts) => { let idxNextNodePort = 0; diff --git a/src/mongo/shell/shardingtest.js b/src/mongo/shell/shardingtest.js index b77131ab170..2e39ec890e0 100644 --- a/src/mongo/shell/shardingtest.js +++ b/src/mongo/shell/shardingtest.js @@ -781,7 +781,8 @@ var ShardingTest = function(params) { const x509AuthRequired = (conn.fullOptions && conn.fullOptions.clusterAuthMode && conn.fullOptions.clusterAuthMode === "x509" && - currNode.fullOptions.sslMode === "requireSSL"); + (currNode.fullOptions.sslMode === "requireSSL" || + currNode.fullOptions.tlsMode === "requireTLS")); if (keyFileUsed) { authutil.asCluster(currNode, keyFileUsed, () => { diff --git a/src/mongo/shell/utils.js b/src/mongo/shell/utils.js index ee8a9449438..a20fd89a25f 100644 --- a/src/mongo/shell/utils.js +++ b/src/mongo/shell/utils.js @@ -392,7 +392,11 @@ jsTest.basicUserRoles = ["dbOwner"]; jsTest.adminUserRoles = ["root"]; jsTest.authenticate = function(conn) { - if (!jsTest.options().auth && !jsTest.options().keyFile) { + const connOptions = conn.fullOptions || {}; + const authMode = + connOptions.clusterAuthMode || conn.clusterAuthMode || jsTest.options().clusterAuthMode; + + if (!jsTest.options().auth && !jsTest.options().keyFile && authMode !== "x509") { conn.authenticated = true; return true; } @@ -402,12 +406,25 @@ jsTest.authenticate = function(conn) { // Set authenticated to stop an infinite recursion from getDB calling // back into authenticate. conn.authenticated = true; - print("Authenticating as user " + jsTestOptions().authUser + " with mechanism " + - DB.prototype._getDefaultAuthenticationMechanism() + " on connection: " + conn); - conn.authenticated = conn.getDB(jsTestOptions().authenticationDatabase).auth({ - user: jsTestOptions().authUser, - pwd: jsTestOptions().authPassword, - }); + let mech = DB.prototype._getDefaultAuthenticationMechanism(); + if (authMode === 'x509') { + mech = 'MONGODB-X509'; + } + + print("Authenticating as user " + jsTestOptions().authUser + " with mechanism " + mech + + " on connection: " + conn); + + if (authMode !== 'x509') { + conn.authenticated = conn.getDB(jsTestOptions().authenticationDatabase).auth({ + user: jsTestOptions().authUser, + pwd: jsTestOptions().authPassword, + }); + } else { + authutil.assertAuthenticate(conn, '$external', { + mechanism: 'MONGODB-X509', + }); + } + return conn.authenticated; // Dont' run the hang analyzer because we expect that this might fail in the normal // course of events. diff --git a/src/mongo/shell/utils_auth.js b/src/mongo/shell/utils_auth.js index d0a26bd429e..9ad340e950b 100644 --- a/src/mongo/shell/utils_auth.js +++ b/src/mongo/shell/utils_auth.js @@ -81,14 +81,15 @@ authutil.assertAuthenticateFails = function(conns, dbName, authParams) { authutil.asCluster = function(conn, keyfile, action) { var ex; - const connOptions = conn.fullOptions || {}; - const authMode = connOptions.clusterAuthMode || jsTest.options().clusterAuthMode; - // put a connection in an array for uniform processing. let connArray = conn; if (conn.length == null) connArray = [conn]; + const connOptions = connArray[0].fullOptions || {}; + const authMode = connOptions.clusterAuthMode || connArray[0].clusterAuthMode || + jsTest.options().clusterAuthMode; + let clusterTimes = connArray.map(connElem => { const connClusterTime = connElem.getClusterTime(); const sessionClusterTime = connElem._getDefaultSession().getClusterTime(); @@ -102,14 +103,24 @@ authutil.asCluster = function(conn, keyfile, action) { }); let authDB = 'admin'; - if ((authMode === 'keyFile') || (authMode === 'sendKeyFile') || (authMode === 'sendX509')) { + if ((authMode === 'keyFile') || (authMode === 'sendKeyFile') || + (authMode === 'sendX509' && keyfile !== undefined)) { + if (keyfile === undefined) { + keyfile = connOptions.keyFile || connArray[0].keyFile; + assert(keyfile !== undefined, + `Cannot find a keyfile to use for authentication from the connection: ${ + tojson(connOptions)} ==== ${tojson(connArray[0])}`); + } + authutil.assertAuthenticate(conn, 'admin', { user: '__system', mechanism: 'SCRAM-SHA-1', pwd: cat(keyfile).replace(/[\011-\015\040]/g, '') }); - } else if (authMode === 'x509') { - authDB = '$external'; + } else if (authMode === 'x509' || authMode === 'sendX509') { + // When we login as __system, it gets registered internally as __system@local as the user + // name + authDB = 'local'; authutil.assertAuthenticate(conn, '$external', { mechanism: 'MONGODB-X509', }); |