summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2021-05-03 10:10:01 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-03 14:43:41 +0000
commit57f8c0d7c31a5a01c76748ae725591d44e08a2a8 (patch)
tree0dec98fd1d546394acc4e7454081c573b4536add
parent7d746afd02264f30e766caff7183bd2a8961c27d (diff)
downloadmongo-57f8c0d7c31a5a01c76748ae725591d44e08a2a8.tar.gz
SERVER-53605 Ensure replsettest.asCluster works with clusterAuthMode = x509
-rw-r--r--buildscripts/resmokeconfig/suites/ssl.yml4
-rw-r--r--buildscripts/resmokeconfig/suites/ssl_x509.yml23
-rw-r--r--etc/evergreen.yml9
-rw-r--r--jstests/ssl/ssl_x509_roles.js14
-rw-r--r--jstests/ssl_x509/cluster_x509_restart.js37
-rw-r--r--jstests/ssl_x509/initial_sync1_x509.js (renamed from jstests/ssl/initial_sync1_x509.js)22
-rw-r--r--jstests/ssl_x509/mixed_mode_sharded_transition.js (renamed from jstests/ssl/mixed_mode_sharded_transition.js)0
-rw-r--r--jstests/ssl_x509/sharding_with_x509.js (renamed from jstests/ssl/sharding_with_x509.js)8
-rw-r--r--jstests/ssl_x509/shell_x509_system_user.js (renamed from jstests/ssl/shell_x509_system_user.js)5
-rw-r--r--jstests/ssl_x509/speculative-auth-replset.js (renamed from jstests/ssl/speculative-auth-replset.js)11
-rw-r--r--jstests/ssl_x509/speculative-auth-sharding.js (renamed from jstests/ssl/speculative-auth-sharding.js)4
-rw-r--r--jstests/ssl_x509/ssl_get_more.js (renamed from jstests/ssl/ssl_get_more.js)0
-rw-r--r--jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js (renamed from jstests/ssl/upgrade_noauth_to_x509_ssl.js)0
-rw-r--r--jstests/ssl_x509/upgrade_to_x509_ssl.js (renamed from jstests/ssl/upgrade_to_x509_ssl.js)5
-rw-r--r--src/mongo/client/dbclient_base.h6
-rw-r--r--src/mongo/client/dbclient_connection.cpp4
-rw-r--r--src/mongo/client/dbclient_connection.h2
-rw-r--r--src/mongo/client/dbclient_rs.cpp5
-rw-r--r--src/mongo/client/dbclient_rs.h2
-rw-r--r--src/mongo/db/dbdirectclient.h4
-rw-r--r--src/mongo/scripting/mozjs/mongo.cpp7
-rw-r--r--src/mongo/scripting/mozjs/mongo.h3
-rw-r--r--src/mongo/shell/encrypted_dbclient_base.cpp4
-rw-r--r--src/mongo/shell/encrypted_dbclient_base.h2
-rw-r--r--src/mongo/shell/replsettest.js42
-rw-r--r--src/mongo/shell/shardingtest.js3
-rw-r--r--src/mongo/shell/utils.js31
-rw-r--r--src/mongo/shell/utils_auth.js23
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',
});