From c377f378176e34987babf95db8ed70a12ce44b4f Mon Sep 17 00:00:00 2001 From: Mark Benvenuto Date: Mon, 17 Sep 2018 18:31:30 -0400 Subject: SERVER-36250 Add support for optionally logging specific negotiated TLS versions (cherry picked from commit 0780841a51470b33105ec2b0a7831531b82d0a8d) --- src/mongo/transport/session_asio.h | 4 +- src/mongo/util/net/SConscript | 1 + src/mongo/util/net/sock.cpp | 5 +- src/mongo/util/net/ssl_manager.cpp | 40 +++++ src/mongo/util/net/ssl_manager.h | 29 ++- src/mongo/util/net/ssl_manager_apple.cpp | 47 +++-- src/mongo/util/net/ssl_manager_openssl.cpp | 38 ++-- src/mongo/util/net/ssl_manager_windows.cpp | 39 ++--- src/mongo/util/net/ssl_options.cpp | 42 +++++ src/mongo/util/net/ssl_options.h | 1 + src/mongo/util/net/ssl_options_test.cpp | 272 +++++++++++++++++++++++++++++ 11 files changed, 448 insertions(+), 70 deletions(-) (limited to 'src/mongo') diff --git a/src/mongo/transport/session_asio.h b/src/mongo/transport/session_asio.h index 96cb9f3a4b3..7dee8878037 100644 --- a/src/mongo/transport/session_asio.h +++ b/src/mongo/transport/session_asio.h @@ -239,7 +239,7 @@ protected: auto sslManager = getSSLManager(); auto swPeerInfo = uassertStatusOK(sslManager->parseAndValidatePeerCertificate( - _sslSocket->native_handle(), target.host())); + _sslSocket->native_handle(), target.host(), target)); if (swPeerInfo) { SSLPeerInfo::forSession(shared_from_this()) = std::move(*swPeerInfo); @@ -618,7 +618,7 @@ private: if (sslPeerInfo.subjectName.empty()) { auto sslManager = getSSLManager(); auto swPeerInfo = sslManager->parseAndValidatePeerCertificate( - _sslSocket->native_handle(), ""); + _sslSocket->native_handle(), "", _remote); // The value of swPeerInfo is a bit complicated: // diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript index 1f9052fdb5b..ffb36bc4913 100644 --- a/src/mongo/util/net/SConscript +++ b/src/mongo/util/net/SConscript @@ -141,6 +141,7 @@ env.CppUnitTest( 'sock_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/server_options_servers', '$BUILD_DIR/mongo/util/fail_point', 'network', 'socket', diff --git a/src/mongo/util/net/sock.cpp b/src/mongo/util/net/sock.cpp index d94a67cf84e..311b713c8ae 100644 --- a/src/mongo/util/net/sock.cpp +++ b/src/mongo/util/net/sock.cpp @@ -242,7 +242,7 @@ bool Socket::secure(SSLManagerInterface* mgr, const std::string& remoteHost) { } _sslManager = mgr; _sslConnection.reset(_sslManager->connect(this)); - mgr->parseAndValidatePeerCertificateDeprecated(_sslConnection.get(), remoteHost); + mgr->parseAndValidatePeerCertificateDeprecated(_sslConnection.get(), remoteHost, HostAndPort()); return true; } @@ -260,7 +260,8 @@ SSLPeerInfo Socket::doSSLHandshake(const char* firstBytes, int len) { remoteString()); } _sslConnection.reset(_sslManager->accept(this, firstBytes, len)); - return _sslManager->parseAndValidatePeerCertificateDeprecated(_sslConnection.get(), ""); + return _sslManager->parseAndValidatePeerCertificateDeprecated( + _sslConnection.get(), "", HostAndPort()); } std::string Socket::getSNIServerName() const { diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index c2be5bd69aa..e4e189e23bc 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -727,6 +727,46 @@ public: } } tlsVersionStatus; +void recordTLSVersion(TLSVersion version, const HostAndPort& hostForLogging) { + StringData versionString; + auto& counts = mongo::TLSVersionCounts::get(getGlobalServiceContext()); + switch (version) { + case TLSVersion::kTLS10: + counts.tls10.addAndFetch(1); + if (std::find(sslGlobalParams.tlsLogVersions.cbegin(), + sslGlobalParams.tlsLogVersions.cend(), + SSLParams::Protocols::TLS1_0) != sslGlobalParams.tlsLogVersions.cend()) { + versionString = "1.0"_sd; + } + break; + case TLSVersion::kTLS11: + counts.tls11.addAndFetch(1); + if (std::find(sslGlobalParams.tlsLogVersions.cbegin(), + sslGlobalParams.tlsLogVersions.cend(), + SSLParams::Protocols::TLS1_1) != sslGlobalParams.tlsLogVersions.cend()) { + versionString = "1.1"_sd; + } + break; + case TLSVersion::kTLS12: + counts.tls12.addAndFetch(1); + if (std::find(sslGlobalParams.tlsLogVersions.cbegin(), + sslGlobalParams.tlsLogVersions.cend(), + SSLParams::Protocols::TLS1_2) != sslGlobalParams.tlsLogVersions.cend()) { + versionString = "1.2"_sd; + } + break; + default: + if (!sslGlobalParams.tlsLogVersions.empty()) { + versionString = "unkown"_sd; + } + break; + } + + if (!versionString.empty()) { + log() << "Accepted connection with TLS Version " << versionString << " from connection " + << hostForLogging; + } +} #endif diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h index f8884f30ebe..0a83de2b88b 100644 --- a/src/mongo/util/net/ssl_manager.h +++ b/src/mongo/util/net/ssl_manager.h @@ -162,7 +162,9 @@ public: * a StatusWith instead. */ virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated( - const SSLConnectionInterface* conn, const std::string& remoteHost) = 0; + const SSLConnectionInterface* conn, + const std::string& remoteHost, + const HostAndPort& hostForLogging) = 0; /** * Gets the SSLConfiguration containing all information about the current SSL setup @@ -203,7 +205,9 @@ public: * X509 authorization will be returned. */ virtual StatusWith> parseAndValidatePeerCertificate( - SSLConnectionType ssl, const std::string& remoteHost) = 0; + SSLConnectionType ssl, + const std::string& remoteHost, + const HostAndPort& hostForLogging) = 0; }; // Access SSL functions through this instance. @@ -234,5 +238,26 @@ std::string removeFQDNRoot(std::string name); */ std::string escapeRfc2253(StringData str); +/** + * Platform neutral TLS version enum + */ +enum class TLSVersion { + kUnknown, + kTLS10, + kTLS11, + kTLS12, +}; + +/** + * Map SSL version to platform-neutral enum. + */ +StatusWith mapTLSVersion(SSLConnectionType conn); + +/** + * Record information about TLS versions and optionally log the TLS version + */ +void recordTLSVersion(TLSVersion version, const HostAndPort& hostForLogging); + + } // namespace mongo #endif // #ifdef MONGO_CONFIG_SSL diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp index 4c31fa75fa9..f292c14bd6c 100644 --- a/src/mongo/util/net/ssl_manager_apple.cpp +++ b/src/mongo/util/net/ssl_manager_apple.cpp @@ -1062,10 +1062,13 @@ public: SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len) final; SSLPeerInfo parseAndValidatePeerCertificateDeprecated(const SSLConnectionInterface* conn, - const std::string& remoteHost) final; + const std::string& remoteHost, + const HostAndPort& hostForLogging) final; StatusWith> parseAndValidatePeerCertificate( - ::SSLContextRef conn, const std::string& remoteHost) final; + ::SSLContextRef conn, + const std::string& remoteHost, + const HostAndPort& hostForLogging) final; const SSLConfiguration& getSSLConfiguration() const final { return _sslConfiguration; @@ -1249,10 +1252,12 @@ SSLConnectionInterface* SSLManagerApple::accept(Socket* socket, const char* init } SSLPeerInfo SSLManagerApple::parseAndValidatePeerCertificateDeprecated( - const SSLConnectionInterface* conn, const std::string& remoteHost) { + const SSLConnectionInterface* conn, + const std::string& remoteHost, + const HostAndPort& hostForLogging) { auto ssl = checked_cast(conn)->get(); - auto swPeerSubjectName = parseAndValidatePeerCertificate(ssl, remoteHost); + auto swPeerSubjectName = parseAndValidatePeerCertificate(ssl, remoteHost, hostForLogging); // We can't use uassertStatusOK here because we need to throw a NetworkException. if (!swPeerSubjectName.isOK()) { throwSocketError(SocketErrorKind::CONNECT_ERROR, swPeerSubjectName.getStatus().reason()); @@ -1260,44 +1265,34 @@ SSLPeerInfo SSLManagerApple::parseAndValidatePeerCertificateDeprecated( return swPeerSubjectName.getValue().get_value_or(SSLPeerInfo()); } -void recordTLSVersion(::SSLContextRef ssl) { +StatusWith mapTLSVersion(SSLContextRef ssl) { ::SSLProtocol protocol; uassertOSStatusOK(::SSLGetNegotiatedProtocolVersion(ssl, &protocol)); - auto& counts = mongo::TLSVersionCounts::get(getGlobalServiceContext()); switch (protocol) { case kTLSProtocol1: - counts.tls10.addAndFetch(1); - break; + return TLSVersion::kTLS10; case kTLSProtocol11: - counts.tls11.addAndFetch(1); - break; + return TLSVersion::kTLS11; case kTLSProtocol12: - counts.tls12.addAndFetch(1); - break; - // case kTLSProtocol13: - // counts.tls13.addAndFetch(1); - // break; - case kSSLProtocolUnknown: - case kSSLProtocol2: - case kSSLProtocol3: - case kSSLProtocol3Only: - case kTLSProtocol1Only: - case kSSLProtocolAll: - case kDTLSProtocol1: + return TLSVersion::kTLS12; default: // Some system headers may define additional protocols, so suppress warnings. - // Do nothing - break; + return TLSVersion::kUnknown; } } StatusWith> SSLManagerApple::parseAndValidatePeerCertificate( - ::SSLContextRef ssl, const std::string& remoteHost) { + ::SSLContextRef ssl, const std::string& remoteHost, const HostAndPort& hostForLogging) { // Record TLS version stats - recordTLSVersion(ssl); + auto tlsVersionStatus = mapTLSVersion(ssl); + if (!tlsVersionStatus.isOK()) { + return tlsVersionStatus.getStatus(); + } + + recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging); /* While we always have a system CA via the Keychain, * we'll pretend not to in terms of validation if the server diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index 98b297bba55..5f08a469b6a 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -345,10 +345,11 @@ public: SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len) final; SSLPeerInfo parseAndValidatePeerCertificateDeprecated(const SSLConnectionInterface* conn, - const std::string& remoteHost) final; + const std::string& remoteHost, + const HostAndPort& hostForLogging) final; StatusWith> parseAndValidatePeerCertificate( - SSL* conn, const std::string& remoteHost) final; + SSL* conn, const std::string& remoteHost, const HostAndPort& hostForLogging) final; const SSLConfiguration& getSSLConfiguration() const final { return _sslConfiguration; @@ -1274,35 +1275,34 @@ SSLConnectionInterface* SSLManagerOpenSSL::accept(Socket* socket, } -void recordTLSVersion(const SSL* conn) { +StatusWith mapTLSVersion(SSL* conn) { int protocol = SSL_version(conn); - auto& counts = mongo::TLSVersionCounts::get(getGlobalServiceContext()); switch (protocol) { case TLS1_VERSION: - counts.tls10.addAndFetch(1); - break; + return TLSVersion::kTLS10; case TLS1_1_VERSION: - counts.tls11.addAndFetch(1); - break; + return TLSVersion::kTLS11; case TLS1_2_VERSION: - counts.tls12.addAndFetch(1); - break; + return TLSVersion::kTLS12; #ifdef TLS1_3_VERSION case TLS1_3_VERSION: - counts.tls13.addAndFetch(1); - break; + return TLSVersion::kTLS13; #endif default: - // Do nothing - break; + return TLSVersion::kUnknown; } } StatusWith> SSLManagerOpenSSL::parseAndValidatePeerCertificate( - SSL* conn, const std::string& remoteHost) { + SSL* conn, const std::string& remoteHost, const HostAndPort& hostForLogging) { + + auto tlsVersionStatus = mapTLSVersion(conn); + if (!tlsVersionStatus.isOK()) { + return tlsVersionStatus.getStatus(); + } - recordTLSVersion(conn); + recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging); if (!_sslConfiguration.hasCA && isSSLServer) return {boost::none}; @@ -1416,10 +1416,12 @@ StatusWith> SSLManagerOpenSSL::parseAndValidatePeer SSLPeerInfo SSLManagerOpenSSL::parseAndValidatePeerCertificateDeprecated( - const SSLConnectionInterface* connInterface, const std::string& remoteHost) { + const SSLConnectionInterface* connInterface, + const std::string& remoteHost, + const HostAndPort& hostForLogging) { const SSLConnectionOpenSSL* conn = checked_cast(connInterface); - auto swPeerSubjectName = parseAndValidatePeerCertificate(conn->ssl, remoteHost); + auto swPeerSubjectName = parseAndValidatePeerCertificate(conn->ssl, remoteHost, hostForLogging); // We can't use uassertStatusOK here because we need to throw a NetworkException. if (!swPeerSubjectName.isOK()) { throwSocketError(SocketErrorKind::CONNECT_ERROR, swPeerSubjectName.getStatus().reason()); diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp index 6581c752640..a45082c3dc9 100644 --- a/src/mongo/util/net/ssl_manager_windows.cpp +++ b/src/mongo/util/net/ssl_manager_windows.cpp @@ -274,10 +274,11 @@ public: SSLConnectionInterface* accept(Socket* socket, const char* initialBytes, int len) final; SSLPeerInfo parseAndValidatePeerCertificateDeprecated(const SSLConnectionInterface* conn, - const std::string& remoteHost) final; + const std::string& remoteHost, + const HostAndPort& hostForLogging) final; StatusWith> parseAndValidatePeerCertificate( - PCtxtHandle ssl, const std::string& remoteHost) final; + PCtxtHandle ssl, const std::string& remoteHost, const HostAndPort& hostForLogging) final; const SSLConfiguration& getSSLConfiguration() const final { @@ -1484,11 +1485,14 @@ Status SSLManagerWindows::_validateCertificate(PCCERT_CONTEXT cert, } SSLPeerInfo SSLManagerWindows::parseAndValidatePeerCertificateDeprecated( - const SSLConnectionInterface* conn, const std::string& remoteHost) { + const SSLConnectionInterface* conn, + const std::string& remoteHost, + const HostAndPort& hostForLogging) { auto swPeerSubjectName = parseAndValidatePeerCertificate( const_cast(static_cast(conn)) ->_engine.native_handle(), - remoteHost); + remoteHost, + hostForLogging); // We can't use uassertStatusOK here because we need to throw a SocketException. if (!swPeerSubjectName.isOK()) { throwSocketError(SocketErrorKind::CONNECT_ERROR, swPeerSubjectName.getStatus().reason()); @@ -1659,7 +1663,7 @@ Status validatePeerCertificate(const std::string& remoteHost, return Status::OK(); } -Status recordTLSVersion(PCtxtHandle ssl) { +StatusWith mapTLSVersion(PCtxtHandle ssl) { SecPkgContext_ConnectionInfo connInfo; SECURITY_STATUS ss = QueryContextAttributes(ssl, SECPKG_ATTR_CONNECTION_INFO, &connInfo); @@ -1670,37 +1674,32 @@ Status recordTLSVersion(PCtxtHandle ssl) { << ss); } - auto& counts = mongo::TLSVersionCounts::get(getGlobalServiceContext()); switch (connInfo.dwProtocol) { case SP_PROT_TLS1_CLIENT: case SP_PROT_TLS1_SERVER: - counts.tls10.addAndFetch(1); - break; + return TLSVersion::kTLS10; case SP_PROT_TLS1_1_CLIENT: case SP_PROT_TLS1_1_SERVER: - counts.tls11.addAndFetch(1); - break; + return TLSVersion::kTLS11; case SP_PROT_TLS1_2_CLIENT: case SP_PROT_TLS1_2_SERVER: - counts.tls12.addAndFetch(1); - break; + return TLSVersion::kTLS12; default: - // Do nothing - break; + return TLSVersion::kUnknown; } - - return Status::OK(); } StatusWith> SSLManagerWindows::parseAndValidatePeerCertificate( - PCtxtHandle ssl, const std::string& remoteHost) { + PCtxtHandle ssl, const std::string& remoteHost, const HostAndPort& hostForLogging) { PCCERT_CONTEXT cert; - auto countStatus = recordTLSVersion(ssl); - if (!countStatus.isOK()) { - return countStatus; + auto tlsVersionStatus = mapTLSVersion(ssl); + if (!tlsVersionStatus.isOK()) { + return tlsVersionStatus.getStatus(); } + recordTLSVersion(tlsVersionStatus.getValue(), hostForLogging); + if (!_sslConfiguration.hasCA && isSSLServer) return {boost::none}; diff --git a/src/mongo/util/net/ssl_options.cpp b/src/mongo/util/net/ssl_options.cpp index 2169798e30f..aebab2d48a9 100644 --- a/src/mongo/util/net/ssl_options.cpp +++ b/src/mongo/util/net/ssl_options.cpp @@ -230,6 +230,14 @@ Status addSSLServerOptions(moe::OptionSection* options) { moe::String, "Comma separated list of TLS protocols to disable [TLS1_0,TLS1_1,TLS1_2]"); + options + ->addOptionChaining( + "net.tls.logVersions", + "tlsLogVersions", + moe::String, + "Comma separated list of TLS protocols to log on connect [TLS1_0,TLS1_1,TLS1_2]") + .hidden(); + options->addOptionChaining("net.ssl.weakCertificateValidation", "sslWeakCertificateValidation", moe::Switch, @@ -277,6 +285,33 @@ Status addSSLServerOptions(moe::OptionSection* options) { return Status::OK(); } +Status storeTLSLogVersion(const std::string& loggedProtocols) { + // The tlsLogVersion field is composed of a comma separated list of protocols to + // log. First, tokenize the field. + const auto tokens = StringSplitter::split(loggedProtocols, ","); + + // All universally accepted tokens, and their corresponding enum representation. + const std::map validConfigs{ + {"TLS1_0", SSLParams::Protocols::TLS1_0}, + {"TLS1_1", SSLParams::Protocols::TLS1_1}, + {"TLS1_2", SSLParams::Protocols::TLS1_2}, + }; + + // Map the tokens to their enum values, and push them onto the list of logged protocols. + for (const std::string& token : tokens) { + auto mappedToken = validConfigs.find(token); + if (mappedToken != validConfigs.end()) { + sslGlobalParams.tlsLogVersions.push_back(mappedToken->second); + continue; + } + + return Status(ErrorCodes::BadValue, "Unrecognized tlsLogVersions '" + token + "'"); + } + + return Status::OK(); +} + + Status addSSLClientOptions(moe::OptionSection* options) { options->addOptionChaining("ssl", "ssl", moe::Switch, "use SSL for all connections"); @@ -474,6 +509,13 @@ Status storeSSLServerOptions(const moe::Environment& params) { #endif } + if (params.count("net.tls.logVersions")) { + const auto status = storeTLSLogVersion(params["net.tls.logVersions"].as()); + if (!status.isOK()) { + return status; + } + } + if (params.count("net.ssl.weakCertificateValidation")) { sslGlobalParams.sslWeakCertificateValidation = params["net.ssl.weakCertificateValidation"].as(); diff --git a/src/mongo/util/net/ssl_options.h b/src/mongo/util/net/ssl_options.h index 9679df7be98..ec756d94266 100644 --- a/src/mongo/util/net/ssl_options.h +++ b/src/mongo/util/net/ssl_options.h @@ -75,6 +75,7 @@ struct SSLParams { #endif std::vector sslDisabledProtocols; // --sslDisabledProtocols + std::vector tlsLogVersions; // --tlsLogVersion bool sslWeakCertificateValidation = false; // --sslWeakCertificateValidation bool sslFIPSMode = false; // --sslFIPSMode bool sslAllowInvalidCertificates = false; // --sslAllowInvalidCertificates diff --git a/src/mongo/util/net/ssl_options_test.cpp b/src/mongo/util/net/ssl_options_test.cpp index 37f5042af16..6184c52eb98 100644 --- a/src/mongo/util/net/ssl_options_test.cpp +++ b/src/mongo/util/net/ssl_options_test.cpp @@ -34,7 +34,15 @@ #include +#include "mongo/config.h" +#include "mongo/db/server_options_server_helpers.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/net/ssl_options.h" +#include "mongo/util/options_parser/environment.h" +#include "mongo/util/options_parser/option_section.h" +#include "mongo/util/options_parser/options_parser.h" + +namespace moe = mongo::optionenvironment; namespace mongo { namespace { @@ -83,5 +91,269 @@ TEST(SSLOptions, invalidCases) { "Invalid certificate selector value for 'option': Not a valid hex string"); } +class OptionsParserTester : public moe::OptionsParser { +public: + Status readConfigFile(const std::string& filename, std::string* config) { + if (filename != _filename) { + ::mongo::StringBuilder sb; + sb << "Parser using filename: " << filename + << " which does not match expected filename: " << _filename; + return Status(ErrorCodes::InternalError, sb.str()); + } + *config = _config; + return Status::OK(); + } + void setConfig(const std::string& filename, const std::string& config) { + _filename = filename; + _config = config; + } + +private: + std::string _filename; + std::string _config; +}; + +TEST(SetupOptions, sslModeDisabled) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--sslMode"); + argv.push_back("disabled"); + std::map env_map; + + ASSERT_OK(::mongo::addSSLServerOptions(&options)); + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + ASSERT_OK(::mongo::storeSSLServerOptions(environment)); + ASSERT_EQ(::mongo::sslGlobalParams.sslMode.load(), ::mongo::sslGlobalParams.SSLMode_disabled); +} + +TEST(SetupOptions, sslModeRequired) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::string sslPEMKeyFile = "jstests/libs/server.pem"; + std::string sslCAFFile = "jstests/libs/ca.pem"; + std::string sslCRLFile = "jstests/libs/crl.pem"; + std::string sslClusterFile = "jstests/libs/cluster_cert.pem"; + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--sslMode"); + argv.push_back("requireSSL"); + argv.push_back("--sslPEMKeyFile"); + argv.push_back(sslPEMKeyFile); + argv.push_back("--sslCAFile"); + argv.push_back(sslCAFFile); + argv.push_back("--sslCRLFile"); + argv.push_back(sslCRLFile); + argv.push_back("--sslClusterFile"); + argv.push_back(sslClusterFile); + argv.push_back("--sslAllowInvalidHostnames"); + argv.push_back("--sslAllowInvalidCertificates"); + argv.push_back("--sslWeakCertificateValidation"); + argv.push_back("--sslFIPSMode"); + argv.push_back("--sslPEMKeyPassword"); + argv.push_back("pw1"); + argv.push_back("--sslClusterPassword"); + argv.push_back("pw2"); + argv.push_back("--sslDisabledProtocols"); + argv.push_back("TLS1_1"); + argv.push_back("--tlsLogVersions"); + argv.push_back("TLS1_0"); + std::map env_map; + + ASSERT_OK(mongo::addSSLServerOptions(&options)); + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + ASSERT_OK(mongo::storeSSLServerOptions(environment)); + + ASSERT_EQ(::mongo::sslGlobalParams.sslMode.load(), ::mongo::sslGlobalParams.SSLMode_requireSSL); + ASSERT_EQ(::mongo::sslGlobalParams.sslPEMKeyFile.substr( + ::mongo::sslGlobalParams.sslPEMKeyFile.length() - sslPEMKeyFile.length()), + sslPEMKeyFile); + ASSERT_EQ(::mongo::sslGlobalParams.sslCAFile.substr( + ::mongo::sslGlobalParams.sslCAFile.length() - sslCAFFile.length()), + sslCAFFile); + ASSERT_EQ(::mongo::sslGlobalParams.sslCRLFile.substr( + ::mongo::sslGlobalParams.sslCRLFile.length() - sslCRLFile.length()), + sslCRLFile); + ASSERT_EQ(::mongo::sslGlobalParams.sslClusterFile.substr( + ::mongo::sslGlobalParams.sslClusterFile.length() - sslClusterFile.length()), + sslClusterFile); + ASSERT_EQ(::mongo::sslGlobalParams.sslAllowInvalidHostnames, true); + ASSERT_EQ(::mongo::sslGlobalParams.sslAllowInvalidCertificates, true); + ASSERT_EQ(::mongo::sslGlobalParams.sslWeakCertificateValidation, true); + ASSERT_EQ(::mongo::sslGlobalParams.sslFIPSMode, true); + ASSERT_EQ(::mongo::sslGlobalParams.sslPEMKeyPassword, "pw1"); + ASSERT_EQ(::mongo::sslGlobalParams.sslClusterPassword, "pw2"); + ASSERT_EQ(static_cast(::mongo::sslGlobalParams.sslDisabledProtocols.back()), + static_cast(::mongo::SSLParams::Protocols::TLS1_1)); + ASSERT_EQ(static_cast(::mongo::sslGlobalParams.tlsLogVersions.back()), + static_cast(::mongo::SSLParams::Protocols::TLS1_0)); +} + +#ifdef MONGO_CONFIG_SSL_CERTIFICATE_SELECTORS +TEST(SetupOptions, tlsModeRequiredCertificateSelector) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--tlsMode"); + argv.push_back("requireTLS"); + argv.push_back("--tlsCertificateSelector"); + argv.push_back("subject=Subject 1"); + argv.push_back("--tlsClusterCertificateSelector"); + argv.push_back("subject=Subject 2"); + std::map env_map; + + ASSERT_OK(mongo::addSSLServerOptions(&options)); + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + ASSERT_OK(mongo::storeSSLServerOptions(environment)); + + ASSERT_EQ(::mongo::sslGlobalParams.sslMode.load(), ::mongo::sslGlobalParams.SSLMode_requireSSL); + ASSERT_EQ(::mongo::sslGlobalParams.sslCertificateSelector.subject, "Subject 1"); + ASSERT_EQ(::mongo::sslGlobalParams.sslClusterCertificateSelector.subject, "Subject 2"); +} + +TEST(SetupOptions, sslModeRequiredCertificateSelector) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--sslMode"); + argv.push_back("requireSSL"); + argv.push_back("--sslCertificateSelector"); + argv.push_back("subject=Subject 1"); + argv.push_back("--sslClusterCertificateSelector"); + argv.push_back("subject=Subject 2"); + std::map env_map; + + ASSERT_OK(mongo::addSSLServerOptions(&options)); + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + ASSERT_OK(mongo::storeSSLServerOptions(environment)); + + ASSERT_EQ(::mongo::sslGlobalParams.sslMode.load(), ::mongo::sslGlobalParams.SSLMode_requireSSL); + ASSERT_EQ(::mongo::sslGlobalParams.sslCertificateSelector.subject, "Subject 1"); + ASSERT_EQ(::mongo::sslGlobalParams.sslClusterCertificateSelector.subject, "Subject 2"); +} + +TEST(SetupOptions, disableNonSSLConnectionLoggingFalse) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--setParameter"); + argv.push_back("disableNonSSLConnectionLogging=false"); + std::map env_map; + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + Status storeRet = mongo::storeServerOptions(environment); + + ASSERT_EQ(::mongo::sslGlobalParams.disableNonSSLConnectionLogging, false); +} + +TEST(SetupOptions, disableNonTLSConnectionLoggingFalse) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ::mongo::sslGlobalParams.disableNonSSLConnectionLoggingSet = false; + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--setParameter"); + argv.push_back("disableNonTLSConnectionLogging=false"); + std::map env_map; + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + Status storeRet = mongo::storeServerOptions(environment); + + ASSERT_EQ(::mongo::sslGlobalParams.disableNonSSLConnectionLogging, false); +} + +TEST(SetupOptions, disableNonSSLConnectionLoggingTrue) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ::mongo::sslGlobalParams.disableNonSSLConnectionLoggingSet = false; + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--setParameter"); + argv.push_back("disableNonSSLConnectionLogging=true"); + std::map env_map; + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + Status storeRet = mongo::storeServerOptions(environment); + + ASSERT_EQ(::mongo::sslGlobalParams.disableNonSSLConnectionLogging, true); +} + +TEST(SetupOptions, disableNonTLSConnectionLoggingTrue) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ::mongo::sslGlobalParams.disableNonSSLConnectionLoggingSet = false; + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--setParameter"); + argv.push_back("disableNonTLSConnectionLogging=true"); + std::map env_map; + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + Status storeRet = mongo::storeServerOptions(environment); + + ASSERT_EQ(::mongo::sslGlobalParams.disableNonSSLConnectionLogging, true); +} + +TEST(SetupOptions, disableNonTLSConnectionLoggingInvalid) { + OptionsParserTester parser; + moe::Environment environment; + moe::OptionSection options; + + ASSERT_OK(::mongo::addGeneralServerOptions(&options)); + + std::vector argv; + argv.push_back("binaryname"); + argv.push_back("--setParameter"); + argv.push_back("disableNonTLSConnectionLogging=false"); + argv.push_back("--setParameter"); + argv.push_back("disableNonSSLConnectionLogging=false"); + std::map env_map; + + ASSERT_OK(parser.run(options, argv, env_map, &environment)); + ASSERT_NOT_OK(mongo::storeServerOptions(environment)); +} +#endif + } // namespace } // namespace mongo -- cgit v1.2.1