summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Caimano <ben.caimano@10gen.com>2021-02-17 17:42:20 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-16 17:02:35 +0000
commit0b8bd0798190c3aaa077d22682cf1b4b41055021 (patch)
tree010a0a1106d6702144bb4a2cac7ef659923ee3f6
parent6bc5f238ca6c1f5dc8e3552300412ce6f1cc6a60 (diff)
downloadmongo-0b8bd0798190c3aaa077d22682cf1b4b41055021.tar.gz
SERVER-54136 Make the authenticate command respect enforceUserClusterSeparation
(cherry picked from commit 664eacb0a0924e6a9ab2d2043e0326946f027a39)
-rw-r--r--jstests/ssl/x509_client.js52
-rw-r--r--jstests/ssl/x509_enforce_user_cluster_separation.js205
-rw-r--r--src/mongo/db/auth/SConscript12
-rw-r--r--src/mongo/db/auth/auth_options.idl6
-rw-r--r--src/mongo/db/commands/SConscript2
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp101
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp1
-rw-r--r--src/mongo/db/commands/user_management_commands.idl9
-rw-r--r--src/mongo/shell/shardingtest.js40
-rw-r--r--src/mongo/util/net/SConscript1
-rw-r--r--src/mongo/util/net/ssl_options_server.cpp7
11 files changed, 327 insertions, 109 deletions
diff --git a/jstests/ssl/x509_client.js b/jstests/ssl/x509_client.js
index 725006f37e0..dd867a1c134 100644
--- a/jstests/ssl/x509_client.js
+++ b/jstests/ssl/x509_client.js
@@ -18,12 +18,10 @@ MongoRunner.stopMongod(conn);
const SERVER_CERT = "jstests/libs/server.pem";
const CA_CERT = "jstests/libs/ca.pem";
-const SERVER_USER = "C=US,ST=New York,L=New York City,O=MongoDB,OU=Kernel,CN=server";
-const INTERNAL_USER = "C=US,ST=New York,L=New York City,O=MongoDB,OU=Kernel,CN=internal";
const CLIENT_USER = "CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US";
const INVALID_CLIENT_USER = "C=US,ST=New York,L=New York City,O=MongoDB,OU=KernelUser,CN=invalid";
-function authAndTest(mongo, {clusterUserSeparationOveride = false} = {}) {
+function authAndTest(mongo) {
external = mongo.getDB("$external");
test = mongo.getDB("test");
@@ -61,21 +59,23 @@ function authAndTest(mongo, {clusterUserSeparationOveride = false} = {}) {
assert(log.some((line) => successRegex.test(line)));
- const overrideDependentTester =
- clusterUserSeparationOveride ? assert.doesNotThrow : assert.throws;
- // It should be impossible to create users with the same name as the server's subject,
- // unless guardrails are explicitly overridden
- overrideDependentTester(function() {
+ let createServerUser = function() {
+ // It should be impossible to create users with the same name as the server's subject,
+ // unless guardrails are explicitly overridden
external.createUser(
{user: SERVER_USER, roles: [{'role': 'userAdminAnyDatabase', 'db': 'admin'}]});
- }, [], "Created user with same name as the server's x.509 subject");
+ };
+ assert.throws(
+ createServerUser, [], "Created user with same name as the server's x.509 subject");
- // It should be impossible to create users with names recognized as cluster members,
- // unless guardrails are explicitly overridden
- overrideDependentTester(function() {
+ let createInternalUser = function() {
+ // It should be impossible to create users with names recognized as cluster members,
+ // unless guardrails are explicitly overridden
external.createUser(
{user: INTERNAL_USER, roles: [{'role': 'userAdminAnyDatabase', 'db': 'admin'}]});
- }, [], "Created user which would be recognized as a cluster member");
+ };
+ assert.throws(
+ createInternalUser, [], "Created user which would be recognized as a cluster member");
// Check that we can add a user and read data
test.createUser(
@@ -101,14 +101,6 @@ const x509_options = {
authAndTest(mongo);
MongoRunner.stopMongod(mongo);
}
-{
- print("1.5. Testing x.509 auth to mongod with cluster/user separation disabled");
- const mongo = MongoRunner.runMongod(Object.merge(
- x509_options, {auth: "", setParameter: {enforceUserClusterSeparation: false}}));
-
- authAndTest(mongo, {clusterUserSeparationOveride: true});
- MongoRunner.stopMongod(mongo);
-}
{
print("2. Testing x.509 auth to mongos");
@@ -127,21 +119,3 @@ const x509_options = {
authAndTest(new Mongo("localhost:" + st.s0.port));
st.stop();
}
-{
- print("2.5 Testing x.509 auth to mongos with cluster/user separation disabled");
- var st = new ShardingTest({
- shards: 1,
- mongos: 1,
- other: {
- keyFile: 'jstests/libs/key1',
- configOptions:
- Object.merge(x509_options, {setParameter: {enforceUserClusterSeparation: false}}),
- mongosOptions: x509_options,
- shardOptions: x509_options,
- useHostname: false
- }
- });
-
- authAndTest(new Mongo("localhost:" + st.s0.port), {clusterUserSeparationOveride: true});
- st.stop();
-}
diff --git a/jstests/ssl/x509_enforce_user_cluster_separation.js b/jstests/ssl/x509_enforce_user_cluster_separation.js
new file mode 100644
index 00000000000..46d3938bc99
--- /dev/null
+++ b/jstests/ssl/x509_enforce_user_cluster_separation.js
@@ -0,0 +1,205 @@
+// Check if this build supports the authenticationMechanisms startup parameter.
+
+const SERVER_CERT = "jstests/libs/server.pem";
+const SERVER_SAN_CERT = "jstests/libs/server_SAN.pem";
+const CLIENT_CERT = "jstests/libs/client.pem";
+const CA_CERT = "jstests/libs/ca.pem";
+
+const SERVER_USER = "CN=server,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
+const SERVER_SAN_USER =
+ "CN=Kernel Client Peer Role,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
+const CLIENT_USER = "CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US";
+
+function authAndTest(cert, user) {
+ const INVALID_USER = "C=US,ST=New York,L=New York City,O=MongoDB,OU=KernelUser,CN=invalid";
+
+ let external = db.getSiblingDB("$external");
+ let test = db.getSiblingDB("test");
+
+ assert(!external.auth({user: INVALID_USER, mechanism: 'MONGODB-X509'}),
+ "authentication with invalid user should fail");
+ assert(external.auth({user: user, mechanism: 'MONGODB-X509'}),
+ "authentication with valid user failed");
+ assert(external.auth({mechanism: 'MONGODB-X509'}),
+ "authentication with valid cert and no user field failed");
+ assert(external.runCommand({authenticate: 1, mechanism: 'MONGODB-X509', user: user}).ok,
+ "runCommand authentication with valid cert and user field failed");
+ assert(external.runCommand({authenticate: 1, mechanism: 'MONGODB-X509'}).ok,
+ "runCommand authentication with valid cert and no user field failed");
+ // Smoke our current user with a find.
+ test.foo.findOne();
+
+ // Check that we can add a user and read data.
+ test.createUser(
+ {user: "test", pwd: "test", roles: [{'role': 'readWriteAnyDatabase', 'db': 'admin'}]});
+ test.foo.findOne();
+
+ // Reads are not allowed after logout.
+ external.logout();
+ assert.throws(function() {
+ test.foo.findOne();
+ }, [], "read after logout");
+}
+
+function runSubShell(conn, cert, user, func) {
+ const args = [
+ 'mongo',
+ '--tls',
+ `--tlsCAFile=${CA_CERT}`,
+ `--tlsCertificateKeyFile=${cert}`,
+ '--tlsAllowInvalidHostnames',
+ '--authenticationDatabase=$external',
+ '--authenticationMechanism=MONGODB-X509',
+ `mongodb://${conn.host}`,
+ '--eval',
+ `(${func.toString()})('${cert}', '${user}');`
+ ];
+ const ret = _runMongoProgram(...args);
+ assert(ret == ErrorCodes.OK, 'subshell did not succeed');
+}
+
+function initUser(conn, user) {
+ const external = conn.getDB("$external");
+ external.createUser({
+ user: user,
+ roles: [
+ {'role': 'userAdminAnyDatabase', 'db': 'admin'},
+ {'role': 'readWriteAnyDatabase', 'db': 'admin'},
+ {'role': 'clusterMonitor', 'db': 'admin'},
+ ]
+ });
+
+ // Localhost exception should not be in place anymore
+ const test = conn.getDB("test");
+ assert.throws(function() {
+ test.foo.findOne();
+ }, [], "read without login");
+}
+
+const x509_options = {
+ sslMode: "requireSSL",
+ sslPEMKeyFile: SERVER_CERT,
+ sslCAFile: CA_CERT
+};
+
+const mongodOptions =
+ Object.merge(x509_options, {auth: "", setParameter: {enforceUserClusterSeparation: false}});
+
+const mongosOptions =
+ Object.merge(x509_options, {setParameter: {enforceUserClusterSeparation: false}});
+
+function runMongodTest(desc, func) {
+ print(desc);
+ const mongo = MongoRunner.runMongod(mongodOptions);
+ func(mongo);
+
+ MongoRunner.stopMongod(mongo);
+}
+
+function runMongodFailTest(desc, options) {
+ print(desc);
+ const mongo = MongoRunner.runMongod(Object.merge(mongodOptions, options));
+ assert(!mongo, "MongoD started successfully with bad options");
+}
+
+function runMongosTest(desc, func) {
+ print(desc);
+ const st = new ShardingTest({
+ shards: 1,
+ mongos: 1,
+ other: {
+ keyFile: 'jstests/libs/key1',
+ configOptions: mongodOptions,
+ mongosOptions: mongosOptions,
+ shardOptions: x509_options,
+ useHostname: false
+ }
+ });
+
+ const mongo = new Mongo(`localhost:${st.s0.port}`);
+ func(mongo);
+ st.stop();
+}
+
+function runMongosFailTest(desc, options) {
+ print(desc);
+ // We start the ShardingTest cleanly first because it throws and fails to clean up after itself.
+ const st = new ShardingTest({
+ config: 1,
+ shards: 1,
+ mongos: 1,
+ other: {
+ keyFile: 'jstests/libs/key1',
+ configOptions: mongodOptions,
+ mongosOptions: mongosOptions,
+ shardOptions: x509_options,
+ useHostname: false
+ }
+ });
+
+ const failOptions = Object.merge(mongosOptions, options);
+ print(`Fail options: ${tojson(failOptions)}`);
+
+ assert.throws(function() {
+ // Start a new mongos with bad options.
+ st.restartMongos(0, failOptions);
+ }, [], "MongoS restarted successfully with bad options");
+
+ // Avoid st.stop() because it will throw when it attempts to stop the second mongos.
+ st.stopAllShards();
+ st.stopAllConfigServers();
+}
+
+runMongodTest("1a. Testing x.509 auth to mongod with a client user/cert", function(conn) {
+ initUser(conn, CLIENT_USER);
+
+ runSubShell(conn, CLIENT_CERT, CLIENT_USER, authAndTest);
+});
+
+runMongodTest("1b. Testing x.509 auth to mongod with the server user/cert", function(conn) {
+ initUser(conn, SERVER_USER);
+
+ runSubShell(conn, SERVER_CERT, SERVER_USER, authAndTest);
+});
+
+runMongodTest("1c. Testing x.509 auth to mongod with a cluster user/cert", function(conn) {
+ initUser(conn, SERVER_SAN_USER);
+
+ runSubShell(conn, SERVER_SAN_CERT, SERVER_SAN_USER, authAndTest);
+});
+
+runMongodFailTest('1d. Testing x.509 cluster auth on mongod with "x509" option',
+ {clusterAuthMode: "x509"});
+
+runMongodFailTest('1e. Testing x.509 cluster auth on mongod with "sendX509" option',
+ {clusterAuthMode: "sendX509"});
+
+runMongodFailTest('1e. Testing x.509 cluster auth on mongod with "sendKeyFile" option',
+ {clusterAuthMode: "sendKeyFile"});
+
+runMongosTest("2a. Testing x.509 auth to mongos with a client user/cert", function(conn) {
+ initUser(conn, CLIENT_USER);
+
+ runSubShell(conn, CLIENT_CERT, CLIENT_USER, authAndTest);
+});
+
+runMongosTest("2b. Testing x.509 auth to mongos with the server user/cert", function(conn) {
+ initUser(conn, SERVER_USER);
+
+ runSubShell(conn, SERVER_CERT, SERVER_USER, authAndTest);
+});
+
+runMongosTest("2c. Testing x.509 auth to mongos with a cluster user/cert", function(conn) {
+ initUser(conn, SERVER_SAN_USER);
+
+ runSubShell(conn, SERVER_SAN_CERT, SERVER_SAN_USER, authAndTest);
+});
+
+runMongosFailTest('2d. Testing x.509 cluster auth on mongos with "x509" option',
+ {restart: true, clusterAuthMode: "x509"});
+
+runMongosFailTest('2e. Testing x.509 cluster auth on mongos with "sendX509" option',
+ {clusterAuthMode: "sendX509"});
+
+runMongosFailTest('2f. Testing x.509 cluster auth on mongos with "sendKeyFile" option',
+ {clusterAuthMode: "sendKeyFile"});
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index d8c5ac1ee2e..6bd7207d9d9 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -139,13 +139,23 @@ env.Library(
)
env.Library(
+ target='auth_options',
+ source=[
+ env.Idlc("auth_options.idl")[0],
+ ],
+ LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/idl/server_parameter',
+ ],
+)
+
+env.Library(
target='role_graph_update',
source=[
'role_graph_update.cpp',
- env.Idlc("auth_options.idl")[0],
],
LIBDEPS=[
'auth',
+ 'auth_options',
'role_graph',
'$BUILD_DIR/mongo/db/update/update_driver',
],
diff --git a/src/mongo/db/auth/auth_options.idl b/src/mongo/db/auth/auth_options.idl
index 488e311ee75..a0d5139938a 100644
--- a/src/mongo/db/auth/auth_options.idl
+++ b/src/mongo/db/auth/auth_options.idl
@@ -42,3 +42,9 @@ server_parameters:
cpp_vartype: bool
cpp_varname: roleGraphInvalidationIsFatal
test_only: true
+ enforceUserClusterSeparation:
+ description: "Prevents creation of users whose names would be interpreted as cluster members"
+ set_at: startup
+ cpp_varname: "gEnforceUserClusterSeparation"
+ cpp_vartype: bool
+ default: true
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index e7bf9e16d93..4cd84cf27bb 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -184,6 +184,7 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/audit',
+ '$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/auth/sasl_options',
'$BUILD_DIR/mongo/db/auth/user_document_parser',
'$BUILD_DIR/mongo/db/commands',
@@ -366,6 +367,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/client/clientdriver_minimal',
'$BUILD_DIR/mongo/db/auth/auth',
+ '$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/auth/authprivilege',
'$BUILD_DIR/mongo/db/auth/role_graph',
'$BUILD_DIR/mongo/db/auth/sasl_options',
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 02a3505e92b..3a64955228b 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -42,6 +42,7 @@
#include "mongo/client/sasl_client_authenticate.h"
#include "mongo/config.h"
#include "mongo/db/audit.h"
+#include "mongo/db/auth/auth_options_gen.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/sasl_options.h"
@@ -68,71 +69,81 @@ namespace {
static bool _isX509AuthDisabled;
static constexpr auto kX509AuthenticationDisabledMessage = "x.509 authentication is disabled."_sd;
+constexpr auto kExternalDB = "$external"_sd;
+
#ifdef MONGO_CONFIG_SSL
Status _authenticateX509(OperationContext* opCtx, const UserName& user, const BSONObj& cmdObj) {
if (!getSSLManager()) {
return Status(ErrorCodes::ProtocolError,
"SSL support is required for the MONGODB-X509 mechanism.");
}
- if (user.getDB() != "$external") {
- return Status(ErrorCodes::ProtocolError,
- "X.509 authentication must always use the $external database.");
- }
-
- Client* client = Client::getCurrent();
- AuthorizationSession* authorizationSession = AuthorizationSession::get(client);
- auto clientName = SSLPeerInfo::forSession(client->session()).subjectName;
- uassert(ErrorCodes::AuthenticationFailed,
- "No verified subject name available from client",
- !clientName.empty());
if (!getSSLManager()->getSSLConfiguration().hasCA) {
return Status(ErrorCodes::AuthenticationFailed,
"Unable to verify x.509 certificate, as no CA has been provided.");
- } else if (user.getUser() != clientName.toString()) {
+ }
+
+ Client* client = opCtx->getClient();
+ auto clientName = SSLPeerInfo::forSession(client->session()).subjectName;
+ if (clientName.empty()) {
+ return Status(ErrorCodes::AuthenticationFailed,
+ "No verified subject name available from client");
+ }
+
+ if (user.getDB() != kExternalDB) {
+ return Status(ErrorCodes::ProtocolError,
+ "X.509 authentication must always use the $external database.");
+ }
+
+ if (user.getUser() != clientName.toString()) {
return Status(ErrorCodes::AuthenticationFailed,
"There is no x.509 client certificate matching the user.");
- } else {
+ }
+
+ AuthorizationSession* authorizationSession = AuthorizationSession::get(client);
+
+ auto isInternalClient = [&]() -> bool {
+ return opCtx->getClient()->session()->getTags() & transport::Session::kInternalClient;
+ };
+
+ auto authorizeExternalUser = [&]() -> Status {
+ if (_isX509AuthDisabled) {
+ return Status(ErrorCodes::BadValue, kX509AuthenticationDisabledMessage);
+ }
+ return authorizationSession->addAndAuthorizeUser(opCtx, user);
+ };
+
+ if (getSSLManager()->getSSLConfiguration().isClusterMember(clientName)) {
// Handle internal cluster member auth, only applies to server-server connections
- if (getSSLManager()->getSSLConfiguration().isClusterMember(clientName)) {
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) {
- return Status(ErrorCodes::AuthenticationFailed,
- "The provided certificate "
- "can only be used for cluster authentication, not client "
- "authentication. The current configuration does not allow "
- "x.509 cluster authentication, check the --clusterAuthMode flag");
- }
- auto& clientMetadata =
- ClientMetadataIsMasterState::get(opCtx->getClient()).getClientMetadata();
- if (clientMetadata) {
- auto clientMetadataDoc = clientMetadata->getDocument();
- auto driverName = clientMetadataDoc.getObjectField("driver"_sd)
- .getField("name"_sd)
- .checkAndGetStringData();
- if (!clientMetadata->getApplicationName().empty() ||
- (driverName != "MongoDB Internal Client" &&
- driverName != "NetworkInterfaceTL")) {
+ switch (serverGlobalParams.clusterAuthMode.load()) {
+ case ServerGlobalParams::ClusterAuthMode_undefined:
+ case ServerGlobalParams::ClusterAuthMode_keyFile: {
+ uassert(ErrorCodes::AuthenticationFailed,
+ "The provided certificate can only be used for cluster authentication, not "
+ "client authentication. The current configuration does not allow x.509 "
+ "cluster authentication, check the --clusterAuthMode flag",
+ !gEnforceUserClusterSeparation);
+
+ return authorizeExternalUser();
+ } break;
+ case ServerGlobalParams::ClusterAuthMode_sendKeyFile:
+ case ServerGlobalParams::ClusterAuthMode_sendX509:
+ case ServerGlobalParams::ClusterAuthMode_x509: {
+ if (!isInternalClient()) {
warning() << "Client isn't a mongod or mongos, but is connecting with a "
"certificate with cluster membership";
}
- }
- authorizationSession->grantInternalAuthorization(client);
+ authorizationSession->grantInternalAuthorization(client);
+ return Status::OK();
+ } break;
}
+ } else {
// Handle normal client authentication, only applies to client-server connections
- else {
- if (_isX509AuthDisabled) {
- return Status(ErrorCodes::BadValue, kX509AuthenticationDisabledMessage);
- }
- Status status = authorizationSession->addAndAuthorizeUser(opCtx, user);
- if (!status.isOK()) {
- return status;
- }
- }
- return Status::OK();
+ return authorizeExternalUser();
}
+
+ MONGO_UNREACHABLE;
}
#endif // MONGO_CONFIG_SSL
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index fd1809ae1da..1fc2293f2a8 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -47,6 +47,7 @@
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/address_restriction.h"
+#include "mongo/db/auth/auth_options_gen.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
diff --git a/src/mongo/db/commands/user_management_commands.idl b/src/mongo/db/commands/user_management_commands.idl
index 7df3ab4acda..1ae9c9658c5 100644
--- a/src/mongo/db/commands/user_management_commands.idl
+++ b/src/mongo/db/commands/user_management_commands.idl
@@ -32,12 +32,3 @@ imports:
- "mongo/idl/basic_types.idl"
- "mongo/db/auth/auth_types.idl"
- "mongo/db/auth/address_restriction.idl"
-
-server_parameters:
- enforceUserClusterSeparation:
- description: "Prevents creation of users whose names would be interpreted as cluster members"
- set_at: startup
- cpp_varname: "gEnforceUserClusterSeparation"
- cpp_vartype: bool
- default: true
-
diff --git a/src/mongo/shell/shardingtest.js b/src/mongo/shell/shardingtest.js
index ff4f71bae09..1386c4c3d1d 100644
--- a/src/mongo/shell/shardingtest.js
+++ b/src/mongo/shell/shardingtest.js
@@ -380,17 +380,18 @@ var ShardingTest = function(params) {
}
};
- this.stopAllMongos = function(opts) {
- for (var i = 0; i < this._mongos.length; i++) {
- this.stopMongos(i, opts);
+ this.stopAllConfigServers = function(opts) {
+ if (this.configRS) {
+ this.configRS.stopSet(undefined, undefined, opts);
+ } else {
+ // Old style config triplet
+ for (var i = 0; i < this._configServers.length; i++) {
+ this.stopConfigServer(i, opts);
+ }
}
};
- this.stop = function(opts) {
- this.checkUUIDsConsistentAcrossCluster();
-
- this.stopAllMongos(opts);
-
+ this.stopAllShards = function(opts) {
for (var i = 0; i < this._connections.length; i++) {
if (this._rs[i]) {
this._rs[i].test.stopSet(15, undefined, opts);
@@ -398,16 +399,25 @@ var ShardingTest = function(params) {
this.stopMongod(i, opts);
}
}
+ };
- if (this.configRS) {
- this.configRS.stopSet(undefined, undefined, opts);
- } else {
- // Old style config triplet
- for (var i = 0; i < this._configServers.length; i++) {
- this.stopConfigServer(i, opts);
- }
+ this.stopAllMongos = function(opts) {
+ for (var i = 0; i < this._mongos.length; i++) {
+ this.stopMongos(i, opts);
}
+ };
+
+ this.stop = function(opts) {
+ this.checkUUIDsConsistentAcrossCluster();
+
+ this.stopAllMongos(opts);
+
+ let startTime = new Date(); // Measure the execution time of shutting down shards.
+ this.stopAllShards(opts);
+ print("ShardingTest stopped all shards, took " + (new Date() - startTime) + "ms for " +
+ this._connections.length + " shards.");
+ this.stopAllConfigServers(opts);
if (!opts || !opts.noCleanData) {
print("ShardingTest stop deleting all dbpaths");
for (var i = 0; i < _alldbpaths.length; i++) {
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index 24412313a97..1ed2c22ca26 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -68,6 +68,7 @@ env.Library(
'ssl_options',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
]
diff --git a/src/mongo/util/net/ssl_options_server.cpp b/src/mongo/util/net/ssl_options_server.cpp
index dba0e0f94f7..74a341a6e90 100644
--- a/src/mongo/util/net/ssl_options_server.cpp
+++ b/src/mongo/util/net/ssl_options_server.cpp
@@ -37,6 +37,7 @@
#include "mongo/base/status.h"
#include "mongo/config.h"
+#include "mongo/db/auth/auth_options_gen.h"
#include "mongo/db/server_options.h"
#include "mongo/util/log.h"
#include "mongo/util/options_parser/startup_option_init.h"
@@ -240,6 +241,12 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
if (sslGlobalParams.sslMode.load() == SSLParams::SSLMode_disabled) {
return {ErrorCodes::BadValue, "need to enable TLS via the tlsMode flag"};
}
+
+ if (!gEnforceUserClusterSeparation) {
+ uasserted(ErrorCodes::BadValue,
+ "cannot have have x.509 cluster authentication while not enforcing user "
+ "cluster separation");
+ }
}
if (sslGlobalParams.sslMode.load() == SSLParams::SSLMode_allowSSL) {