diff options
author | Andrew Shuvalov <andrew.shuvalov@mongodb.com> | 2021-08-06 21:34:26 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-08-06 22:03:25 +0000 |
commit | a3124693d95c37633cca3935d3d2515f63222d22 (patch) | |
tree | 60187d39af1834c72b9357643cee21f6358f4cd2 | |
parent | 3f1695a90ae84726d560e02fb88b1521cde351d6 (diff) | |
download | mongo-a3124693d95c37633cca3935d3d2515f63222d22.tar.gz |
SERVER-59067: low level stress test for OpenSSL manager
-rw-r--r-- | src/mongo/util/net/ssl_manager_openssl.cpp | 10 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_test.cpp | 109 |
2 files changed, 118 insertions, 1 deletions
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index f847ce22706..563194e03c4 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -2686,7 +2686,7 @@ bool SSLManagerOpenSSL::_readCertificateChainFromMemory( #if OPENSSL_VERSION_NUMBER >= 0x100010fFL if (1 != SSL_CTX_add1_chain_cert(context, ca.get())) { #else - if (1 != SSL_CTX_add_extra_chain_cert(context, ca.release())) { + if (1 != SSL_CTX_add_extra_chain_cert(context, ca.get())) { #endif CaptureSSLErrorInAttrs capture(errorAttrs); LOGV2_ERROR( @@ -2695,6 +2695,10 @@ bool SSLManagerOpenSSL::_readCertificateChainFromMemory( } _getX509CertInfo(ca, &debugInfo, std::nullopt, targetClusterURI); logCert(debugInfo, "", 5159902); +#if OPENSSL_VERSION_NUMBER < 0x100010fFL + ca.release(); // Older version add_extra_chain_cert takes over the pointer without + // incrementing refcount. Avoid double free. +#endif } // When the while loop ends, it's usually just EOF. auto err = ERR_peek_last_error(); @@ -3462,6 +3466,10 @@ void SSLManagerOpenSSL::_getX509CertInfo(UniqueX509& x509, CertInformationToLog* info, std::optional<StringData> keyFile, std::optional<StringData> targetClusterURI) { + if (!x509) { + return; + } + info->subject = getCertificateSubjectX509Name(x509.get()); info->issuer = convertX509ToSSLX509Name(X509_get_issuer_name(x509.get())); diff --git a/src/mongo/util/net/ssl_manager_test.cpp b/src/mongo/util/net/ssl_manager_test.cpp index 72902a32106..acebdca5fd8 100644 --- a/src/mongo/util/net/ssl_manager_test.cpp +++ b/src/mongo/util/net/ssl_manager_test.cpp @@ -627,6 +627,115 @@ TEST(SSLManager, TransientSSLParams) { ASSERT_NOT_OK(tla.rotateCertificates(swContext.getValue()->manager, true)); } +#if OPENSSL_VERSION_NUMBER >= 0x100010fFL + +TEST(SSLManager, TransientSSLParamsStressTestWithTransport) { + static constexpr int kMaxContexts = 100; + static constexpr int kThreads = 10; + SSLParams params; + params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL); + params.sslCAFile = "jstests/libs/ca.pem"; + + ServiceEntryPointUtil sepu; + + auto options = [] { + ServerGlobalParams params; + params.noUnixSocket = true; + transport::TransportLayerASIO::Options opts(¶ms); + return opts; + }(); + transport::TransportLayerASIO tla(options, &sepu); + + TransientSSLParams transientSSLParams; + transientSSLParams.sslClusterPEMPayload = loadFile("jstests/libs/client.pem"); + transientSSLParams.targetedClusterConnectionString = ConnectionString::forLocal(); + + Mutex mutex = MONGO_MAKE_LATCH("::test_mutex"); + std::deque<std::shared_ptr<const transport::SSLConnectionContext>> contexts; + std::vector<stdx::thread> threads; + Counter64 iterations; + + for (int t = 0; t < kThreads; ++t) { + stdx::thread thread([&]() { + Timer timer; + while (timer.elapsed() < Seconds(2)) { + auto swContext = tla.createTransientSSLContext(transientSSLParams); + invariant(swContext.getStatus().isOK()); + std::shared_ptr<const transport::SSLConnectionContext> ctxToDelete; + { + auto lk = stdx::lock_guard(mutex); + contexts.push_back(std::move(swContext.getValue())); + if (contexts.size() > kMaxContexts) { + ctxToDelete = contexts.front(); + contexts.pop_front(); + } + } + iterations.increment(); + } + }); + threads.push_back(std::move(thread)); + } + for (auto& t : threads) { + t.join(); + } + + contexts.clear(); + LOGV2(5906701, "Stress test completed", "iterations"_attr = iterations); +} + +TEST(SSLManager, TransientSSLParamsStressTestWithManager) { + static constexpr int kMaxManagers = 100; + static constexpr int kThreads = 10; + SSLParams params; + params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL); + params.sslPEMKeyFile = "jstests/libs/server.pem"; + params.sslCAFile = "jstests/libs/ca.pem"; + + TransientSSLParams transientParams; + transientParams.sslClusterPEMPayload = loadFile("jstests/libs/client.pem"); + + Mutex mutex = MONGO_MAKE_LATCH("::test_mutex"); + std::deque<std::shared_ptr<SSLManagerInterface>> managers; + std::vector<stdx::thread> threads; + int iterations = 0; + + for (int t = 0; t < kThreads; ++t) { + stdx::thread thread([&]() { + Timer timer; + while (timer.elapsed() < Seconds(3)) { + std::shared_ptr<SSLManagerInterface> manager = + SSLManagerInterface::create(params, transientParams, true /* isSSLServer */); + + auto egress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23); + invariant(manager + ->initSSLContext(egress->native_handle(), + params, + SSLManagerInterface::ConnectionDirection::kOutgoing) + .isOK()); + std::shared_ptr<SSLManagerInterface> managerToDelete; + { + auto lk = stdx::lock_guard(mutex); + managers.push_back(std::move(manager)); + if (managers.size() > kMaxManagers) { + managerToDelete = managers.front(); + managers.pop_front(); + } + } + ++iterations; + } + }); + threads.push_back(std::move(thread)); + } + for (auto& t : threads) { + t.join(); + } + + managers.clear(); + LOGV2(5906702, "Stress test completed", "iterations"_attr = iterations); +} + +#endif // OPENSSL_VERSION_NUMBER >= 0x100010fFL + #endif // MONGO_CONFIG_SSL_PROVIDER == MONGO_CONFIG_SSL_PROVIDER_OPENSSL static bool isSanWarningWritten(const std::vector<std::string>& logLines) { |