From c73b1c09eb5ce2053577abac0a4ba360e3845de8 Mon Sep 17 00:00:00 2001 From: Mark Benvenuto Date: Wed, 16 Jun 2021 10:41:25 -0400 Subject: SERVER-55792 Verify credentials when clusterAuthMode is set via setParameter --- jstests/ssl/set_parameter_ssl.js | 39 +++- jstests/sslSpecial/set_parameter_nossl.js | 2 +- src/mongo/db/SConscript | 24 +-- src/mongo/db/auth/SConscript | 21 +++ src/mongo/db/auth/auth_decorations.cpp | 19 ++ src/mongo/db/auth/authorization_manager_global.cpp | 39 +++- src/mongo/db/auth/cluster_auth_mode.cpp | 196 +++++++++++++++++++++ src/mongo/db/auth/cluster_auth_mode.h | 150 ++++++++++++++++ .../db/auth/sasl_scram_server_conversation.cpp | 25 ++- src/mongo/db/auth/security_key.cpp | 14 +- src/mongo/db/auth/security_key.h | 4 +- src/mongo/db/auth/security_key_test.cpp | 5 +- src/mongo/db/commands/SConscript | 1 + src/mongo/db/commands/authentication_commands.cpp | 47 +++-- src/mongo/db/initialize_server_security_state.cpp | 75 -------- src/mongo/db/initialize_server_security_state.h | 41 ----- src/mongo/db/mongod_main.cpp | 4 - src/mongo/db/mongod_options.cpp | 5 +- src/mongo/db/server_options.h | 27 +-- src/mongo/db/server_options_base.cpp | 10 +- src/mongo/db/server_options_server_helpers.cpp | 30 +--- src/mongo/s/SConscript | 2 - src/mongo/s/mongos_main.cpp | 4 - src/mongo/util/net/SConscript | 3 + src/mongo/util/net/ssl_manager.cpp | 8 +- src/mongo/util/net/ssl_options_server.cpp | 12 +- src/mongo/util/net/ssl_parameters.cpp | 35 ---- src/mongo/util/net/ssl_parameters_auth.cpp | 69 ++------ 28 files changed, 552 insertions(+), 359 deletions(-) create mode 100644 src/mongo/db/auth/cluster_auth_mode.cpp create mode 100644 src/mongo/db/auth/cluster_auth_mode.h delete mode 100644 src/mongo/db/initialize_server_security_state.cpp delete mode 100644 src/mongo/db/initialize_server_security_state.h 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', ], ) @@ -130,6 +132,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=[ @@ -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(); +const auto getClusterAuthMode = + ServiceContext::declareDecoration>(); + 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{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 + * . + * + * 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::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 + * . + * + * 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 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> SaslSCRAMServerMechanism::_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> SaslSCRAMServerMechanism::_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 -#include #include #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 +#include "mongo/db/auth/cluster_auth_mode.h" + namespace mongo { template 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 - * . - * - * 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{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 - * . - * - * 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() == "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 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(); - - 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(); + 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 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 and not bound by enum - // rules. - return "undefined"; - } -} - -StatusWith 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 StatusWith 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 and not bound by enum - // rules. - return "undefined"; - } -} - -StatusWith 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 -- cgit v1.2.1