summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2021-06-16 10:41:25 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-06-16 15:40:35 +0000
commitc73b1c09eb5ce2053577abac0a4ba360e3845de8 (patch)
tree90ebcc920053920129cd0c2d4e60d0ca4146f3a2
parenta616859a60e6cbb40ab0b7ddbeed06e726bd40bc (diff)
downloadmongo-c73b1c09eb5ce2053577abac0a4ba360e3845de8.tar.gz
SERVER-55792 Verify credentials when clusterAuthMode is set via setParameter
-rw-r--r--jstests/ssl/set_parameter_ssl.js39
-rw-r--r--jstests/sslSpecial/set_parameter_nossl.js2
-rw-r--r--src/mongo/db/SConscript24
-rw-r--r--src/mongo/db/auth/SConscript21
-rw-r--r--src/mongo/db/auth/auth_decorations.cpp19
-rw-r--r--src/mongo/db/auth/authorization_manager_global.cpp39
-rw-r--r--src/mongo/db/auth/cluster_auth_mode.cpp196
-rw-r--r--src/mongo/db/auth/cluster_auth_mode.h150
-rw-r--r--src/mongo/db/auth/sasl_scram_server_conversation.cpp25
-rw-r--r--src/mongo/db/auth/security_key.cpp14
-rw-r--r--src/mongo/db/auth/security_key.h4
-rw-r--r--src/mongo/db/auth/security_key_test.cpp5
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp47
-rw-r--r--src/mongo/db/initialize_server_security_state.cpp75
-rw-r--r--src/mongo/db/initialize_server_security_state.h41
-rw-r--r--src/mongo/db/mongod_main.cpp4
-rw-r--r--src/mongo/db/mongod_options.cpp5
-rw-r--r--src/mongo/db/server_options.h27
-rw-r--r--src/mongo/db/server_options_base.cpp10
-rw-r--r--src/mongo/db/server_options_server_helpers.cpp30
-rw-r--r--src/mongo/s/SConscript2
-rw-r--r--src/mongo/s/mongos_main.cpp4
-rw-r--r--src/mongo/util/net/SConscript3
-rw-r--r--src/mongo/util/net/ssl_manager.cpp8
-rw-r--r--src/mongo/util/net/ssl_options_server.cpp12
-rw-r--r--src/mongo/util/net/ssl_parameters.cpp35
-rw-r--r--src/mongo/util/net/ssl_parameters_auth.cpp69
28 files changed, 552 insertions, 359 deletions
diff --git a/jstests/ssl/set_parameter_ssl.js b/jstests/ssl/set_parameter_ssl.js
index 1a39cbd22a2..ce4143d0996 100644
--- a/jstests/ssl/set_parameter_ssl.js
+++ b/jstests/ssl/set_parameter_ssl.js
@@ -51,19 +51,46 @@ function testTransportTransition(scheme, oldMode, newMode, shouldSucceed) {
}
function testAuthModeTransition(oldMode, newMode, sslMode, shouldSucceed) {
- var conn = MongoRunner.runMongod({
+ const keyFile = 'jstests/libs/key1';
+
+ let config = {
sslMode: sslMode,
sslPEMKeyFile: SERVER_CERT,
sslCAFile: CA_CERT,
clusterAuthMode: oldMode
- });
+ };
- var adminDB = conn.getDB("admin");
- adminDB.createUser({user: "root", pwd: "pwd", roles: ['root']});
- adminDB.auth("root", "pwd");
- var res = adminDB.runCommand({"setParameter": 1, "clusterAuthMode": newMode});
+ if (oldMode != 'x509') {
+ config.keyFile = keyFile;
+ }
+
+ const conn = MongoRunner.runMongod(config);
+ const adminDB = conn.getDB("admin");
+ let authAsKeyFileCluster = function() {
+ const authParams = {
+ user: '__system',
+ mechanism: 'SCRAM-SHA-1',
+ pwd: cat(keyFile).replace(/[\011-\015\040]/g, '')
+ };
+ return adminDB.auth(authParams);
+ };
+
+ if (oldMode != 'x509') {
+ assert(authAsKeyFileCluster());
+ }
+
+ var res = adminDB.runCommand({"setParameter": 1, "clusterAuthMode": newMode});
assert(res["ok"] == shouldSucceed, tojson(res));
+
+ if (shouldSucceed && oldMode != 'x509') {
+ if (newMode == 'x509') {
+ assert(!authAsKeyFileCluster(), "Key file cluster auth should no longer work");
+ } else {
+ assert(authAsKeyFileCluster(), "Key file cluster auth should still work");
+ }
+ }
+
MongoRunner.stopMongod(conn);
}
diff --git a/jstests/sslSpecial/set_parameter_nossl.js b/jstests/sslSpecial/set_parameter_nossl.js
index 95b66bc274f..94f4337fb80 100644
--- a/jstests/sslSpecial/set_parameter_nossl.js
+++ b/jstests/sslSpecial/set_parameter_nossl.js
@@ -5,7 +5,7 @@
// cannot be used to transition from disabled/keyFile modes
function testTransition(newSSLMode, newClusterAuthMode) {
// If no parameters are given sslMode defaults to disabled
- var conn = MongoRunner.runMongod({clusterAuthMode: "keyFile"});
+ var conn = MongoRunner.runMongod({clusterAuthMode: "keyFile", keyFile: 'jstests/libs/key1'});
var adminDB = conn.getDB("admin");
adminDB.createUser({user: "root", pwd: "pwd", roles: ["root"]});
adminDB.auth("root", "pwd");
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index c30feb23528..b6036db8e53 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -306,6 +306,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
'server_options_core',
],
@@ -325,26 +326,8 @@ env.Clone().InjectModule("enterprise").Library(
'server_options',
'server_options_base',
],
-)
-
-# This library is linked into mongos and mongod only, not into the shell or any tools.
-env.Library(
- target="initialize_server_security_state",
- source=[
- "initialize_server_security_state.cpp",
- ],
- LIBDEPS=[
- "serverinit",
- ],
LIBDEPS_PRIVATE=[
- "$BUILD_DIR/mongo/client/authentication",
- "$BUILD_DIR/mongo/db/auth/auth",
- "$BUILD_DIR/mongo/db/auth/security_key",
- "$BUILD_DIR/mongo/rpc/metadata",
- "$BUILD_DIR/mongo/rpc/rpc",
- "$BUILD_DIR/mongo/util/net/ssl_manager",
- "$BUILD_DIR/mongo/util/net/ssl_parameters_auth",
- "auth/authorization_manager_global",
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
],
)
@@ -384,6 +367,7 @@ env.Library(
'mongod_options_storage.idl',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/repl/repl_settings',
'$BUILD_DIR/mongo/db/repl/replica_set_messages',
'$BUILD_DIR/mongo/db/storage/storage_options',
@@ -2097,7 +2081,6 @@ env.Library(
'index/index_access_methods',
'index/index_descriptor',
'index_builds_coordinator_mongod',
- 'initialize_server_security_state',
'initialize_snmp',
'introspect',
'keys_collection_client_direct',
@@ -2200,7 +2183,6 @@ env.Library(
'index/index_access_method_factory',
'index/index_access_methods',
'index_builds_coordinator_mongod',
- 'initialize_server_security_state',
'initialize_snmp',
'keys_collection_client_direct',
'kill_sessions',
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index f0e4da41fc7..6d1a9073014 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -33,6 +33,8 @@ env.Library(
'$BUILD_DIR/mongo/db/service_context',
],
LIBDEPS_PRIVATE=[
+ 'auth_options',
+ 'cluster_auth_mode',
'sasl_options',
],
)
@@ -131,6 +133,16 @@ env.Library(
)
env.Library(
+ target='cluster_auth_mode',
+ source=[
+ 'cluster_auth_mode.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
+)
+
+env.Library(
target='auth_options',
source=[
"auth_options.idl",
@@ -266,7 +278,12 @@ env.Library(
'authorization_manager_global_parameters.idl',
],
LIBDEPS_PRIVATE=[
+ "$BUILD_DIR/mongo/client/authentication",
'$BUILD_DIR/mongo/idl/server_parameter',
+ "$BUILD_DIR/mongo/util/net/ssl_manager",
+ "$BUILD_DIR/mongo/util/net/ssl_parameters_auth",
+ 'cluster_auth_mode',
+ 'security_key'
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/server_options_core',
@@ -290,6 +307,7 @@ env.Library(
'$BUILD_DIR/mongo/util/icu',
'$BUILD_DIR/mongo/util/md5',
'auth',
+ 'cluster_auth_mode',
'sasl_options',
'security_file',
'user',
@@ -396,6 +414,9 @@ env.Library(
'sasl_options',
'user',
],
+ LIBDEPS_PRIVATE=[
+ 'cluster_auth_mode',
+ ],
)
env.Library(
diff --git a/src/mongo/db/auth/auth_decorations.cpp b/src/mongo/db/auth/auth_decorations.cpp
index 9dc6ccf868e..c4eb1af64af 100644
--- a/src/mongo/db/auth/auth_decorations.cpp
+++ b/src/mongo/db/auth/auth_decorations.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/auth/sasl_options.h"
#include "mongo/db/client.h"
#include "mongo/db/commands/authentication_commands.h"
@@ -56,6 +57,9 @@ struct DisabledAuthMechanisms {
const auto getDisabledAuthMechanisms = ServiceContext::declareDecoration<DisabledAuthMechanisms>();
+const auto getClusterAuthMode =
+ ServiceContext::declareDecoration<synchronized_value<ClusterAuthMode>>();
+
class AuthzClientObserver final : public ServiceContext::ClientObserver {
public:
void onCreateClient(Client* client) override {
@@ -133,6 +137,21 @@ void AuthorizationSession::set(Client* client,
authzSession = std::move(authorizationSession);
}
+ClusterAuthMode ClusterAuthMode::get(ServiceContext* svcCtx) {
+ return getClusterAuthMode(svcCtx).get();
+}
+
+ClusterAuthMode ClusterAuthMode::set(ServiceContext* svcCtx, const ClusterAuthMode& mode) {
+ auto sv = getClusterAuthMode(svcCtx).synchronize();
+ if (!sv->canTransitionTo(mode)) {
+ uasserted(5579202,
+ fmt::format("Illegal state transition for clusterAuthMode from '{}' to '{}'",
+ sv->toString(),
+ mode.toString()));
+ }
+ return std::exchange(*sv, mode);
+}
+
void disableX509Auth(ServiceContext* svcCtx) {
getDisabledAuthMechanisms(svcCtx).x509 = true;
}
diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp
index 9a7651bb91f..b7a21b94fa5 100644
--- a/src/mongo/db/auth/authorization_manager_global.cpp
+++ b/src/mongo/db/auth/authorization_manager_global.cpp
@@ -29,13 +29,19 @@
#include "mongo/platform/basic.h"
+#include "mongo/client/authenticate.h"
+#include "mongo/config.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_manager_global_parameters_gen.h"
#include "mongo/db/auth/authz_manager_external_state.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
+#include "mongo/db/auth/sasl_command_constants.h"
+#include "mongo/db/auth/security_key.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/server_options.h"
#include "mongo/db/service_context.h"
#include "mongo/util/assert_util.h"
+#include "mongo/util/net/ssl_manager.h"
namespace mongo {
namespace {
@@ -44,11 +50,40 @@ ServiceContext::ConstructorActionRegisterer createAuthorizationManager(
"CreateAuthorizationManager",
{"OIDGeneration", "EndStartupOptionStorage"},
[](ServiceContext* service) {
+ // Officially set the ClusterAuthMode for this ServiceContext
+ ClusterAuthMode::set(service, serverGlobalParams.startupClusterAuthMode);
+
+ const auto clusterAuthMode = serverGlobalParams.startupClusterAuthMode;
+ const auto authIsEnabled =
+ serverGlobalParams.authState == ServerGlobalParams::AuthState::kEnabled;
+
auto authzManager = AuthorizationManager::create(service);
- authzManager->setAuthEnabled(serverGlobalParams.authState ==
- ServerGlobalParams::AuthState::kEnabled);
+ authzManager->setAuthEnabled(authIsEnabled);
authzManager->setShouldValidateAuthSchemaOnStartup(gStartupAuthSchemaValidation);
+
+ // Auto-enable auth unless we are in mixed auth/no-auth or clusterAuthMode was not provided.
+ // clusterAuthMode defaults to "keyFile" if a --keyFile parameter is provided.
+ if (clusterAuthMode.isDefined() && !serverGlobalParams.transitionToAuth) {
+ authzManager->setAuthEnabled(true);
+ }
AuthorizationManager::set(service, std::move(authzManager));
+
+ if (clusterAuthMode.allowsKeyFile()) {
+ // Load up the keys if we allow key files authentication.
+ const auto gotKeys = setUpSecurityKey(serverGlobalParams.keyFile, clusterAuthMode);
+ uassert(5579201, "Unable to acquire security key[s]", gotKeys);
+ }
+
+ if (clusterAuthMode.sendsX509()) {
+ // Send x509 authentication if we can.
+#ifdef MONGO_CONFIG_SSL
+ auth::setInternalUserAuthParams(auth::createInternalX509AuthDocument(
+ boost::optional<StringData>{SSLManagerCoordinator::get()
+ ->getSSLManager()
+ ->getSSLConfiguration()
+ .clientSubjectName.toString()}));
+#endif
+ }
});
} // namespace
diff --git a/src/mongo/db/auth/cluster_auth_mode.cpp b/src/mongo/db/auth/cluster_auth_mode.cpp
new file mode 100644
index 00000000000..6f8470981ab
--- /dev/null
+++ b/src/mongo/db/auth/cluster_auth_mode.cpp
@@ -0,0 +1,196 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kAccessControl
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/auth/cluster_auth_mode.h"
+
+#include "mongo/logv2/log.h"
+
+namespace mongo {
+namespace {
+constexpr auto kKeyFileStr = "keyFile"_sd;
+constexpr auto kSendKeyFileStr = "sendKeyFile"_sd;
+constexpr auto kSendX509Str = "sendX509"_sd;
+constexpr auto kX509Str = "x509"_sd;
+constexpr auto kUndefinedStr = "undefined"_sd;
+} // namespace
+
+StatusWith<ClusterAuthMode> ClusterAuthMode::parse(StringData strMode) {
+ if (strMode == kKeyFileStr) {
+ return ClusterAuthMode(Value::kKeyFile);
+ } else if (strMode == kSendKeyFileStr) {
+ return ClusterAuthMode(Value::kSendKeyFile);
+ } else if (strMode == kSendX509Str) {
+ return ClusterAuthMode(Value::kSendX509);
+ } else if (strMode == kX509Str) {
+ return ClusterAuthMode(Value::kX509);
+ } else {
+ return Status(ErrorCodes::BadValue,
+ str::stream() << "Invalid clusterAuthMode '" << strMode << "'");
+ }
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::isDefined() const {
+ switch (_value) {
+ case Value::kUndefined:
+ return false;
+ case Value::kX509:
+ case Value::kKeyFile:
+ case Value::kSendKeyFile:
+ case Value::kSendX509:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::canTransitionTo(const ClusterAuthMode& mode) const {
+ switch (_value) {
+ case Value::kUndefined:
+ return true;
+ case Value::kKeyFile:
+ return mode._value == Value::kSendKeyFile;
+ case Value::kSendKeyFile:
+ return mode._value == Value::kSendX509;
+ case Value::kSendX509:
+ return mode._value == Value::kX509;
+ case Value::kX509:
+ return false;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::keyFileOnly() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kSendKeyFile:
+ case Value::kSendX509:
+ case Value::kX509:
+ return false;
+ case Value::kKeyFile:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::allowsKeyFile() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kX509:
+ return false;
+ case Value::kKeyFile:
+ case Value::kSendKeyFile:
+ case Value::kSendX509:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::allowsX509() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kKeyFile:
+ return false;
+ case Value::kSendKeyFile:
+ case Value::kSendX509:
+ case Value::kX509:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::sendsKeyFile() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kSendX509:
+ case Value::kX509:
+ return false;
+ case Value::kKeyFile:
+ case Value::kSendKeyFile:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::sendsX509() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kKeyFile:
+ case Value::kSendKeyFile:
+ return false;
+ case Value::kSendX509:
+ case Value::kX509:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+bool ClusterAuthMode::x509Only() const {
+ switch (_value) {
+ case Value::kUndefined:
+ case Value::kKeyFile:
+ case Value::kSendKeyFile:
+ case Value::kSendX509:
+ return false;
+ case Value::kX509:
+ return true;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+StringData ClusterAuthMode::toString() const {
+ switch (_value) {
+ case Value::kUndefined:
+ return kUndefinedStr;
+ case Value::kKeyFile:
+ return kKeyFileStr;
+ case Value::kSendKeyFile:
+ return kSendKeyFileStr;
+ case Value::kSendX509:
+ return kSendX509Str;
+ case Value::kX509:
+ return kX509Str;
+ };
+
+ MONGO_UNREACHABLE;
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/auth/cluster_auth_mode.h b/src/mongo/db/auth/cluster_auth_mode.h
new file mode 100644
index 00000000000..a46a0922071
--- /dev/null
+++ b/src/mongo/db/auth/cluster_auth_mode.h
@@ -0,0 +1,150 @@
+/**
+ * Copyright (C) 2021-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/base/status_with.h"
+#include "mongo/base/string_data.h"
+
+namespace mongo {
+
+class ServiceContext;
+
+/**
+ * ClusterAuthMode is a thin wrapper around an enum for decorated storage and semantic utility.
+ */
+class ClusterAuthMode {
+ enum class Value {
+ kUndefined,
+ /**
+ * Authenticate using keyfile, accept only keyfiles
+ */
+ kKeyFile,
+
+ /**
+ * Authenticate using keyfile, accept both keyfiles and X.509
+ */
+ kSendKeyFile,
+
+ /**
+ * Authenticate using X.509, accept both keyfiles and X.509
+ */
+ kSendX509,
+
+ /**
+ * Authenticate using X.509, accept only X.509
+ */
+ kX509
+ };
+
+public:
+ /**
+ * Parse a string and return either a ClusterAuthMode or a not-okay Status.
+ */
+ static StatusWith<ClusterAuthMode> parse(StringData strMode);
+
+ /**
+ * Return a pre-constructed ClusterAuthMode for keyFile mode.
+ *
+ * This is used for implied-key file startup.
+ */
+ static ClusterAuthMode keyFile() {
+ return ClusterAuthMode(Value::kKeyFile);
+ }
+
+ /**
+ * Get the ClusterAuthMode associated with the given ServiceContext.
+ *
+ * This function is synchronized.
+ */
+ static ClusterAuthMode get(ServiceContext* svcCtx);
+
+ /**
+ * Set the ClusterAuthMode associated with a ServiceContext and return the previous mode.
+ *
+ * This function is synchronized.
+ */
+ static ClusterAuthMode set(ServiceContext* svcCtx, const ClusterAuthMode& mode);
+
+ ClusterAuthMode() = default;
+ ~ClusterAuthMode() = default;
+
+ /**
+ * Returns true if this mode is allowed to transition to the other mode.
+ */
+ bool canTransitionTo(const ClusterAuthMode& mode) const;
+
+ /**
+ * Returns true if this mode is defined.
+ */
+ bool isDefined() const;
+
+ /**
+ * Returns true if this mode allows x509 authentication as a server.
+ */
+ bool allowsX509() const;
+
+ /**
+ * Returns true if this mode allows key file authentication as a server.
+ */
+ bool allowsKeyFile() const;
+
+ /**
+ * Returns true if this mode sends x509 authentication as a client.
+ */
+ bool sendsX509() const;
+
+ /**
+ * Returns true if this mode sends key file authentication as a client.
+ */
+ bool sendsKeyFile() const;
+
+ /**
+ * Returns true if this mode only sends and receives x509 authentication.
+ */
+ bool x509Only() const;
+
+ /**
+ * Returns true if this mode only sends and receives keyfile authentication.
+ */
+ bool keyFileOnly() const;
+
+ /**
+ * Returns a constant string representing this mode.
+ */
+ StringData toString() const;
+
+private:
+ // For now, we can require that static functions are used to make modes.
+ ClusterAuthMode(Value value) : _value(value) {}
+
+ Value _value = Value::kUndefined;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/auth/sasl_scram_server_conversation.cpp b/src/mongo/db/auth/sasl_scram_server_conversation.cpp
index d92b4711c01..8273de3fbba 100644
--- a/src/mongo/db/auth/sasl_scram_server_conversation.cpp
+++ b/src/mongo/db/auth/sasl_scram_server_conversation.cpp
@@ -39,6 +39,7 @@
#include "mongo/base/string_data.h"
#include "mongo/crypto/mechanism_scram.h"
#include "mongo/crypto/sha1_block.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/auth/sasl_command_constants.h"
#include "mongo/db/auth/sasl_mechanism_policies.h"
#include "mongo/db/auth/sasl_mechanism_registry.h"
@@ -177,14 +178,26 @@ StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_fir
UserName user(ServerMechanismBase::ServerMechanismBase::_principalName,
ServerMechanismBase::getAuthenticationDatabase());
+ const auto isInternalUser = (user == internalSecurity.user->getName());
+ const auto clusterAuthMode = ClusterAuthMode::get(opCtx->getServiceContext());
+
// SERVER-16534, some mechanisms must be enabled for authenticating the internal user, so that
// cluster members may communicate with each other. Hence ignore disabled auth mechanism
// for the internal user.
- if (Policy::isInternalAuthMech() &&
- !sequenceContains(saslGlobalParams.authenticationMechanisms, Policy::getName()) &&
- user != internalSecurity.user->getName()) {
- return Status(ErrorCodes::BadValue,
- str::stream() << Policy::getName() << " authentication is disabled");
+ if (Policy::isInternalAuthMech()) {
+ if (isInternalUser) {
+ if (!clusterAuthMode.allowsKeyFile()) {
+ // We can no longer accept keyfiles.
+ return Status(ErrorCodes::BadValue,
+ str::stream() << Policy::getName()
+ << " is disallowed for cluster authentication");
+ }
+ } else {
+ if (!sequenceContains(saslGlobalParams.authenticationMechanisms, Policy::getName())) {
+ return Status(ErrorCodes::BadValue,
+ str::stream() << Policy::getName() << " authentication is disabled");
+ }
+ }
}
// The authentication database is also the source database for the user.
@@ -204,7 +217,7 @@ StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_fir
if (!scramCredentials.isValid()) {
// Check for authentication attempts of the __system user on
// systems started without a keyfile.
- if (userName == internalSecurity.user->getName()) {
+ if (isInternalUser) {
return Status(ErrorCodes::AuthenticationFailed,
"It is not possible to authenticate as the __system user "
"on servers started without a --keyFile parameter");
diff --git a/src/mongo/db/auth/security_key.cpp b/src/mongo/db/auth/security_key.cpp
index a9b012543fe..c09075d4f31 100644
--- a/src/mongo/db/auth/security_key.cpp
+++ b/src/mongo/db/auth/security_key.cpp
@@ -34,21 +34,15 @@
#include "mongo/db/auth/security_key.h"
#include <string>
-#include <sys/stat.h>
#include <vector>
#include "mongo/base/status_with.h"
-#include "mongo/client/authenticate.h"
+#include "mongo/client/internal_auth.h"
#include "mongo/crypto/mechanism_scram.h"
#include "mongo/crypto/sha1_block.h"
#include "mongo/crypto/sha256_block.h"
-#include "mongo/db/auth/action_set.h"
-#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
-#include "mongo/db/auth/privilege.h"
-#include "mongo/db/auth/sasl_command_constants.h"
#include "mongo/db/auth/sasl_options.h"
-#include "mongo/db/auth/sasl_scram_server_conversation.h"
#include "mongo/db/auth/security_file.h"
#include "mongo/db/auth/user.h"
#include "mongo/db/server_options.h"
@@ -135,7 +129,7 @@ private:
using std::string;
-bool setUpSecurityKey(const string& filename) {
+bool setUpSecurityKey(const string& filename, ClusterAuthMode mode) {
auto swKeyStrings = mongo::readSecurityFile(filename);
if (!swKeyStrings.isOK()) {
LOGV2(20254, "Read security file failed", "error"_attr = swKeyStrings.getStatus());
@@ -171,9 +165,7 @@ bool setUpSecurityKey(const string& filename) {
internalSecurity.alternateCredentials = std::move(*credentials);
}
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendKeyFile) {
+ if (mode.sendsKeyFile()) {
auth::setInternalAuthKeys(keyStrings);
}
diff --git a/src/mongo/db/auth/security_key.h b/src/mongo/db/auth/security_key.h
index 02a87aa5b23..bf53276994f 100644
--- a/src/mongo/db/auth/security_key.h
+++ b/src/mongo/db/auth/security_key.h
@@ -31,6 +31,8 @@
#include <string>
+#include "mongo/db/auth/cluster_auth_mode.h"
+
namespace mongo {
template <class T>
class StatusWith;
@@ -42,6 +44,6 @@ class StatusWith;
* @param filename the file containing the key
* @return if the key was successfully stored
*/
-bool setUpSecurityKey(const std::string& filename);
+bool setUpSecurityKey(const std::string& filename, ClusterAuthMode mode);
} // namespace mongo
diff --git a/src/mongo/db/auth/security_key_test.cpp b/src/mongo/db/auth/security_key_test.cpp
index fc1787b5962..1902eb93335 100644
--- a/src/mongo/db/auth/security_key_test.cpp
+++ b/src/mongo/db/auth/security_key_test.cpp
@@ -33,6 +33,7 @@
#include "mongo/base/string_data.h"
#include "mongo/db/auth/authorization_manager.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/auth/security_file.h"
#include "mongo/db/auth/security_key.h"
#include "mongo/unittest/unittest.h"
@@ -164,9 +165,9 @@ TEST(SecurityKey, Test) {
TestFile file(testCase.fileContents, testCase.mode != TestCase::FailureMode::Permissions);
if (testCase.mode == TestCase::FailureMode::Success) {
- ASSERT_TRUE(setUpSecurityKey(file.path().string()));
+ ASSERT_TRUE(setUpSecurityKey(file.path().string(), ClusterAuthMode::keyFile()));
} else {
- ASSERT_FALSE(setUpSecurityKey(file.path().string()));
+ ASSERT_FALSE(setUpSecurityKey(file.path().string(), ClusterAuthMode::keyFile()));
}
}
}
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 5b338058572..fe8996d0112 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -194,6 +194,7 @@ env.Library(
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/auth/authentication_session',
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/commands',
'$BUILD_DIR/mongo/rpc/client_metadata',
'$BUILD_DIR/mongo/util/net/ssl_manager',
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 9edc8bcc4d7..ba920d46e20 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -46,6 +46,7 @@
#include "mongo/db/auth/auth_options_gen.h"
#include "mongo/db/auth/authentication_session.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/security_key.h"
#include "mongo/db/auth/user_name.h"
@@ -269,6 +270,8 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
return opCtx->getClient()->session()->getTags() & transport::Session::kInternalClient;
};
+ const auto clusterAuthMode = ClusterAuthMode::get(opCtx->getServiceContext());
+
auto authorizeExternalUser = [&] {
uassert(ErrorCodes::BadValue,
kX509AuthenticationDisabledMessage,
@@ -278,31 +281,25 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
if (sslConfiguration->isClusterMember(clientName)) {
// Handle internal cluster member auth, only applies to server-server connections
- 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);
-
- authorizeExternalUser();
- } break;
- case ServerGlobalParams::ClusterAuthMode_sendKeyFile:
- case ServerGlobalParams::ClusterAuthMode_sendX509:
- case ServerGlobalParams::ClusterAuthMode_x509: {
- if (!isInternalClient()) {
- LOGV2_WARNING(
- 20430,
- "Client isn't a mongod or mongos, but is connecting with a certificate "
- "with cluster membership");
- }
-
- session->setAsClusterMember();
- authorizationSession->grantInternalAuthorization(client);
- } break;
- };
+ if (!clusterAuthMode.allowsX509()) {
+ 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);
+
+ authorizeExternalUser();
+ } else {
+ if (!isInternalClient()) {
+ LOGV2_WARNING(
+ 20430,
+ "Client isn't a mongod or mongos, but is connecting with a certificate "
+ "with cluster membership");
+ }
+
+ session->setAsClusterMember();
+ authorizationSession->grantInternalAuthorization(client);
+ }
} else {
// Handle normal client authentication, only applies to client-server connections
authorizeExternalUser();
diff --git a/src/mongo/db/initialize_server_security_state.cpp b/src/mongo/db/initialize_server_security_state.cpp
deleted file mode 100644
index 46a08632239..00000000000
--- a/src/mongo/db/initialize_server_security_state.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/initialize_server_global_state.h"
-
-#include "mongo/client/authenticate.h"
-#include "mongo/config.h"
-#include "mongo/db/auth/authorization_manager.h"
-#include "mongo/db/auth/sasl_command_constants.h"
-#include "mongo/db/auth/security_key.h"
-#include "mongo/db/server_options.h"
-#include "mongo/util/net/ssl_manager.h"
-
-namespace mongo {
-
-bool initializeServerSecurityGlobalState(ServiceContext* service) {
-
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
- if (!serverGlobalParams.keyFile.empty() &&
- clusterAuthMode != ServerGlobalParams::ClusterAuthMode_x509) {
- if (!setUpSecurityKey(serverGlobalParams.keyFile)) {
- // error message printed in setUpPrivateKey
- return false;
- }
- }
-
- // Auto-enable auth unless we are in mixed auth/no-auth or clusterAuthMode was not provided.
- // clusterAuthMode defaults to "keyFile" if a --keyFile parameter is provided.
- if (clusterAuthMode != ServerGlobalParams::ClusterAuthMode_undefined &&
- !serverGlobalParams.transitionToAuth) {
- AuthorizationManager::get(service)->setAuthEnabled(true);
- }
-
-#ifdef MONGO_CONFIG_SSL
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_x509 ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendX509) {
- auth::setInternalUserAuthParams(auth::createInternalX509AuthDocument(
- boost::optional<StringData>{SSLManagerCoordinator::get()
- ->getSSLManager()
- ->getSSLConfiguration()
- .clientSubjectName.toString()}));
- }
-#endif
-
- return true;
-}
-} // namespace mongo
diff --git a/src/mongo/db/initialize_server_security_state.h b/src/mongo/db/initialize_server_security_state.h
deleted file mode 100644
index d6c4d18b08e..00000000000
--- a/src/mongo/db/initialize_server_security_state.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright (C) 2018-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-namespace mongo {
-
-class ServiceContext;
-
-/**
- * Perform security initialization activity for mongod and mongos.
- */
-bool initializeServerSecurityGlobalState(ServiceContext* service);
-
-} // namespace mongo
diff --git a/src/mongo/db/mongod_main.cpp b/src/mongo/db/mongod_main.cpp
index e42e56c5f34..c14577624c5 100644
--- a/src/mongo/db/mongod_main.cpp
+++ b/src/mongo/db/mongod_main.cpp
@@ -88,7 +88,6 @@
#include "mongo/db/index_builds_coordinator_mongod.h"
#include "mongo/db/index_names.h"
#include "mongo/db/initialize_server_global_state.h"
-#include "mongo/db/initialize_server_security_state.h"
#include "mongo/db/initialize_snmp.h"
#include "mongo/db/introspect.h"
#include "mongo/db/json.h"
@@ -1468,9 +1467,6 @@ int mongod_main(int argc, char* argv[]) {
if (!initializeServerGlobalState(service))
quickExit(EXIT_FAILURE);
- if (!initializeServerSecurityGlobalState(service))
- quickExit(EXIT_FAILURE);
-
// There is no single-threaded guarantee beyond this point.
ThreadSafetyContext::getThreadSafetyContext()->allowMultiThreading();
diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp
index ee0bbd93040..881f83c1abc 100644
--- a/src/mongo/db/mongod_options.cpp
+++ b/src/mongo/db/mongod_options.cpp
@@ -41,6 +41,7 @@
#include "mongo/bson/json.h"
#include "mongo/bson/util/builder.h"
#include "mongo/config.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/cluster_auth_mode_option_gen.h"
#include "mongo/db/global_settings.h"
#include "mongo/db/keyfile_option_gen.h"
@@ -515,8 +516,8 @@ Status storeMongodOptions(const moe::Environment& params) {
if (!replSettings.getReplSetString().empty() &&
(params.count("security.authorization") &&
params["security.authorization"].as<std::string>() == "enabled") &&
- serverGlobalParams.clusterAuthMode.load() != ServerGlobalParams::ClusterAuthMode_x509 &&
- !params.count("security.keyFile")) {
+ !serverGlobalParams.startupClusterAuthMode.x509Only() &&
+ serverGlobalParams.keyFile.empty()) {
return Status(
ErrorCodes::BadValue,
str::stream()
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
index c14b522821e..7a5e3cd226f 100644
--- a/src/mongo/db/server_options.h
+++ b/src/mongo/db/server_options.h
@@ -29,6 +29,7 @@
#pragma once
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/jsobj.h"
#include "mongo/logv2/log_format.h"
#include "mongo/platform/atomic_word.h"
@@ -122,31 +123,9 @@ struct ServerGlobalParams {
AuthState authState = AuthState::kUndefined;
- bool transitionToAuth = false; // --transitionToAuth, mixed mode for rolling auth upgrade
- AtomicWord<int> clusterAuthMode; // --clusterAuthMode, the internal cluster auth mode
+ bool transitionToAuth = false; // --transitionToAuth, mixed mode for rolling auth upgrade
- enum ClusterAuthModes {
- ClusterAuthMode_undefined,
- /**
- * Authenticate using keyfile, accept only keyfiles
- */
- ClusterAuthMode_keyFile,
-
- /**
- * Authenticate using keyfile, accept both keyfiles and X.509
- */
- ClusterAuthMode_sendKeyFile,
-
- /**
- * Authenticate using X.509, accept both keyfiles and X.509
- */
- ClusterAuthMode_sendX509,
-
- /**
- * Authenticate using X.509, accept only X.509
- */
- ClusterAuthMode_x509
- };
+ ClusterAuthMode startupClusterAuthMode;
// for the YAML config, sharding._overrideShardIdentity. Can only be used when in
// queryableBackupMode.
diff --git a/src/mongo/db/server_options_base.cpp b/src/mongo/db/server_options_base.cpp
index 1cdda7e93d7..d8768dfcd02 100644
--- a/src/mongo/db/server_options_base.cpp
+++ b/src/mongo/db/server_options_base.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/server_options_base.h"
#include "mongo/base/string_data.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/server_options_base_gen.h"
#include "mongo/db/server_options_general_gen.h"
#include "mongo/logv2/log_component.h"
@@ -108,14 +109,7 @@ Status validateSystemLogDestinationSetting(const std::string& value) {
}
Status validateSecurityClusterAuthModeSetting(const std::string& value) {
- // keyFile|sendKeyFile|sendX509|x509
- constexpr auto kKeyFile = "keyFile"_sd;
- constexpr auto kSendKeyFile = "sendKeyFile"_sd;
- constexpr auto kSendX509 = "sendX509"_sd;
- constexpr auto kX509 = "X509"_sd;
-
- if (!kKeyFile.equalCaseInsensitive(value) && !kSendKeyFile.equalCaseInsensitive(value) &&
- !kSendX509.equalCaseInsensitive(value) && !kX509.equalCaseInsensitive(value)) {
+ if (!ClusterAuthMode::parse(value).isOK()) {
return {ErrorCodes::BadValue,
"security.clusterAuthMode expects one of 'keyFile', 'sendKeyFile', 'sendX509', or "
"'X509'"};
diff --git a/src/mongo/db/server_options_server_helpers.cpp b/src/mongo/db/server_options_server_helpers.cpp
index 641ce12cca6..57f05b16ba4 100644
--- a/src/mongo/db/server_options_server_helpers.cpp
+++ b/src/mongo/db/server_options_server_helpers.cpp
@@ -316,24 +316,10 @@ Status storeServerOptions(const moe::Environment& params) {
}
if (params.count("security.clusterAuthMode")) {
- std::string clusterAuthMode = params["security.clusterAuthMode"].as<std::string>();
-
- if (clusterAuthMode == "keyFile") {
- serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_keyFile);
- } else if (clusterAuthMode == "sendKeyFile") {
- serverGlobalParams.clusterAuthMode.store(
- ServerGlobalParams::ClusterAuthMode_sendKeyFile);
- } else if (clusterAuthMode == "sendX509") {
- serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_sendX509);
- } else if (clusterAuthMode == "x509") {
- serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_x509);
- } else {
- return Status(ErrorCodes::BadValue,
- "unsupported value for clusterAuthMode " + clusterAuthMode);
- }
+ const auto modeStr = params["security.clusterAuthMode"].as<std::string>();
+ serverGlobalParams.startupClusterAuthMode =
+ uassertStatusOK(ClusterAuthMode::parse(modeStr));
serverGlobalParams.authState = ServerGlobalParams::AuthState::kEnabled;
- } else {
- serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_undefined);
}
if (params.count("net.maxIncomingConnections")) {
@@ -432,12 +418,14 @@ Status storeServerOptions(const moe::Environment& params) {
}
if (!params.count("security.clusterAuthMode") && params.count("security.keyFile")) {
- serverGlobalParams.clusterAuthMode.store(ServerGlobalParams::ClusterAuthMode_keyFile);
+ serverGlobalParams.startupClusterAuthMode = ClusterAuthMode::keyFile();
}
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
+
+ const bool hasClusterAuthMode = serverGlobalParams.startupClusterAuthMode.isDefined();
if (serverGlobalParams.transitionToAuth &&
- (clusterAuthMode != ServerGlobalParams::ClusterAuthMode_keyFile &&
- clusterAuthMode != ServerGlobalParams::ClusterAuthMode_x509)) {
+ !(hasClusterAuthMode &&
+ (serverGlobalParams.startupClusterAuthMode.x509Only() ||
+ serverGlobalParams.startupClusterAuthMode.keyFileOnly()))) {
return Status(ErrorCodes::BadValue,
"--transitionToAuth must be used with keyFile or x509 authentication");
}
diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript
index 471839f6c4d..97ade90b2d8 100644
--- a/src/mongo/s/SConscript
+++ b/src/mongo/s/SConscript
@@ -434,7 +434,6 @@ env.Library(
'$BUILD_DIR/mongo/db/curop',
'$BUILD_DIR/mongo/db/dbdirectclient',
'$BUILD_DIR/mongo/db/ftdc/ftdc_mongos',
- '$BUILD_DIR/mongo/db/initialize_server_security_state',
'$BUILD_DIR/mongo/db/logical_session_cache',
'$BUILD_DIR/mongo/db/logical_session_cache_impl',
'$BUILD_DIR/mongo/db/logical_time_metadata_hook',
@@ -501,7 +500,6 @@ env.Library(
'$BUILD_DIR/mongo/db/auth/authmongos',
'$BUILD_DIR/mongo/db/commands/servers',
'$BUILD_DIR/mongo/db/ftdc/ftdc_mongos',
- '$BUILD_DIR/mongo/db/initialize_server_security_state',
'$BUILD_DIR/mongo/db/lasterror',
'$BUILD_DIR/mongo/db/log_process_details',
'$BUILD_DIR/mongo/db/read_write_concern_defaults',
diff --git a/src/mongo/s/mongos_main.cpp b/src/mongo/s/mongos_main.cpp
index 08d2d02da44..c0a2458ad26 100644
--- a/src/mongo/s/mongos_main.cpp
+++ b/src/mongo/s/mongos_main.cpp
@@ -54,7 +54,6 @@
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/ftdc/ftdc_mongos.h"
#include "mongo/db/initialize_server_global_state.h"
-#include "mongo/db/initialize_server_security_state.h"
#include "mongo/db/kill_sessions.h"
#include "mongo/db/lasterror.h"
#include "mongo/db/log_process_details.h"
@@ -938,9 +937,6 @@ ExitCode mongos_main(int argc, char* argv[]) {
if (!initializeServerGlobalState(service))
return EXIT_ABRUPT;
- if (!initializeServerSecurityGlobalState(service))
- quickExit(EXIT_FAILURE);
-
startSignalProcessingThread();
return main(service);
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index c81249eb0d8..11afd617e83 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -69,6 +69,7 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/auth/auth_options',
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
]
@@ -129,6 +130,7 @@ if not get_option('ssl') == 'off':
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/base/secure_allocator',
'$BUILD_DIR/mongo/crypto/sha_block_${MONGO_CRYPTO}',
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/idl/server_parameter',
@@ -147,6 +149,7 @@ if not get_option('ssl') == 'off':
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/client/authentication',
+ '$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/idl/server_parameter',
'ssl_options',
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index 31a858c8910..2f4a6fb713f 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -375,14 +375,14 @@ void SSLManagerCoordinator::rotate() {
std::shared_ptr<SSLManagerInterface> manager =
SSLManagerInterface::create(sslGlobalParams, isSSLServer);
- int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_x509 ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendX509) {
+ auto svcCtx = getGlobalServiceContext();
+ const auto clusterAuthMode = ClusterAuthMode::get(svcCtx);
+ if (clusterAuthMode.sendsX509()) {
auth::setInternalUserAuthParams(auth::createInternalX509AuthDocument(
StringData(manager->getSSLConfiguration().clientSubjectName.toString())));
}
- auto tl = getGlobalServiceContext()->getTransportLayer();
+ auto tl = svcCtx->getTransportLayer();
invariant(tl != nullptr);
uassertStatusOK(tl->rotateCertificates(manager, false));
diff --git a/src/mongo/util/net/ssl_options_server.cpp b/src/mongo/util/net/ssl_options_server.cpp
index 809befe82d8..4612993df07 100644
--- a/src/mongo/util/net/ssl_options_server.cpp
+++ b/src/mongo/util/net/ssl_options_server.cpp
@@ -190,7 +190,7 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
}
#endif
- const int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
+ const auto clusterAuthMode = serverGlobalParams.startupClusterAuthMode;
if (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled) {
bool usingCertifiateSelectors = params.count("net.tls.certificateSelector");
if (sslGlobalParams.sslPEMKeyFile.size() == 0 && !usingCertifiateSelectors) {
@@ -209,7 +209,7 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
// When using cetificate selectors, we use the local system certificate store for verifying
// X.509 certificates for auth instead of relying on a CA file.
if (sslGlobalParams.sslCAFile.empty() && !usingCertifiateSelectors &&
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_x509) {
+ clusterAuthMode.allowsX509()) {
uasserted(ErrorCodes::BadValue, sslCANotFoundError);
}
} else if (sslGlobalParams.sslPEMKeyFile.size() || sslGlobalParams.sslPEMKeyPassword.size() ||
@@ -227,9 +227,7 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
"using TLS configuration parameters");
}
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendKeyFile ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendX509 ||
- clusterAuthMode == ServerGlobalParams::ClusterAuthMode_x509) {
+ if (clusterAuthMode.allowsX509()) {
if (sslGlobalParams.sslMode.load() == SSLParams::SSLMode_disabled) {
uasserted(ErrorCodes::BadValue, "need to enable TLS via the tlsMode flag");
}
@@ -243,9 +241,7 @@ MONGO_STARTUP_OPTIONS_POST(SSLServerOptions)(InitializerContext*) {
if (sslGlobalParams.sslMode.load() == SSLParams::SSLMode_allowSSL) {
// allowSSL and x509 is valid only when we are transitioning to auth.
- if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_sendX509 ||
- (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_x509 &&
- !serverGlobalParams.transitionToAuth)) {
+ if (clusterAuthMode.sendsX509() && !serverGlobalParams.transitionToAuth) {
uasserted(ErrorCodes::BadValue,
"cannot have x.509 cluster authentication in allowTLS mode");
}
diff --git a/src/mongo/util/net/ssl_parameters.cpp b/src/mongo/util/net/ssl_parameters.cpp
index ba825cc2e23..b7a5ea78848 100644
--- a/src/mongo/util/net/ssl_parameters.cpp
+++ b/src/mongo/util/net/ssl_parameters.cpp
@@ -44,41 +44,6 @@
namespace mongo {
namespace {
-std::string clusterAuthModeFormat() {
- switch (serverGlobalParams.clusterAuthMode.load()) {
- case ServerGlobalParams::ClusterAuthMode_keyFile:
- return "keyFile";
- case ServerGlobalParams::ClusterAuthMode_sendKeyFile:
- return "sendKeyFile";
- case ServerGlobalParams::ClusterAuthMode_sendX509:
- return "sendX509";
- case ServerGlobalParams::ClusterAuthMode_x509:
- return "x509";
- default:
- // Default case because clusterAuthMode is an AtomicWord<int> and not bound by enum
- // rules.
- return "undefined";
- }
-}
-
-StatusWith<ServerGlobalParams::ClusterAuthModes> clusterAuthModeParse(StringData strMode) {
- if (strMode == "keyFile") {
- return ServerGlobalParams::ClusterAuthMode_keyFile;
- } else if (strMode == "sendKeyFile") {
- return ServerGlobalParams::ClusterAuthMode_sendKeyFile;
- } else if (strMode == "sendX509") {
- return ServerGlobalParams::ClusterAuthMode_sendX509;
- } else if (strMode == "x509") {
- return ServerGlobalParams::ClusterAuthMode_x509;
- } else {
- return Status(ErrorCodes::BadValue,
- str::stream()
- << "Invalid clusterAuthMode '" << strMode
- << "', expected one of: 'keyFile', 'sendKeyFile', 'sendX509', or 'x509'");
- }
-}
-
-
template <typename T, typename U>
StatusWith<SSLParams::SSLModes> checkTLSModeTransition(T modeToString,
U stringToMode,
diff --git a/src/mongo/util/net/ssl_parameters_auth.cpp b/src/mongo/util/net/ssl_parameters_auth.cpp
index 980c93df358..f88e2bd3302 100644
--- a/src/mongo/util/net/ssl_parameters_auth.cpp
+++ b/src/mongo/util/net/ssl_parameters_auth.cpp
@@ -32,84 +32,41 @@
#include "mongo/client/authenticate.h"
#include "mongo/config.h"
+#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/auth/sasl_command_constants.h"
#include "mongo/db/server_options.h"
#include "mongo/util/net/ssl_options.h"
#include "mongo/util/net/ssl_parameters_auth_gen.h"
namespace mongo {
-namespace {
-
-std::string clusterAuthModeFormat() {
- switch (serverGlobalParams.clusterAuthMode.load()) {
- case ServerGlobalParams::ClusterAuthMode_keyFile:
- return "keyFile";
- case ServerGlobalParams::ClusterAuthMode_sendKeyFile:
- return "sendKeyFile";
- case ServerGlobalParams::ClusterAuthMode_sendX509:
- return "sendX509";
- case ServerGlobalParams::ClusterAuthMode_x509:
- return "x509";
- default:
- // Default case because clusterAuthMode is an AtomicWord<int> and not bound by enum
- // rules.
- return "undefined";
- }
-}
-
-StatusWith<ServerGlobalParams::ClusterAuthModes> clusterAuthModeParse(StringData strMode) {
- if (strMode == "keyFile") {
- return ServerGlobalParams::ClusterAuthMode_keyFile;
- } else if (strMode == "sendKeyFile") {
- return ServerGlobalParams::ClusterAuthMode_sendKeyFile;
- } else if (strMode == "sendX509") {
- return ServerGlobalParams::ClusterAuthMode_sendX509;
- } else if (strMode == "x509") {
- return ServerGlobalParams::ClusterAuthMode_x509;
- } else {
- return Status(ErrorCodes::BadValue,
- str::stream()
- << "Invalid clusterAuthMode '" << strMode
- << "', expected one of: 'keyFile', 'sendKeyFile', 'sendX509', or 'x509'");
- }
-}
-
-} // namespace
void ClusterAuthModeServerParameter::append(OperationContext*,
BSONObjBuilder& builder,
const std::string& fieldName) {
- builder.append(fieldName, clusterAuthModeFormat());
+ const auto clusterAuthMode = ClusterAuthMode::get(getGlobalServiceContext());
+ builder.append(fieldName, clusterAuthMode.toString());
}
-Status ClusterAuthModeServerParameter::setFromString(const std::string& strMode) {
-
- auto swMode = clusterAuthModeParse(strMode);
- if (!swMode.isOK()) {
- return swMode.getStatus();
- }
+Status ClusterAuthModeServerParameter::setFromString(const std::string& strMode) try {
+ auto mode = uassertStatusOK(ClusterAuthMode::parse(strMode));
- auto mode = swMode.getValue();
- auto oldMode = serverGlobalParams.clusterAuthMode.load();
auto sslMode = sslGlobalParams.sslMode.load();
- if ((mode == ServerGlobalParams::ClusterAuthMode_sendX509) &&
- (oldMode == ServerGlobalParams::ClusterAuthMode_sendKeyFile)) {
+ if (mode.allowsX509()) {
if (sslMode == SSLParams::SSLMode_disabled || sslMode == SSLParams::SSLMode_allowSSL) {
return {ErrorCodes::BadValue,
"Illegal state transition for clusterAuthMode, need to enable SSL for outgoing "
"connections"};
}
- serverGlobalParams.clusterAuthMode.store(mode);
+ }
+
+ // Set our ingress mode, then our egress parameters.
+ ClusterAuthMode::set(getGlobalServiceContext(), mode);
+ if (mode.sendsX509()) {
auth::setInternalUserAuthParams(auth::createInternalX509AuthDocument());
- } else if ((mode == ServerGlobalParams::ClusterAuthMode_x509) &&
- (oldMode == ServerGlobalParams::ClusterAuthMode_sendX509)) {
- serverGlobalParams.clusterAuthMode.store(mode);
- } else {
- return {ErrorCodes::BadValue,
- str::stream() << "Illegal state transition for clusterAuthMode, change from "
- << clusterAuthModeFormat() << " to " << strMode};
}
return Status::OK();
+} catch (const DBException& ex) {
+ return ex.toStatus();
}
} // namespace mongo