diff options
author | Shreyas Kalyan <shreyas.kalyan@10gen.com> | 2020-05-05 11:07:46 -0700 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-08 03:25:46 +0000 |
commit | c1e9eee0dd99c16dcaaaf77dad10d995992693e5 (patch) | |
tree | 985914405f3e7892483d39f9de9d0d6421913b4a /src/mongo | |
parent | a01e575c7f2811ee8c4d3b98ecb0230b1b991399 (diff) | |
download | mongo-c1e9eee0dd99c16dcaaaf77dad10d995992693e5.tar.gz |
SERVER-47934 Create a setParameter to control the OCSP HTTP client timeout
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/shell/shell_options.cpp | 1 | ||||
-rw-r--r-- | src/mongo/util/net/ocsp/ocsp_manager.cpp | 56 | ||||
-rw-r--r-- | src/mongo/util/net/ocsp/ocsp_manager.h | 11 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_openssl.cpp | 18 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_windows.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_parameters.idl | 21 |
6 files changed, 80 insertions, 29 deletions
diff --git a/src/mongo/shell/shell_options.cpp b/src/mongo/shell/shell_options.cpp index 4cd0fb791d9..2365462e317 100644 --- a/src/mongo/shell/shell_options.cpp +++ b/src/mongo/shell/shell_options.cpp @@ -65,6 +65,7 @@ const std::set<std::string> kSetShellParameterWhitelist = { "awsEC2InstanceMetadataUrl", "awsECSInstanceMetadataUrl", "ocspEnabled", + "ocspClientHttpTimeoutSecs", "disabledSecureAllocatorDomains", "newLineAfterPasswordPromptForTest", "skipShellCursorFinalize", diff --git a/src/mongo/util/net/ocsp/ocsp_manager.cpp b/src/mongo/util/net/ocsp/ocsp_manager.cpp index 11ebf085bde..9b0a2e517c7 100644 --- a/src/mongo/util/net/ocsp/ocsp_manager.cpp +++ b/src/mongo/util/net/ocsp/ocsp_manager.cpp @@ -32,6 +32,7 @@ #include "mongo/db/client.h" #include "mongo/executor/network_interface_factory.h" #include "mongo/util/net/ocsp/ocsp_manager.h" +#include "mongo/util/net/ssl_parameters_gen.h" namespace mongo { @@ -52,14 +53,24 @@ auto makeTaskExecutor() { OCSPManager::OCSPManager() { _pool = makeTaskExecutor(); - _client = HttpClient::create(); - if (!_client) { + this->_tlsServerHttp = HttpClient::create(); + this->_tlsClientHttp = HttpClient::create(); + + if (!this->_tlsServerHttp) { return; } - _client->allowInsecureHTTP(true); - _client->setTimeout(kOCSPRequestTimeoutSeconds); - _client->setHeaders({"Content-Type: application/ocsp-request"}); + this->_tlsClientHttp->allowInsecureHTTP(true); + this->_tlsClientHttp->setTimeout(Seconds(gTLSOCSPVerifyTimeoutSecs)); + this->_tlsClientHttp->setHeaders({"Content-Type: application/ocsp-request"}); + + this->_tlsServerHttp->allowInsecureHTTP(true); + if (gTLSOCSPStaplingTimeoutSecs < 0) { + this->_tlsServerHttp->setTimeout(Seconds(gTLSOCSPVerifyTimeoutSecs)); + } else { + this->_tlsServerHttp->setTimeout(Seconds(gTLSOCSPStaplingTimeoutSecs)); + } + this->_tlsServerHttp->setHeaders({"Content-Type: application/ocsp-request"}); } void OCSPManager::startThreadPool() { @@ -73,8 +84,9 @@ void OCSPManager::startThreadPool() { * Returns a vector of bytes to be constructed into a OCSP response. */ Future<std::vector<uint8_t>> OCSPManager::requestStatus(std::vector<uint8_t> data, - StringData responderURI) { - if (!this->_client) { + StringData responderURI, + OCSPPurpose purpose) { + if (!this->_tlsClientHttp || !this->_tlsServerHttp) { return Future<std::vector<uint8_t>>::makeReady( Status(ErrorCodes::InternalErrorNotSupported, "HTTP Client not supported")); } @@ -82,19 +94,23 @@ Future<std::vector<uint8_t>> OCSPManager::requestStatus(std::vector<uint8_t> dat auto pf = makePromiseFuture<DataBuilder>(); std::string uri("http://" + responderURI); - _pool->schedule( - [this, promise = std::move(pf.promise), uri = std::move(uri), data = std::move(data)]( - auto status) mutable { - if (!status.isOK()) { - return; - } - try { - auto result = this->_client->post(uri, data); - promise.emplaceValue(std::move(result)); - } catch (...) { - promise.setError(exceptionToStatus()); - } - }); + _pool->schedule([this, + purpose, + promise = std::move(pf.promise), + uri = std::move(uri), + data = std::move(data)](auto status) mutable { + if (!status.isOK()) { + return; + } + try { + const auto& client = + purpose == OCSPPurpose::kClientVerify ? this->_tlsClientHttp : this->_tlsServerHttp; + auto result = client->post(uri, data); + promise.emplaceValue(std::move(result)); + } catch (...) { + promise.setError(exceptionToStatus()); + } + }); return std::move(pf.future).then( [](DataBuilder dataBuilder) mutable -> Future<std::vector<uint8_t>> { diff --git a/src/mongo/util/net/ocsp/ocsp_manager.h b/src/mongo/util/net/ocsp/ocsp_manager.h index e392b5e0a12..674e3b5476b 100644 --- a/src/mongo/util/net/ocsp/ocsp_manager.h +++ b/src/mongo/util/net/ocsp/ocsp_manager.h @@ -38,7 +38,8 @@ namespace mongo { -constexpr Seconds kOCSPRequestTimeoutSeconds(5); +enum class OCSPPurpose { kClientVerify, kStaple }; + class OCSPManager { public: @@ -50,12 +51,16 @@ public: return &manager; }; - Future<std::vector<uint8_t>> requestStatus(std::vector<uint8_t> data, StringData responderURI); + Future<std::vector<uint8_t>> requestStatus(std::vector<uint8_t> data, + StringData responderURI, + OCSPPurpose direction); void startThreadPool(); private: - std::unique_ptr<HttpClient> _client; + std::unique_ptr<HttpClient> _tlsClientHttp; + std::unique_ptr<HttpClient> _tlsServerHttp; + std::unique_ptr<ThreadPool> _pool; }; diff --git a/src/mongo/util/net/ssl_manager_openssl.cpp b/src/mongo/util/net/ssl_manager_openssl.cpp index 67f29f435a9..7d678f0d1c5 100644 --- a/src/mongo/util/net/ssl_manager_openssl.cpp +++ b/src/mongo/util/net/ssl_manager_openssl.cpp @@ -693,7 +693,8 @@ StatusWith<std::vector<std::string>> addOCSPUrlToMap( } Future<UniqueOCSPResponse> retrieveOCSPResponse(const std::string& host, - OCSPRequestAndIDs& ocspRequestAndIDs) { + OCSPRequestAndIDs& ocspRequestAndIDs, + OCSPPurpose purpose) { auto& [ocspReq, certIDs] = ocspRequestAndIDs; // Decompose the OCSP request into a DER encoded OCSP request @@ -711,7 +712,7 @@ Future<UniqueOCSPResponse> retrieveOCSPResponse(const std::string& host, // Query the OCSP responder return OCSPManager::get() - ->requestStatus(buffer, host) + ->requestStatus(buffer, host, purpose) .then([](std::vector<uint8_t> responseData) mutable -> StatusWith<UniqueOCSPResponse> { const uint8_t* respDataPtr = responseData.data(); @@ -824,7 +825,8 @@ StatusWith<std::pair<OCSPCertIDSet, Date_t>> parseAndValidateOCSPResponse( Future<OCSPFetchResponse> dispatchRequests(SSL_CTX* context, std::shared_ptr<STACK_OF(X509)> intermediateCerts, - OCSPValidationContext& ocspContext) { + OCSPValidationContext& ocspContext, + OCSPPurpose purpose) { auto& [ocspRequestMap, _, leafResponders] = ocspContext; struct OCSPCompletionState { @@ -844,7 +846,8 @@ Future<OCSPFetchResponse> dispatchRequests(SSL_CTX* context, for (auto host : leafResponders) { auto& ocspRequestAndIDs = ocspRequestMap[host]; - Future<UniqueOCSPResponse> futureResponse = retrieveOCSPResponse(host, ocspRequestAndIDs); + Future<UniqueOCSPResponse> futureResponse = + retrieveOCSPResponse(host, ocspRequestAndIDs, purpose); futureResponses.push_back(std::move(futureResponse)); }; @@ -965,7 +968,9 @@ private: auto ocspContext = std::move(swOCSPContext.getValue()); auto swResponse = - dispatchRequests(key.context, key.intermediateCerts, ocspContext).getNoThrow(); + dispatchRequests( + key.context, key.intermediateCerts, ocspContext, OCSPPurpose::kClientVerify) + .getNoThrow(); if (!swResponse.isOK()) { return boost::none; } @@ -1753,7 +1758,8 @@ Status SSLManagerOpenSSL::stapleOCSPResponse(SSL_CTX* context) { auto ocspContext = std::move(swOCSPContext.getValue()); - return dispatchRequests(context, std::move(intermediateCerts), ocspContext) + return dispatchRequests( + context, std::move(intermediateCerts), ocspContext, OCSPPurpose::kStaple) .onCompletion([](StatusWith<OCSPFetchResponse> swResponse) -> Milliseconds { if (!swResponse.isOK()) { LOGV2_WARNING(23233, "Could not staple OCSP response to outgoing certificate."); diff --git a/src/mongo/util/net/ssl_manager_windows.cpp b/src/mongo/util/net/ssl_manager_windows.cpp index cab3f2780ae..45b7267e48e 100644 --- a/src/mongo/util/net/ssl_manager_windows.cpp +++ b/src/mongo/util/net/ssl_manager_windows.cpp @@ -1708,6 +1708,8 @@ Status validatePeerCertificate(const std::string& remoteHost, certChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = usage; } + certChainPara.dwUrlRetrievalTimeout = kTLSClientOCSPTimeoutSecs * 1000; + PCCERT_CHAIN_CONTEXT chainContext; BOOL ret = CertGetCertificateChain(certChainEngine, cert, diff --git a/src/mongo/util/net/ssl_parameters.idl b/src/mongo/util/net/ssl_parameters.idl index 3a106ec54a8..76929f4c31b 100644 --- a/src/mongo/util/net/ssl_parameters.idl +++ b/src/mongo/util/net/ssl_parameters.idl @@ -80,6 +80,27 @@ server_parameters: cpp_varname: "kOCSPValidationRefreshPeriodSecs" validator: gte: 1 + tlsOCSPVerifyTimeoutSecs: + description: >- + How long the http client should wait before timing out + when fetching OCSP Responses for peer certificate + set_at: startup + cpp_vartype: int + default: 5 + cpp_varname: "gTLSOCSPVerifyTimeoutSecs" + validator: + gte: 1 + tlsOCSPStaplingTimeoutSecs: + description: >- + How long the http client should wait before timing out + when fetching OCSP Responses for stapling. If not set, + value is taken from tlsClientOCSPTimeoutSecs + set_at: startup + cpp_vartype: int + default: -1 + cpp_varname: "gTLSOCSPStaplingTimeoutSecs" + validator: + gte: 1 opensslCipherConfig: description: "Cipher configuration string for OpenSSL based TLS connections" |