summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2018-09-17 18:31:30 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2018-10-29 16:53:50 -0400
commitc377f378176e34987babf95db8ed70a12ce44b4f (patch)
tree73ed0318d5c67367915a35dda0b182d33bd24047 /src/mongo
parent8fd826de50666df19bb86158d7aa8753f98a152f (diff)
downloadmongo-c377f378176e34987babf95db8ed70a12ce44b4f.tar.gz
SERVER-36250 Add support for optionally logging specific negotiated TLS versions
(cherry picked from commit 0780841a51470b33105ec2b0a7831531b82d0a8d)
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/transport/session_asio.h4
-rw-r--r--src/mongo/util/net/SConscript1
-rw-r--r--src/mongo/util/net/sock.cpp5
-rw-r--r--src/mongo/util/net/ssl_manager.cpp40
-rw-r--r--src/mongo/util/net/ssl_manager.h29
-rw-r--r--src/mongo/util/net/ssl_manager_apple.cpp47
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp38
-rw-r--r--src/mongo/util/net/ssl_manager_windows.cpp39
-rw-r--r--src/mongo/util/net/ssl_options.cpp42
-rw-r--r--src/mongo/util/net/ssl_options.h1
-rw-r--r--src/mongo/util/net/ssl_options_test.cpp272
11 files changed, 448 insertions, 70 deletions
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<boost::optional<SSLPeerInfo>> 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<TLSVersion> 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<boost::optional<SSLPeerInfo>> 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<const SSLConnectionApple*>(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<TLSVersion> 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<boost::optional<SSLPeerInfo>> 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<boost::optional<SSLPeerInfo>> 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<TLSVersion> 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<boost::optional<SSLPeerInfo>> 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<boost::optional<SSLPeerInfo>> 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<const SSLConnectionOpenSSL*>(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<boost::optional<SSLPeerInfo>> 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<SSLConnectionWindows*>(static_cast<const SSLConnectionWindows*>(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<TLSVersion> 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<boost::optional<SSLPeerInfo>> 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<std::string, SSLParams::Protocols> 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<string>());
+ if (!status.isOK()) {
+ return status;
+ }
+ }
+
if (params.count("net.ssl.weakCertificateValidation")) {
sslGlobalParams.sslWeakCertificateValidation =
params["net.ssl.weakCertificateValidation"].as<bool>();
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<Protocols> sslDisabledProtocols; // --sslDisabledProtocols
+ std::vector<Protocols> 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 <ostream>
+#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<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--sslMode");
+ argv.push_back("disabled");
+ std::map<std::string, std::string> 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<std::string> 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<std::string, std::string> 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<int>(::mongo::sslGlobalParams.sslDisabledProtocols.back()),
+ static_cast<int>(::mongo::SSLParams::Protocols::TLS1_1));
+ ASSERT_EQ(static_cast<int>(::mongo::sslGlobalParams.tlsLogVersions.back()),
+ static_cast<int>(::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<std::string> 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<std::string, std::string> 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<std::string> 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<std::string, std::string> 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<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--setParameter");
+ argv.push_back("disableNonSSLConnectionLogging=false");
+ std::map<std::string, std::string> 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<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--setParameter");
+ argv.push_back("disableNonTLSConnectionLogging=false");
+ std::map<std::string, std::string> 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<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--setParameter");
+ argv.push_back("disableNonSSLConnectionLogging=true");
+ std::map<std::string, std::string> 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<std::string> argv;
+ argv.push_back("binaryname");
+ argv.push_back("--setParameter");
+ argv.push_back("disableNonTLSConnectionLogging=true");
+ std::map<std::string, std::string> 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<std::string> 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<std::string, std::string> env_map;
+
+ ASSERT_OK(parser.run(options, argv, env_map, &environment));
+ ASSERT_NOT_OK(mongo::storeServerOptions(environment));
+}
+#endif
+
} // namespace
} // namespace mongo