summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2020-04-20 14:34:56 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-29 17:26:40 +0000
commit09c727b590720420f3cb206fe53931810638c336 (patch)
tree47a22b4ab7b80df6f6e8a0f01fff5c6980223abe
parent64541a43da9df2cc0b5dbd79a872469116f61504 (diff)
downloadmongo-09c727b590720420f3cb206fe53931810638c336.tar.gz
SERVER-47429 Validate authenticationMechanisms server parameter
(cherry picked from commit 817a7f1951189b2a8c7c06fb5fb5361241c1cd57)
-rw-r--r--jstests/auth/validate_sasl_mechanism.js23
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.cpp43
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.h3
-rw-r--r--src/mongo/db/service_context.cpp12
-rw-r--r--src/mongo/db/service_context.h17
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;