diff options
author | Jonathan Reams <jbreams@mongodb.com> | 2018-12-19 13:41:40 -0500 |
---|---|---|
committer | Jonathan Reams <jbreams@mongodb.com> | 2019-01-03 17:18:52 -0500 |
commit | b7c5662bbb9c1e0c562b0dcf700547f387911661 (patch) | |
tree | 30f6382d1e103830067cab8b54306759f7d85214 /src/mongo/util | |
parent | 310b84d607506406c78925693b4bf71dd95e35e5 (diff) | |
download | mongo-b7c5662bbb9c1e0c562b0dcf700547f387911661.tar.gz |
SERVER-37835 Support rolling over X509 cluster auth certificates
Diffstat (limited to 'src/mongo/util')
-rwxr-xr-x | src/mongo/util/generate_icu_init_cpp.py | 3 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 155 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_apple.cpp | 3 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_openssl.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_windows.cpp | 3 |
5 files changed, 124 insertions, 42 deletions
diff --git a/src/mongo/util/generate_icu_init_cpp.py b/src/mongo/util/generate_icu_init_cpp.py index a95740b8c75..56f11217eca 100755 --- a/src/mongo/util/generate_icu_init_cpp.py +++ b/src/mongo/util/generate_icu_init_cpp.py @@ -101,7 +101,8 @@ alignas(16) const uint8_t kRawData[] = {%(decimal_encoded_data)s}; } // namespace -MONGO_INITIALIZER(LoadICUData)(InitializerContext* context) { +MONGO_INITIALIZER_GENERAL(LoadICUData, MONGO_NO_PREREQUISITES, ("BeginStartupOptionHandling"))( + InitializerContext* context) { UErrorCode status = U_ZERO_ERROR; udata_setCommonData(kRawData, &status); fassert(40088, U_SUCCESS(status)); diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index a6c59494748..ac772a97a01 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -288,6 +288,114 @@ constexpr int kASN1TeletexString = 20; constexpr int kASN1UniversalString = 28; constexpr int kASN1BMPString = 30; constexpr int kASN1OctetString = 4; + +void canonicalizeClusterDN(std::vector<std::string>* dn) { + // remove all RDNs we don't care about + for (size_t i = 0; i < dn->size(); i++) { + std::string& comp = dn->at(i); + boost::algorithm::trim(comp); + if (!mongoutils::str::startsWith(comp.c_str(), "DC=") && + !mongoutils::str::startsWith(comp.c_str(), "O=") && + !mongoutils::str::startsWith(comp.c_str(), "OU=")) { + dn->erase(dn->begin() + i); + i--; + } + } + std::stable_sort(dn->begin(), dn->end()); +} + +constexpr StringData kOID_DC = "0.9.2342.19200300.100.1.25"_sd; +constexpr StringData kOID_O = "2.5.4.10"_sd; +constexpr StringData kOID_OU = "2.5.4.11"_sd; + +std::vector<SSLX509Name::Entry> canonicalizeClusterDN( + const std::vector<std::vector<SSLX509Name::Entry>>& entries) { + std::vector<SSLX509Name::Entry> ret; + + for (const auto& rdn : entries) { + for (const auto& entry : rdn) { + if ((entry.oid != kOID_DC) && (entry.oid != kOID_O) && (entry.oid != kOID_OU)) { + continue; + } + ret.push_back(entry); + } + } + std::stable_sort(ret.begin(), ret.end()); + return ret; +} + +class ClusterMemberDNOverride : public ServerParameter { +public: + ClusterMemberDNOverride() + : ServerParameter( + ServerParameterSet::getGlobal(), "tlsX509ClusterAuthDNOverride", true, true) {} + + void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) override { + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (!_value) { + return; + } + + b.append(name, _value->fullDN.toString()); + } + + Status set(const BSONElement& newValueElement) override { + if (newValueElement.type() != String) { + return {ErrorCodes::BadValue, "DN must be a string"}; + } + return setFromString(newValueElement.String()); + } + + Status setFromString(const std::string& str) override { + if (str.empty()) { + stdx::lock_guard<stdx::mutex> lk(_mutex); + _value = boost::none; + return Status::OK(); + } + + auto swDN = parseDN(str); + if (!swDN.isOK()) { + return swDN.getStatus(); + } + auto dn = std::move(swDN.getValue()); + auto status = dn.normalizeStrings(); + if (!status.isOK()) { + return status; + } + + DNValue val(std::move(dn)); + if (val.canonicalized.empty()) { + return {ErrorCodes::BadValue, + "Cluster member DN's must contain at least one O, OU, or DC component"}; + } + + stdx::lock_guard<stdx::mutex> lk(_mutex); + _value = {std::move(val)}; + + return Status::OK(); + } + + boost::optional<std::vector<SSLX509Name::Entry>> getCanonical() { + stdx::lock_guard<stdx::mutex> lk(_mutex); + if (!_value) { + return boost::none; + } + return _value->canonicalized; + } + +private: + struct DNValue { + explicit DNValue(SSLX509Name dn) + : fullDN(std::move(dn)), canonicalized(canonicalizeClusterDN(fullDN.entries())) {} + + SSLX509Name fullDN; + std::vector<SSLX509Name::Entry> canonicalized; + }; + + stdx::mutex _mutex; + boost::optional<DNValue> _value; +} clusterMemberDNOverrideParameter; + } // namespace StatusWith<SSLX509Name> parseDN(StringData sd) try { @@ -537,43 +645,6 @@ std::string SSLX509Name::toString() const { return os.str(); } -namespace { -void canonicalizeClusterDN(std::vector<std::string>* dn) { - // remove all RDNs we don't care about - for (size_t i = 0; i < dn->size(); i++) { - std::string& comp = dn->at(i); - boost::algorithm::trim(comp); - if (!mongoutils::str::startsWith(comp.c_str(), "DC=") && - !mongoutils::str::startsWith(comp.c_str(), "O=") && - !mongoutils::str::startsWith(comp.c_str(), "OU=")) { - dn->erase(dn->begin() + i); - i--; - } - } - std::stable_sort(dn->begin(), dn->end()); -} - -constexpr StringData kOID_DC = "0.9.2342.19200300.100.1.25"_sd; -constexpr StringData kOID_O = "2.5.4.10"_sd; -constexpr StringData kOID_OU = "2.5.4.11"_sd; - -std::vector<SSLX509Name::Entry> canonicalizeClusterDN( - const std::vector<std::vector<SSLX509Name::Entry>>& entries) { - std::vector<SSLX509Name::Entry> ret; - - for (const auto& rdn : entries) { - for (const auto& entry : rdn) { - if ((entry.oid != kOID_DC) && (entry.oid != kOID_O) && (entry.oid != kOID_OU)) { - continue; - } - ret.push_back(entry); - } - } - std::stable_sort(ret.begin(), ret.end()); - return ret; -} -} // namespace - Status SSLConfiguration::setServerSubjectName(SSLX509Name name) { auto status = name.normalizeStrings(); if (!status.isOK()) { @@ -601,8 +672,16 @@ bool SSLConfiguration::isClusterMember(SSLX509Name subject) const { } auto client = canonicalizeClusterDN(subject.entries()); + if (client.empty()) { + return false; + } + + if (client == _canonicalServerSubjectName) { + return true; + } - return !client.empty() && (client == _canonicalServerSubjectName); + auto altClusterDN = clusterMemberDNOverrideParameter.getCanonical(); + return (altClusterDN && (client == *altClusterDN)); } bool SSLConfiguration::isClusterMember(StringData subjectName) const { diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp index 30de09c63c1..702981323b8 100644 --- a/src/mongo/util/net/ssl_manager_apple.cpp +++ b/src/mongo/util/net/ssl_manager_apple.cpp @@ -1559,7 +1559,8 @@ std::unique_ptr<SSLManagerInterface> SSLManagerInterface::create(const SSLParams return stdx::make_unique<SSLManagerApple>(params, isServer); } -MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("LoadICUData"))(InitializerContext*) { +MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("EndStartupOptionHandling")) +(InitializerContext*) { kMongoDBRolesOID = ::CFStringCreateWithCString( nullptr, mongodbRolesOID.identifier.c_str(), ::kCFStringEncodingUTF8); diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index 11a0ebc4dcb..61f794363eb 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -662,7 +662,7 @@ MONGO_INITIALIZER(SetupOpenSSL)(InitializerContext*) { return Status::OK(); } -MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("SetupOpenSSL", "LoadICUData")) +MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("SetupOpenSSL", "EndStartupOptionHandling")) (InitializerContext*) { stdx::lock_guard<SimpleMutex> lck(sslManagerMtx); if (!isSSLServer || (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled)) { diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp index 7feee26e213..de9854ed536 100644 --- a/src/mongo/util/net/ssl_manager_windows.cpp +++ b/src/mongo/util/net/ssl_manager_windows.cpp @@ -344,7 +344,8 @@ private: UniqueCertificate _sslClusterCertificate; }; -MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("LoadICUData"))(InitializerContext*) { +MONGO_INITIALIZER_WITH_PREREQUISITES(SSLManager, ("EndStartupOptionHandling")) +(InitializerContext*) { stdx::lock_guard<SimpleMutex> lck(sslManagerMtx); if (!isSSLServer || (sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled)) { theSSLManager = new SSLManagerWindows(sslGlobalParams, isSSLServer); |