summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Shuvalov <andrew.shuvalov@mongodb.com>2020-11-19 21:11:30 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-20 14:58:12 +0000
commitd3faf32669a87871992a8534cffab58d83377d79 (patch)
tree0e3302ac5eeffb47c237f609ad2328af91b4d2e9
parent1cabc1efdd46b045bd85189e142fd9b3fa65dc1a (diff)
downloadmongo-d3faf32669a87871992a8534cffab58d83377d79.tar.gz
SERVER-52710: wire up transient SSL parameters up to the NetworkInterface
-rw-r--r--buildscripts/resmokeconfig/suites/integration_tests_replset_ssl.yml35
-rw-r--r--src/mongo/executor/connection_pool.cpp10
-rw-r--r--src/mongo/executor/connection_pool.h11
-rw-r--r--src/mongo/executor/connection_pool_tl.cpp3
-rw-r--r--src/mongo/executor/connection_pool_tl.h12
-rw-r--r--src/mongo/executor/network_interface_tl.cpp20
-rw-r--r--src/mongo/executor/network_interface_tl.h1
-rw-r--r--src/mongo/transport/session_asio.h10
-rw-r--r--src/mongo/transport/ssl_connection_context.h5
-rw-r--r--src/mongo/transport/transport_layer.h11
-rw-r--r--src/mongo/transport/transport_layer_asio.cpp49
-rw-r--r--src/mongo/transport/transport_layer_asio.h22
-rw-r--r--src/mongo/transport/transport_layer_manager.cpp18
-rw-r--r--src/mongo/transport/transport_layer_manager.h8
-rw-r--r--src/mongo/transport/transport_layer_mock.cpp6
-rw-r--r--src/mongo/transport/transport_layer_mock.h4
-rw-r--r--src/mongo/util/net/SConscript21
-rw-r--r--src/mongo/util/net/network_interface_ssl_test.cpp75
-rw-r--r--src/mongo/util/net/ssl_manager_openssl.cpp12
-rw-r--r--src/mongo/util/net/ssl_manager_test.cpp38
20 files changed, 325 insertions, 46 deletions
diff --git a/buildscripts/resmokeconfig/suites/integration_tests_replset_ssl.yml b/buildscripts/resmokeconfig/suites/integration_tests_replset_ssl.yml
new file mode 100644
index 00000000000..fff837dee67
--- /dev/null
+++ b/buildscripts/resmokeconfig/suites/integration_tests_replset_ssl.yml
@@ -0,0 +1,35 @@
+# This suite is a clone of buildscripts/resmokeconfig/suites/integration_tests_replset.yml
+# with TLS options added. The inclusion and exclusion lists are expected to be similar.
+test_kind: cpp_integration_test
+
+selector:
+ root: build/integration_tests.txt
+ exclude_files:
+ - build/**/mongo/client/client_dbclient_connection_integration_test* # Needs connection to single host.
+ - build/install/bin/client_dbclient_connection_integration_test* # Needs connection to single host.
+
+executor:
+ archive:
+ hooks:
+ - CheckReplDBHash
+ - CheckReplOplogs
+ - ValidateCollections
+ config: {}
+ hooks:
+ # The CheckReplDBHash hook waits until all operations have replicated to and have been applied
+ # on the secondaries, so we run the ValidateCollections hook after it to ensure we're
+ # validating the entire contents of the collection.
+ - class: CheckReplOplogs
+ - class: CheckReplDBHash
+ - class: ValidateCollections
+ fixture:
+ class: ReplicaSetFixture
+ mongod_options:
+ set_parameters:
+ logComponentVerbosity:
+ command: 2
+ enableTestCommands: 1
+ tlsMode: preferTLS
+ tlsCAFile: jstests/libs/ca.pem
+ tlsCertificateKeyFile: jstests/libs/server.pem
+ num_nodes: 2
diff --git a/src/mongo/executor/connection_pool.cpp b/src/mongo/executor/connection_pool.cpp
index 36275566ce0..63f30325638 100644
--- a/src/mongo/executor/connection_pool.cpp
+++ b/src/mongo/executor/connection_pool.cpp
@@ -450,15 +450,12 @@ auto ConnectionPool::SpecificPool::make(std::shared_ptr<ConnectionPool> parent,
const Status ConnectionPool::kConnectionStateUnknown =
Status(ErrorCodes::InternalError, "Connection is in an unknown state");
-ConnectionPool::ConnectionPool(
- std::shared_ptr<DependentTypeFactoryInterface> impl,
- std::string name,
- Options options,
- std::shared_ptr<const transport::SSLConnectionContext> transientSSLContext)
+ConnectionPool::ConnectionPool(std::shared_ptr<DependentTypeFactoryInterface> impl,
+ std::string name,
+ Options options)
: _name(std::move(name)),
_factory(std::move(impl)),
_options(std::move(options)),
- _transientSSLContext(std::move(transientSSLContext)),
_controller(_options.controllerFactory()),
_manager(options.egressTagCloserManager) {
if (_manager) {
@@ -1037,6 +1034,7 @@ void ConnectionPool::SpecificPool::spawnConnections() {
"Spawning connections",
"connAllowance"_attr = allowance,
"hostAndPort"_attr = _hostAndPort);
+
for (decltype(allowance) i = 0; i < allowance; ++i) {
OwnedConnection handle;
try {
diff --git a/src/mongo/executor/connection_pool.h b/src/mongo/executor/connection_pool.h
index 64ee4c22cbb..9391dcbba12 100644
--- a/src/mongo/executor/connection_pool.h
+++ b/src/mongo/executor/connection_pool.h
@@ -236,11 +236,9 @@ public:
bool canShutdown = false;
};
- explicit ConnectionPool(
- std::shared_ptr<DependentTypeFactoryInterface> impl,
- std::string name,
- Options options = Options{},
- std::shared_ptr<const transport::SSLConnectionContext> transientSSLContext = {});
+ explicit ConnectionPool(std::shared_ptr<DependentTypeFactoryInterface> impl,
+ std::string name,
+ Options options = Options{});
~ConnectionPool();
@@ -271,9 +269,6 @@ private:
const std::shared_ptr<DependentTypeFactoryInterface> _factory;
const Options _options;
- // SSL context for the connections that require non-default SSL paramaeters.
- std::shared_ptr<const transport::SSLConnectionContext> _transientSSLContext;
-
std::shared_ptr<ControllerInterface> _controller;
// The global mutex for specific pool access and the generation counter
diff --git a/src/mongo/executor/connection_pool_tl.cpp b/src/mongo/executor/connection_pool_tl.cpp
index 4ae4faf570a..dd04a67368b 100644
--- a/src/mongo/executor/connection_pool_tl.cpp
+++ b/src/mongo/executor/connection_pool_tl.cpp
@@ -400,7 +400,8 @@ std::shared_ptr<ConnectionPool::ConnectionInterface> TLTypeFactory::makeConnecti
sslMode,
generation,
_onConnectHook.get(),
- _connPoolOptions.skipAuthentication);
+ _connPoolOptions.skipAuthentication,
+ _transientSSLContext);
fasten(conn.get());
return conn;
}
diff --git a/src/mongo/executor/connection_pool_tl.h b/src/mongo/executor/connection_pool_tl.h
index a147071f54d..5cdb3036fd7 100644
--- a/src/mongo/executor/connection_pool_tl.h
+++ b/src/mongo/executor/connection_pool_tl.h
@@ -51,16 +51,19 @@ public:
TLTypeFactory(transport::ReactorHandle reactor,
transport::TransportLayer* tl,
std::unique_ptr<NetworkConnectionHook> onConnectHook,
- const ConnectionPool::Options& connPoolOptions)
+ const ConnectionPool::Options& connPoolOptions,
+ std::shared_ptr<const transport::SSLConnectionContext> transientSSLContext)
: _executor(std::move(reactor)),
_tl(tl),
_onConnectHook(std::move(onConnectHook)),
- _connPoolOptions(connPoolOptions) {}
+ _connPoolOptions(connPoolOptions),
+ _transientSSLContext(transientSSLContext) {}
std::shared_ptr<ConnectionPool::ConnectionInterface> makeConnection(
const HostAndPort& hostAndPort,
transport::ConnectSSLMode sslMode,
size_t generation) override;
+
std::shared_ptr<ConnectionPool::TimerInterface> makeTimer() override;
const std::shared_ptr<OutOfLineExecutor>& getExecutor() override {
return _executor;
@@ -79,7 +82,9 @@ private:
std::shared_ptr<OutOfLineExecutor> _executor; // This is always a transport::Reactor
transport::TransportLayer* _tl;
std::unique_ptr<NetworkConnectionHook> _onConnectHook;
+ // Options originated from instance of NetworkInterfaceTL.
const ConnectionPool::Options _connPoolOptions;
+ std::shared_ptr<const transport::SSLConnectionContext> _transientSSLContext;
mutable Mutex _mutex =
MONGO_MAKE_LATCH(HierarchicalAcquisitionLevel(0), "TLTypeFactory::_mutex");
@@ -154,6 +159,7 @@ public:
_sslMode(sslMode),
_onConnectHook(onConnectHook),
_transientSSLContext(transientSSLContext) {}
+
~TLConnection() {
// Release must be the first expression of this dtor
release();
@@ -192,7 +198,7 @@ private:
transport::ConnectSSLMode _sslMode;
NetworkConnectionHook* const _onConnectHook;
// SSL context to use intead of the default one for this pool.
- std::shared_ptr<const transport::SSLConnectionContext> _transientSSLContext;
+ const std::shared_ptr<const transport::SSLConnectionContext> _transientSSLContext;
AsyncDBClient::Handle _client;
};
diff --git a/src/mongo/executor/network_interface_tl.cpp b/src/mongo/executor/network_interface_tl.cpp
index f50ae202bc5..28ef98de1e1 100644
--- a/src/mongo/executor/network_interface_tl.cpp
+++ b/src/mongo/executor/network_interface_tl.cpp
@@ -45,6 +45,7 @@
#include "mongo/util/net/socket_utils.h"
#include "mongo/util/testing_proctor.h"
+
namespace mongo {
namespace executor {
@@ -126,25 +127,20 @@ NetworkInterfaceTL::NetworkInterfaceTL(std::string instanceName,
}
std::shared_ptr<const transport::SSLConnectionContext> transientSSLContext;
-
#ifdef MONGO_CONFIG_SSL
if (_connPoolOpts.transientSSLParams) {
- // TODO: uncomment when changes for SERVER-51599 are submitted.
- // auto statusOrContext = _tl->createTransientSSLContext(
- // _connPoolOpts.transientSSLParams.get(), nullptr, true /* asyncOCSPStaple */);
- // uassertStatusOK(statusOrContext.getStatus());
- // transientSSLContext = std::make_shared<const transport::SSLConnectionContext>(
- // std::move(statusOrContext.getValue()));
+ auto statusOrContext =
+ _tl->createTransientSSLContext(_connPoolOpts.transientSSLParams.get(), nullptr);
+ uassertStatusOK(statusOrContext.getStatus());
+ transientSSLContext = std::move(statusOrContext.getValue());
}
#endif
_reactor = _tl->getReactor(transport::TransportLayer::kNewReactor);
auto typeFactory = std::make_unique<connection_pool_tl::TLTypeFactory>(
- _reactor, _tl, std::move(_onConnectHook), _connPoolOpts);
- _pool = std::make_shared<ConnectionPool>(std::move(typeFactory),
- std::string("NetworkInterfaceTL-") + _instanceName,
- _connPoolOpts,
- transientSSLContext);
+ _reactor, _tl, std::move(_onConnectHook), _connPoolOpts, transientSSLContext);
+ _pool = std::make_shared<ConnectionPool>(
+ std::move(typeFactory), std::string("NetworkInterfaceTL-") + _instanceName, _connPoolOpts);
if (TestingProctor::instance().isEnabled()) {
_counters = std::make_unique<SynchronizedCounters>();
diff --git a/src/mongo/executor/network_interface_tl.h b/src/mongo/executor/network_interface_tl.h
index 4dde6c8fdfd..646ebfbb11f 100644
--- a/src/mongo/executor/network_interface_tl.h
+++ b/src/mongo/executor/network_interface_tl.h
@@ -45,6 +45,7 @@
#include "mongo/util/hierarchical_acquisition.h"
#include "mongo/util/strong_weak_finish_line.h"
+
namespace mongo {
namespace executor {
diff --git a/src/mongo/transport/session_asio.h b/src/mongo/transport/session_asio.h
index a6864b37189..df83ab40d2a 100644
--- a/src/mongo/transport/session_asio.h
+++ b/src/mongo/transport/session_asio.h
@@ -114,6 +114,16 @@ public:
_remote = HostAndPort(_remoteAddr.toString(true));
#ifdef MONGO_CONFIG_SSL
_sslContext = transientSSLContext ? transientSSLContext : *tl->_sslContext;
+ if (transientSSLContext) {
+ logv2::DynamicAttributes attrs;
+ if (transientSSLContext->targetClusterURI) {
+ attrs.add("targetClusterURI", *transientSSLContext->targetClusterURI);
+ }
+ attrs.add("isIngress", isIngressSession);
+ attrs.add("connectionId", id());
+ attrs.add("remote", remote());
+ LOGV2(5271001, "Initializing the ASIOSession with transient SSL context", attrs);
+ }
#endif
} catch (const DBException&) {
throw;
diff --git a/src/mongo/transport/ssl_connection_context.h b/src/mongo/transport/ssl_connection_context.h
index 2de1f98c647..0ab7c23091d 100644
--- a/src/mongo/transport/ssl_connection_context.h
+++ b/src/mongo/transport/ssl_connection_context.h
@@ -53,6 +53,11 @@ struct SSLConnectionContext {
std::unique_ptr<asio::ssl::context> ingress;
std::unique_ptr<asio::ssl::context> egress;
std::shared_ptr<SSLManagerInterface> manager;
+ // If this Context was created from transient SSL params this contains the URI of the target
+ // cluster. It can also be used to determine if the context is indeed transient.
+ std::optional<std::string> targetClusterURI;
+
+ ~SSLConnectionContext();
};
#endif
diff --git a/src/mongo/transport/transport_layer.h b/src/mongo/transport/transport_layer.h
index 126b6ec7898..10745f16198 100644
--- a/src/mongo/transport/transport_layer.h
+++ b/src/mongo/transport/transport_layer.h
@@ -42,6 +42,7 @@
#include "mongo/util/future.h"
#include "mongo/util/out_of_line_executor.h"
#include "mongo/util/time_support.h"
+
#ifdef MONGO_CONFIG_SSL
#include "mongo/util/net/ssl_manager.h"
#endif
@@ -133,6 +134,16 @@ public:
/** Rotate the in-use certificates for new connections. */
virtual Status rotateCertificates(std::shared_ptr<SSLManagerInterface> manager,
bool asyncOCSPStaple) = 0;
+
+ /**
+ * Creates a transient SSL context using targeted (non default) SSL params.
+ * @param transientSSLParams overrides any value in stored SSLConnectionContext.
+ * @param optionalManager provides an optional SSL manager, otherwise the default one will be
+ * used.
+ */
+ virtual StatusWith<std::shared_ptr<const transport::SSLConnectionContext>>
+ createTransientSSLContext(const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) = 0;
#endif
private:
diff --git a/src/mongo/transport/transport_layer_asio.cpp b/src/mongo/transport/transport_layer_asio.cpp
index 4fd4df156bc..670ea496bc9 100644
--- a/src/mongo/transport/transport_layer_asio.cpp
+++ b/src/mongo/transport/transport_layer_asio.cpp
@@ -99,6 +99,9 @@ boost::optional<Status> maybeTcpFastOpenStatus;
MONGO_FAIL_POINT_DEFINE(transportLayerASIOasyncConnectTimesOut);
+
+SSLConnectionContext::~SSLConnectionContext() = default;
+
class ASIOReactorTimer final : public ReactorTimer {
public:
explicit ASIOReactorTimer(asio::io_context& ctx)
@@ -1189,17 +1192,33 @@ SSLParams::SSLModes TransportLayerASIO::_sslMode() const {
Status TransportLayerASIO::rotateCertificates(std::shared_ptr<SSLManagerInterface> manager,
bool asyncOCSPStaple) {
- auto newSSLContext = std::make_shared<SSLConnectionContext>();
+
+ auto contextOrStatus =
+ _createSSLContext(manager, _sslMode(), TransientSSLParams(), asyncOCSPStaple);
+ if (!contextOrStatus.isOK()) {
+ return contextOrStatus.getStatus();
+ }
+ _sslContext = std::move(contextOrStatus.getValue());
+ return Status::OK();
+}
+
+StatusWith<std::shared_ptr<const transport::SSLConnectionContext>>
+TransportLayerASIO::_createSSLContext(std::shared_ptr<SSLManagerInterface>& manager,
+ SSLParams::SSLModes sslMode,
+ TransientSSLParams transientEgressSSLParams,
+ bool asyncOCSPStaple) const {
+
+ std::shared_ptr<SSLConnectionContext> newSSLContext = std::make_shared<SSLConnectionContext>();
newSSLContext->manager = manager;
const auto& sslParams = getSSLGlobalParams();
- if (_sslMode() != SSLParams::SSLMode_disabled && _listenerOptions.isIngress()) {
+ if (sslMode != SSLParams::SSLMode_disabled && _listenerOptions.isIngress()) {
newSSLContext->ingress = std::make_unique<asio::ssl::context>(asio::ssl::context::sslv23);
Status status = newSSLContext->manager->initSSLContext(
newSSLContext->ingress->native_handle(),
sslParams,
- TransientSSLParams(),
+ TransientSSLParams(), // Ingress is not using transient params, they are egress.
SSLManagerInterface::ConnectionDirection::kIncoming);
if (!status.isOK()) {
return status;
@@ -1220,15 +1239,33 @@ Status TransportLayerASIO::rotateCertificates(std::shared_ptr<SSLManagerInterfac
Status status = newSSLContext->manager->initSSLContext(
newSSLContext->egress->native_handle(),
sslParams,
- TransientSSLParams(),
+ transientEgressSSLParams,
SSLManagerInterface::ConnectionDirection::kOutgoing);
if (!status.isOK()) {
return status;
}
+ if (!transientEgressSSLParams.sslClusterPEMPayload.empty()) {
+ if (transientEgressSSLParams.targetedClusterConnectionString) {
+ newSSLContext->targetClusterURI =
+ transientEgressSSLParams.targetedClusterConnectionString.toString();
+ }
+ }
}
- _sslContext = std::move(newSSLContext);
- return Status::OK();
+ return newSSLContext;
+}
+
+StatusWith<std::shared_ptr<const transport::SSLConnectionContext>>
+TransportLayerASIO::createTransientSSLContext(const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) {
+
+ auto manager = getSSLManager();
+ if (!manager) {
+ return Status(ErrorCodes::InvalidSSLConfiguration, "TransportLayerASIO has no SSL manager");
+ }
+
+ return _createSSLContext(manager, _sslMode(), transientSSLParams, true /* asyncOCSPStaple */);
}
+
#endif
#ifdef __linux__
diff --git a/src/mongo/transport/transport_layer_asio.h b/src/mongo/transport/transport_layer_asio.h
index d710ec1c89e..6eac75fae2f 100644
--- a/src/mongo/transport/transport_layer_asio.h
+++ b/src/mongo/transport/transport_layer_asio.h
@@ -152,8 +152,22 @@ public:
bool asyncOCSPStaple) override;
std::shared_ptr<SSLManagerInterface> getSSLManager() {
- return _sslContext.get()->manager;
+ auto sslContext = _sslContext.get();
+ if (!sslContext) {
+ return std::shared_ptr<SSLManagerInterface>{};
+ }
+ return sslContext->manager;
}
+
+ /**
+ * Creates a transient SSL context using targeted (non default) SSL params.
+ * @param transientSSLParams overrides any value in stored SSLConnectionContext.
+ * @param optionalManager provides an optional SSL manager, otherwise the default one will be
+ * used.
+ */
+ StatusWith<std::shared_ptr<const transport::SSLConnectionContext>> createTransientSSLContext(
+ const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) override;
#endif
private:
@@ -172,6 +186,12 @@ private:
const HostAndPort& peer,
const Milliseconds& timeout);
+ StatusWith<std::shared_ptr<const transport::SSLConnectionContext>> _createSSLContext(
+ std::shared_ptr<SSLManagerInterface>& manager,
+ SSLParams::SSLModes sslMode,
+ TransientSSLParams transientEgressSSLParams,
+ bool asyncOCSPStaple) const;
+
void _runListener() noexcept;
#ifdef MONGO_CONFIG_SSL
diff --git a/src/mongo/transport/transport_layer_manager.cpp b/src/mongo/transport/transport_layer_manager.cpp
index 272a9ac391d..fd386560a44 100644
--- a/src/mongo/transport/transport_layer_manager.cpp
+++ b/src/mongo/transport/transport_layer_manager.cpp
@@ -45,6 +45,7 @@
#include "mongo/transport/service_executor_synchronous.h"
#include "mongo/transport/session.h"
#include "mongo/transport/transport_layer_asio.h"
+#include "mongo/util/net/ssl/context.hpp"
#include "mongo/util/net/ssl_types.h"
#include "mongo/util/time_support.h"
@@ -154,6 +155,23 @@ Status TransportLayerManager::rotateCertificates(std::shared_ptr<SSLManagerInter
}
return Status::OK();
}
+
+StatusWith<std::shared_ptr<const transport::SSLConnectionContext>>
+TransportLayerManager::createTransientSSLContext(const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) {
+
+ Status firstError(ErrorCodes::InvalidSSLConfiguration,
+ "Failure creating transient SSL context");
+ for (auto&& tl : _tls) {
+ auto statusOrContext = tl->createTransientSSLContext(transientSSLParams, optionalManager);
+ if (statusOrContext.isOK()) {
+ return std::move(statusOrContext.getValue());
+ }
+ firstError = statusOrContext.getStatus();
+ }
+ return firstError;
+}
+
#endif
} // namespace transport
diff --git a/src/mongo/transport/transport_layer_manager.h b/src/mongo/transport/transport_layer_manager.h
index a4fd33cd863..b561a67f591 100644
--- a/src/mongo/transport/transport_layer_manager.h
+++ b/src/mongo/transport/transport_layer_manager.h
@@ -56,8 +56,8 @@ class TransportLayerManager final : public TransportLayer {
TransportLayerManager& operator=(const TransportLayerManager&) = delete;
public:
- TransportLayerManager(std::vector<std::unique_ptr<TransportLayer>> tls,
- const WireSpec& wireSpec = WireSpec::instance())
+ explicit TransportLayerManager(std::vector<std::unique_ptr<TransportLayer>> tls,
+ const WireSpec& wireSpec = WireSpec::instance())
: TransportLayer(wireSpec), _tls(std::move(tls)) {}
explicit TransportLayerManager(const WireSpec& wireSpec = WireSpec::instance())
@@ -107,6 +107,10 @@ public:
#ifdef MONGO_CONFIG_SSL
Status rotateCertificates(std::shared_ptr<SSLManagerInterface> manager,
bool asyncOCSPStaple) override;
+
+ StatusWith<std::shared_ptr<const transport::SSLConnectionContext>> createTransientSSLContext(
+ const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) override;
#endif
private:
template <typename Callable>
diff --git a/src/mongo/transport/transport_layer_mock.cpp b/src/mongo/transport/transport_layer_mock.cpp
index 6fca645649d..dc11e6f06e9 100644
--- a/src/mongo/transport/transport_layer_mock.cpp
+++ b/src/mongo/transport/transport_layer_mock.cpp
@@ -102,5 +102,11 @@ TransportLayerMock::~TransportLayerMock() {
shutdown();
}
+StatusWith<std::shared_ptr<const transport::SSLConnectionContext>>
+TransportLayerMock::createTransientSSLContext(const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) {
+ return Status(ErrorCodes::InvalidSSLConfiguration, "Failure creating transient SSL context");
+}
+
} // namespace transport
} // namespace mongo
diff --git a/src/mongo/transport/transport_layer_mock.h b/src/mongo/transport/transport_layer_mock.h
index b1e778e1e8c..a376f66fc95 100644
--- a/src/mongo/transport/transport_layer_mock.h
+++ b/src/mongo/transport/transport_layer_mock.h
@@ -83,6 +83,10 @@ public:
bool asyncOCSPStaple) override {
return Status::OK();
}
+
+ StatusWith<std::shared_ptr<const transport::SSLConnectionContext>> createTransientSSLContext(
+ const TransientSSLParams& transientSSLParams,
+ const SSLManagerInterface* optionalManager) override;
#endif
private:
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index adf8b0ec033..71c46e22df6 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -230,6 +230,7 @@ if get_option('ssl') == 'on':
'sock_test.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/client/connection_string',
'$BUILD_DIR/mongo/db/server_options_servers',
'$BUILD_DIR/mongo/transport/transport_layer',
'$BUILD_DIR/mongo/util/cmdline_utils/cmdline_utils',
@@ -239,3 +240,23 @@ if get_option('ssl') == 'on':
'ssl_options_server',
],
)
+
+if get_option('ssl') == 'on':
+ env.CppIntegrationTest(
+ target='network_interface_ssl_test',
+ source=[
+ 'network_interface_ssl_test.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/client/connection_string',
+ '$BUILD_DIR/mongo/executor/network_interface',
+ '$BUILD_DIR/mongo/executor/network_interface_factory',
+ '$BUILD_DIR/mongo/executor/network_interface_fixture',
+ '$BUILD_DIR/mongo/executor/network_interface_thread_pool',
+ '$BUILD_DIR/mongo/executor/thread_pool_task_executor',
+ '$BUILD_DIR/mongo/transport/transport_layer_egress_init',
+ '$BUILD_DIR/mongo/util/concurrency/thread_pool',
+ '$BUILD_DIR/mongo/util/version_impl',
+ ],
+)
+
diff --git a/src/mongo/util/net/network_interface_ssl_test.cpp b/src/mongo/util/net/network_interface_ssl_test.cpp
new file mode 100644
index 00000000000..8e3b446bdfe
--- /dev/null
+++ b/src/mongo/util/net/network_interface_ssl_test.cpp
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2018-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
+
+#include <fstream>
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/executor/network_interface_integration_fixture.h"
+#include "mongo/logv2/log.h"
+#include "mongo/unittest/integration_test.h"
+#include "mongo/unittest/unittest.h"
+#include "mongo/util/assert_util.h"
+
+namespace mongo {
+namespace executor {
+namespace {
+
+std::string LoadFile(const std::string& name) {
+ std::ifstream input(name);
+ std::string str((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
+ return str;
+}
+
+class NetworkInterfaceSSLFixture : public NetworkInterfaceIntegrationFixture {
+public:
+ void setUp() final {
+ ConnectionPool::Options options;
+ options.transientSSLParams.emplace([] {
+ TransientSSLParams params;
+ params.sslClusterPEMPayload = LoadFile("jstests/libs/client.pem");
+ params.targetedClusterConnectionString = ConnectionString::forLocal();
+ return params;
+ }());
+ LOGV2(5181101, "Initializing the test connection with transient SSL params");
+ createNet(nullptr, std::move(options));
+ net().startup();
+ }
+};
+
+TEST_F(NetworkInterfaceSSLFixture, Ping) {
+ assertCommandOK("admin", BSON("ping" << 1));
+}
+
+
+} // namespace
+} // namespace executor
+} // namespace mongo
diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp
index d42474657a3..cbd75b964f2 100644
--- a/src/mongo/util/net/ssl_manager_openssl.cpp
+++ b/src/mongo/util/net/ssl_manager_openssl.cpp
@@ -1331,7 +1331,7 @@ private:
StatusWith<boost::optional<std::vector<DERInteger>>> _parseTLSFeature(X509* peerCert) const;
/** @return true if was successful, otherwise false */
- bool _setupPEM(SSL_CTX* context, const std::string& keyFile, PasswordFetcher* password);
+ bool _setupPEM(SSL_CTX* context, const std::string& keyFile, PasswordFetcher* password) const;
/**
* @param payload in-memory payload of a PEM file
@@ -1340,7 +1340,7 @@ private:
bool _setupPEMFromMemoryPayload(SSL_CTX* context,
const std::string& payload,
PasswordFetcher* password,
- StringData targetClusterURI);
+ StringData targetClusterURI) const;
/**
* Setup PEM from BIO, which could be file or memory input abstraction.
@@ -1356,7 +1356,7 @@ private:
UniqueBIO inBio,
PasswordFetcher* password,
std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI);
+ std::optional<StringData> targetClusterURI) const;
/**
* Loads a certificate chain from memory into context.
@@ -2437,7 +2437,7 @@ bool SSLManagerOpenSSL::_readCertificateChainFromMemory(
bool SSLManagerOpenSSL::_setupPEM(SSL_CTX* context,
const std::string& keyFile,
- PasswordFetcher* password) {
+ PasswordFetcher* password) const {
logv2::DynamicAttributes errorAttrs;
errorAttrs.add("keyFile", keyFile);
@@ -2466,7 +2466,7 @@ bool SSLManagerOpenSSL::_setupPEM(SSL_CTX* context,
bool SSLManagerOpenSSL::_setupPEMFromMemoryPayload(SSL_CTX* context,
const std::string& payload,
PasswordFetcher* password,
- StringData targetClusterURI) {
+ StringData targetClusterURI) const {
logv2::DynamicAttributes errorAttrs;
errorAttrs.add("targetClusterURI", targetClusterURI);
@@ -2492,7 +2492,7 @@ bool SSLManagerOpenSSL::_setupPEMFromBIO(SSL_CTX* context,
UniqueBIO inBio,
PasswordFetcher* password,
std::optional<StringData> keyFile,
- std::optional<StringData> targetClusterURI) {
+ std::optional<StringData> targetClusterURI) const {
logv2::DynamicAttributes errorAttrs;
if (keyFile) {
errorAttrs.add("keyFile", *keyFile);
diff --git a/src/mongo/util/net/ssl_manager_test.cpp b/src/mongo/util/net/ssl_manager_test.cpp
index af325854a87..1fbd42bde40 100644
--- a/src/mongo/util/net/ssl_manager_test.cpp
+++ b/src/mongo/util/net/ssl_manager_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/transport/service_entry_point.h"
#include "mongo/transport/transport_layer_asio.h"
+#include "mongo/transport/transport_layer_manager.h"
#include "mongo/util/net/ssl/context_base.hpp"
#include "mongo/util/net/ssl_manager.h"
#include "mongo/util/net/ssl_options.h"
@@ -52,7 +53,6 @@
namespace mongo {
namespace {
-
// Test implementation needed by ASIO transport.
class ServiceEntryPointUtil : public ServiceEntryPoint {
public:
@@ -602,6 +602,42 @@ TEST(SSLManager, InitServerSideContextFromMemory) {
SSLManagerInterface::ConnectionDirection::kOutgoing));
}
+TEST(SSLManager, TransientSSLParams) {
+ SSLParams params;
+ params.sslMode.store(::mongo::sslGlobalParams.SSLMode_requireSSL);
+ params.sslCAFile = "jstests/libs/ca.pem";
+ params.sslClusterFile = "jstests/libs/client.pem";
+
+ std::shared_ptr<SSLManagerInterface> manager =
+ SSLManagerInterface::create(params, false /* isSSLServer */);
+
+ ServiceEntryPointUtil sepu;
+
+ auto options = [] {
+ ServerGlobalParams params;
+ params.noUnixSocket = true;
+ transport::TransportLayerASIO::Options opts(&params);
+ return opts;
+ }();
+ transport::TransportLayerASIO tla(options, &sepu);
+
+ TransientSSLParams transientSSLParams;
+ transientSSLParams.sslClusterPEMPayload = LoadFile("jstests/libs/client.pem");
+ transientSSLParams.targetedClusterConnectionString = ConnectionString::forLocal();
+
+ auto result = tla.createTransientSSLContext(transientSSLParams, manager.get());
+
+ // This will fail because we need to rotate certificates first to
+ // initialize the default SSL context inside TransportLayerASIO.
+ ASSERT_NOT_OK(result.getStatus());
+
+ // Init the transport properly.
+ uassertStatusOK(tla.rotateCertificates(manager, false /* asyncOCSPStaple */));
+
+ result = tla.createTransientSSLContext(transientSSLParams, manager.get());
+ uassertStatusOK(result.getStatus());
+}
+
#endif
} // namespace