diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2020-04-20 14:34:56 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-04-29 17:26:40 +0000 |
commit | 09c727b590720420f3cb206fe53931810638c336 (patch) | |
tree | 47a22b4ab7b80df6f6e8a0f01fff5c6980223abe | |
parent | 64541a43da9df2cc0b5dbd79a872469116f61504 (diff) | |
download | mongo-09c727b590720420f3cb206fe53931810638c336.tar.gz |
SERVER-47429 Validate authenticationMechanisms server parameter
(cherry picked from commit 817a7f1951189b2a8c7c06fb5fb5361241c1cd57)
-rw-r--r-- | jstests/auth/validate_sasl_mechanism.js | 23 | ||||
-rw-r--r-- | src/mongo/db/auth/sasl_mechanism_registry.cpp | 43 | ||||
-rw-r--r-- | src/mongo/db/auth/sasl_mechanism_registry.h | 3 | ||||
-rw-r--r-- | src/mongo/db/service_context.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/service_context.h | 17 |
5 files changed, 97 insertions, 1 deletions
diff --git a/jstests/auth/validate_sasl_mechanism.js b/jstests/auth/validate_sasl_mechanism.js new file mode 100644 index 00000000000..cae29ae83b0 --- /dev/null +++ b/jstests/auth/validate_sasl_mechanism.js @@ -0,0 +1,23 @@ +// Test for invalid sasl auth mechanisms + +(function() { +'use strict'; + +function waitFailedToStart(pid, exitCode) { + assert.soon(function() { + const res = checkProgram(pid); + if (res.alive) { + return false; + } + + return res.exitCode == exitCode; + }, `Failed to wait for ${pid} to die with exit code ${exitCode}`, 30 * 1000); +} + +const m = MongoRunner.runMongod({ + setParameter: "authenticationMechanisms=SCRAM-SHA-1,foo", + waitForConnect: false, +}); + +waitFailedToStart(m.pid, 2); +})(); diff --git a/src/mongo/db/auth/sasl_mechanism_registry.cpp b/src/mongo/db/auth/sasl_mechanism_registry.cpp index bfe479143d3..090e5cf08d6 100644 --- a/src/mongo/db/auth/sasl_mechanism_registry.cpp +++ b/src/mongo/db/auth/sasl_mechanism_registry.cpp @@ -33,11 +33,13 @@ #include "mongo/db/auth/sasl_mechanism_registry.h" #include "mongo/base/init.h" +#include "mongo/client/authenticate.h" #include "mongo/db/auth/sasl_options.h" #include "mongo/db/auth/user.h" #include "mongo/util/icu.h" #include "mongo/util/log.h" #include "mongo/util/net/socket_utils.h" +#include "mongo/util/quick_exit.h" #include "mongo/util/scopeguard.h" #include "mongo/util/sequence_util.h" @@ -144,6 +146,26 @@ bool SASLServerMechanismRegistry::_mechanismSupportedByConfig(StringData mechNam return sequenceContains(_enabledMechanisms, mechName); } +void appendMechs(const std::vector<std::unique_ptr<ServerFactoryBase>>& mechs, + std::vector<std::string>* pNames) { + std::transform(mechs.cbegin(), + mechs.cend(), + std::back_inserter(*pNames), + [](const std::unique_ptr<mongo::ServerFactoryBase>& factory) { + return factory->mechanismName().toString(); + }); +} + +std::vector<std::string> SASLServerMechanismRegistry::getMechanismNames() const { + std::vector<std::string> names; + names.reserve(_externalMechs.size() + _internalMechs.size()); + + appendMechs(_externalMechs, &names); + appendMechs(_internalMechs, &names); + + return names; +} + namespace { ServiceContext::ConstructorActionRegisterer SASLServerMechanismRegistryInitializer{ "CreateSASLServerMechanismRegistry", {"EndStartupOptionStorage"}, [](ServiceContext* service) { @@ -151,6 +173,27 @@ ServiceContext::ConstructorActionRegisterer SASLServerMechanismRegistryInitializ std::make_unique<SASLServerMechanismRegistry>( saslGlobalParams.authenticationMechanisms)); }}; + +ServiceContext::ConstructorActionRegisterer SASLServerMechanismRegistryValidationInitializer{ + "ValidateSASLServerMechanismRegistry", [](ServiceContext* service) { + auto supportedMechanisms = SASLServerMechanismRegistry::get(service).getMechanismNames(); + + // Manually include MONGODB-X509 since there is no factory for it since it not a SASL + // mechanism + supportedMechanisms.push_back(auth::kMechanismMongoX509.toString()); + + // Error if the user tries to use a SASL mechanism that does not exist + for (const auto& mech : saslGlobalParams.authenticationMechanisms) { + auto it = std::find(supportedMechanisms.cbegin(), supportedMechanisms.cend(), mech); + if (it == supportedMechanisms.end()) { + error() << "SASL Mechanism '" << mech << "' is not supported"; + + // Quick Exit since we are in the middle of setting up ServiceContext + quickExit(EXIT_BADOPTIONS); + } + } + }}; + } // namespace } // namespace mongo diff --git a/src/mongo/db/auth/sasl_mechanism_registry.h b/src/mongo/db/auth/sasl_mechanism_registry.h index d9366eaaf59..7e9b8eee95a 100644 --- a/src/mongo/db/auth/sasl_mechanism_registry.h +++ b/src/mongo/db/auth/sasl_mechanism_registry.h @@ -357,6 +357,8 @@ public: return true; } + std::vector<std::string> getMechanismNames() const; + private: using MechList = std::vector<std::unique_ptr<ServerFactoryBase>>; @@ -390,6 +392,7 @@ public: GlobalSASLMechanismRegisterer() { registerer.emplace(std::string(typeid(Factory).name()), std::vector<std::string>{"CreateSASLServerMechanismRegistry"}, + std::vector<std::string>{"ValidateSASLServerMechanismRegistry"}, [](ServiceContext* service) { SASLServerMechanismRegistry::get(service).registerFactory<Factory>(); }); diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp index f14fce1404c..836fffd5133 100644 --- a/src/mongo/db/service_context.cpp +++ b/src/mongo/db/service_context.cpp @@ -382,6 +382,15 @@ ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( std::string name, std::vector<std::string> prereqs, ConstructorAction constructor, + DestructorAction destructor) + : ConstructorActionRegisterer( + std::move(name), prereqs, {}, std::move(constructor), std::move(destructor)) {} + +ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( + std::string name, + std::vector<std::string> prereqs, + std::vector<std::string> dependents, + ConstructorAction constructor, DestructorAction destructor) { if (!destructor) destructor = [](ServiceContext*) {}; @@ -397,7 +406,8 @@ ServiceContext::ConstructorActionRegisterer::ConstructorActionRegisterer( registeredConstructorActions().erase(_iter); return Status::OK(); }, - std::move(prereqs)); + std::move(prereqs), + std::move(dependents)); } ServiceContext::UniqueServiceContext ServiceContext::make() { diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h index e3af71deab5..7fd3383da0c 100644 --- a/src/mongo/db/service_context.h +++ b/src/mongo/db/service_context.h @@ -271,6 +271,23 @@ public: ConstructorAction constructor, DestructorAction destructor = {}); + /** + * This constructor registers a constructor and optional destructor with the given + * "name", a list of names of prerequisites, "prereqs", and a list of names of dependents, + * "dependents". + * + * The named constructor will run after all of its prereqs successfully complete, + * and the corresponding destructor, if provided, will run before any of its + * prerequisites execute. The dependents will run after this constructor and + * the corresponding destructor, if provided, will run after any of its + * dependents execute. + */ + ConstructorActionRegisterer(std::string name, + std::vector<std::string> prereqs, + std::vector<std::string> dependents, + ConstructorAction constructor, + DestructorAction destructor = {}); + private: using ConstructorActionListIterator = stdx::list<ConstructorDestructorActions>::iterator; ConstructorActionListIterator _iter; |