diff options
Diffstat (limited to 'src/mongo/executor')
-rw-r--r-- | src/mongo/executor/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/executor/connection_pool_tl.cpp | 89 | ||||
-rw-r--r-- | src/mongo/executor/network_connection_hook.h | 9 |
3 files changed, 81 insertions, 18 deletions
diff --git a/src/mongo/executor/SConscript b/src/mongo/executor/SConscript index af9be6312b1..aab6a91626f 100644 --- a/src/mongo/executor/SConscript +++ b/src/mongo/executor/SConscript @@ -138,7 +138,6 @@ env.Library( '$BUILD_DIR/mongo/transport/transport_layer', ], LIBDEPS_PRIVATE=[ - '$BUILD_DIR/mongo/db/auth/internal_user_auth', '$BUILD_DIR/mongo/db/commands/test_commands_enabled', '$BUILD_DIR/mongo/transport/transport_layer_manager', 'connection_pool_executor', diff --git a/src/mongo/executor/connection_pool_tl.cpp b/src/mongo/executor/connection_pool_tl.cpp index 7dd943649c1..624e3fe3e6b 100644 --- a/src/mongo/executor/connection_pool_tl.cpp +++ b/src/mongo/executor/connection_pool_tl.cpp @@ -34,7 +34,8 @@ #include "mongo/executor/connection_pool_tl.h" -#include "mongo/db/auth/internal_user_auth.h" +#include "mongo/client/authenticate.h" +#include "mongo/db/auth/authorization_manager.h" #include "mongo/util/log.h" namespace mongo { @@ -157,6 +158,67 @@ void TLConnection::cancelTimeout() { _timer->cancelTimeout(); } +class TLConnectionSetupHook : public executor::NetworkConnectionHook { +public: + explicit TLConnectionSetupHook(executor::NetworkConnectionHook* hookToWrap) + : _wrappedHook(hookToWrap) {} + + BSONObj augmentIsMasterRequest(BSONObj cmdObj) override { + BSONObjBuilder bob(std::move(cmdObj)); + bob.append("hangUpOnStepDown", false); + if (internalSecurity.user) { + bob.append("saslSupportedMechs", internalSecurity.user->getName().getUnambiguousName()); + } + + return bob.obj(); + } + + Status validateHost(const HostAndPort& remoteHost, + const BSONObj& isMasterRequest, + const RemoteCommandResponse& isMasterReply) override try { + const auto saslMechsElem = isMasterReply.data.getField("saslSupportedMechs"); + if (saslMechsElem.type() == Array) { + auto array = saslMechsElem.Array(); + for (const auto& elem : array) { + _saslMechsForInternalAuth.push_back(elem.checkAndGetStringData().toString()); + } + } + + if (!_wrappedHook) { + return Status::OK(); + } else { + return _wrappedHook->validateHost(remoteHost, isMasterRequest, isMasterReply); + } + } catch (const DBException& e) { + return e.toStatus(); + } + + StatusWith<boost::optional<RemoteCommandRequest>> makeRequest( + const HostAndPort& remoteHost) final { + if (_wrappedHook) { + return _wrappedHook->makeRequest(remoteHost); + } else { + return boost::none; + } + } + + Status handleReply(const HostAndPort& remoteHost, RemoteCommandResponse&& response) final { + if (_wrappedHook) { + return _wrappedHook->handleReply(remoteHost, std::move(response)); + } else { + return Status::OK(); + } + } + + const std::vector<std::string>& saslMechsForInternalAuth() const { + return _saslMechsForInternalAuth; + } + +private: + std::vector<std::string> _saslMechsForInternalAuth; + executor::NetworkConnectionHook* const _wrappedHook = nullptr; +}; + void TLConnection::setup(Milliseconds timeout, SetupCallback cb) { auto anchor = shared_from_this(); @@ -180,28 +242,21 @@ void TLConnection::setup(Milliseconds timeout, SetupCallback cb) { } }); + auto isMasterHook = std::make_shared<TLConnectionSetupHook>(_onConnectHook); + AsyncDBClient::connect(_peer, transport::kGlobalSSLMode, _serviceContext, _reactor, timeout) .onError([](StatusWith<AsyncDBClient::Handle> swc) -> StatusWith<AsyncDBClient::Handle> { return Status(ErrorCodes::HostUnreachable, swc.getStatus().reason()); }) - .then([this](AsyncDBClient::Handle client) { + .then([this, isMasterHook](AsyncDBClient::Handle client) { _client = std::move(client); - return _client->initWireVersion("NetworkInterfaceTL", _onConnectHook); + return _client->initWireVersion("NetworkInterfaceTL", isMasterHook.get()); }) - .then([this] { - // Try to authenticate with the default system credentials - return _client->authenticate(getInternalUserAuthParams()) - .onError([this](Status status) -> Future<void> { - // If we're in the middle of a keyfile rollover, there may be alternate - // credentials to try. - const auto altParams = getInternalUserAuthParams(1); - if (!altParams.isEmpty() && status == ErrorCodes::AuthenticationFailed) { - return _client->authenticate(altParams); - } else { - // If there weren't alternate credentials, the original error stands. - return status; - } - }); + .then([this, isMasterHook] { + boost::optional<std::string> mechanism; + if (!isMasterHook->saslMechsForInternalAuth().empty()) + mechanism = isMasterHook->saslMechsForInternalAuth().front(); + return _client->authenticateInternal(std::move(mechanism)); }) .then([this] { if (!_onConnectHook) { diff --git a/src/mongo/executor/network_connection_hook.h b/src/mongo/executor/network_connection_hook.h index 51d18fceb84..c84f4054cf2 100644 --- a/src/mongo/executor/network_connection_hook.h +++ b/src/mongo/executor/network_connection_hook.h @@ -55,6 +55,15 @@ public: virtual ~NetworkConnectionHook() = default; /** + * Optionally augments the isMaster request sent while initializing the wire protocol. + * + * By default this will just return the cmdObj passed in unaltered. + */ + virtual BSONObj augmentIsMasterRequest(BSONObj cmdObj) { + return cmdObj; + } + + /** * Runs optional validation logic on an isMaster reply from a remote host. If a non-OK * Status is returned, it will be propagated up to the completion handler for the command * that initiated the request that caused this connection to be created. This will |