aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal')
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp916
1 files changed, 458 insertions, 458 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp
index 24145e4d92..7dd2bd53ad 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp
@@ -1,7 +1,7 @@
-/**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
#include <aws/core/internal/AWSHttpResourceClient.h>
#include <aws/core/client/DefaultRetryStrategy.h>
@@ -10,31 +10,31 @@
#include <aws/core/http/HttpResponse.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>
-#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/HashingUtils.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/client/CoreErrors.h>
-#include <aws/core/utils/xml/XmlSerializer.h>
-#include <mutex>
+#include <aws/core/utils/xml/XmlSerializer.h>
+#include <mutex>
#include <sstream>
-using namespace Aws;
+using namespace Aws;
using namespace Aws::Utils;
using namespace Aws::Utils::Logging;
-using namespace Aws::Utils::Xml;
+using namespace Aws::Utils::Xml;
using namespace Aws::Http;
using namespace Aws::Client;
using namespace Aws::Internal;
-static const char EC2_SECURITY_CREDENTIALS_RESOURCE[] = "/latest/meta-data/iam/security-credentials";
-static const char EC2_REGION_RESOURCE[] = "/latest/meta-data/placement/availability-zone";
-static const char EC2_IMDS_TOKEN_RESOURCE[] = "/latest/api/token";
-static const char EC2_IMDS_TOKEN_TTL_DEFAULT_VALUE[] = "21600";
-static const char EC2_IMDS_TOKEN_TTL_HEADER[] = "x-aws-ec2-metadata-token-ttl-seconds";
-static const char EC2_IMDS_TOKEN_HEADER[] = "x-aws-ec2-metadata-token";
-static const char RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG[] = "AWSHttpResourceClient";
-static const char EC2_METADATA_CLIENT_LOG_TAG[] = "EC2MetadataClient";
-static const char ECS_CREDENTIALS_CLIENT_LOG_TAG[] = "ECSCredentialsClient";
+static const char EC2_SECURITY_CREDENTIALS_RESOURCE[] = "/latest/meta-data/iam/security-credentials";
+static const char EC2_REGION_RESOURCE[] = "/latest/meta-data/placement/availability-zone";
+static const char EC2_IMDS_TOKEN_RESOURCE[] = "/latest/api/token";
+static const char EC2_IMDS_TOKEN_TTL_DEFAULT_VALUE[] = "21600";
+static const char EC2_IMDS_TOKEN_TTL_HEADER[] = "x-aws-ec2-metadata-token-ttl-seconds";
+static const char EC2_IMDS_TOKEN_HEADER[] = "x-aws-ec2-metadata-token";
+static const char RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG[] = "AWSHttpResourceClient";
+static const char EC2_METADATA_CLIENT_LOG_TAG[] = "EC2MetadataClient";
+static const char ECS_CREDENTIALS_CLIENT_LOG_TAG[] = "ECSCredentialsClient";
namespace Aws
{
@@ -43,464 +43,464 @@ namespace Aws
Aws::String ComputeUserAgentString();
}
- namespace Internal
- {
- static ClientConfiguration MakeDefaultHttpResourceClientConfiguration(const char *logtag)
- {
- ClientConfiguration res;
-
- res.maxConnections = 2;
- res.scheme = Scheme::HTTP;
-
- #if defined(WIN32) && defined(BYPASS_DEFAULT_PROXY)
- // For security reasons, we must bypass any proxy settings when fetching sensitive information, for example
- // user credentials. On Windows, IXMLHttpRequest2 does not support bypassing proxy settings, therefore,
- // we force using WinHTTP client. On POSIX systems, CURL is set to bypass proxy settings by default.
- res.httpLibOverride = TransferLibType::WIN_HTTP_CLIENT;
- AWS_LOGSTREAM_INFO(logtag, "Overriding the current HTTP client to WinHTTP to bypass proxy settings.");
- #else
- (void) logtag; // To disable warning about unused variable
- #endif
- // Explicitly set the proxy settings to empty/zero to avoid relying on defaults that could potentially change
- // in the future.
- res.proxyHost = "";
- res.proxyUserName = "";
- res.proxyPassword = "";
- res.proxyPort = 0;
-
- // EC2MetadataService throttles by delaying the response so the service client should set a large read timeout.
- // EC2MetadataService delay is in order of seconds so it only make sense to retry after a couple of seconds.
- res.connectTimeoutMs = 1000;
- res.requestTimeoutMs = 1000;
- res.retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG, 1, 1000);
-
- return res;
- }
-
- AWSHttpResourceClient::AWSHttpResourceClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* logtag)
- : m_logtag(logtag), m_retryStrategy(clientConfiguration.retryStrategy), m_httpClient(nullptr)
- {
- AWS_LOGSTREAM_INFO(m_logtag.c_str(),
- "Creating AWSHttpResourceClient with max connections "
- << clientConfiguration.maxConnections
- << " and scheme "
- << SchemeMapper::ToString(clientConfiguration.scheme));
-
- m_httpClient = CreateHttpClient(clientConfiguration);
- }
-
- AWSHttpResourceClient::AWSHttpResourceClient(const char* logtag)
- : AWSHttpResourceClient(MakeDefaultHttpResourceClientConfiguration(logtag), logtag)
- {
- }
-
- AWSHttpResourceClient::~AWSHttpResourceClient()
- {
- }
-
- Aws::String AWSHttpResourceClient::GetResource(const char* endpoint, const char* resource, const char* authToken) const
- {
- return GetResourceWithAWSWebServiceResult(endpoint, resource, authToken).GetPayload();
- }
-
- AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const char *endpoint, const char *resource, const char *authToken) const
+ namespace Internal
+ {
+ static ClientConfiguration MakeDefaultHttpResourceClientConfiguration(const char *logtag)
+ {
+ ClientConfiguration res;
+
+ res.maxConnections = 2;
+ res.scheme = Scheme::HTTP;
+
+ #if defined(WIN32) && defined(BYPASS_DEFAULT_PROXY)
+ // For security reasons, we must bypass any proxy settings when fetching sensitive information, for example
+ // user credentials. On Windows, IXMLHttpRequest2 does not support bypassing proxy settings, therefore,
+ // we force using WinHTTP client. On POSIX systems, CURL is set to bypass proxy settings by default.
+ res.httpLibOverride = TransferLibType::WIN_HTTP_CLIENT;
+ AWS_LOGSTREAM_INFO(logtag, "Overriding the current HTTP client to WinHTTP to bypass proxy settings.");
+ #else
+ (void) logtag; // To disable warning about unused variable
+ #endif
+ // Explicitly set the proxy settings to empty/zero to avoid relying on defaults that could potentially change
+ // in the future.
+ res.proxyHost = "";
+ res.proxyUserName = "";
+ res.proxyPassword = "";
+ res.proxyPort = 0;
+
+ // EC2MetadataService throttles by delaying the response so the service client should set a large read timeout.
+ // EC2MetadataService delay is in order of seconds so it only make sense to retry after a couple of seconds.
+ res.connectTimeoutMs = 1000;
+ res.requestTimeoutMs = 1000;
+ res.retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(RESOURCE_CLIENT_CONFIGURATION_ALLOCATION_TAG, 1, 1000);
+
+ return res;
+ }
+
+ AWSHttpResourceClient::AWSHttpResourceClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* logtag)
+ : m_logtag(logtag), m_retryStrategy(clientConfiguration.retryStrategy), m_httpClient(nullptr)
+ {
+ AWS_LOGSTREAM_INFO(m_logtag.c_str(),
+ "Creating AWSHttpResourceClient with max connections "
+ << clientConfiguration.maxConnections
+ << " and scheme "
+ << SchemeMapper::ToString(clientConfiguration.scheme));
+
+ m_httpClient = CreateHttpClient(clientConfiguration);
+ }
+
+ AWSHttpResourceClient::AWSHttpResourceClient(const char* logtag)
+ : AWSHttpResourceClient(MakeDefaultHttpResourceClientConfiguration(logtag), logtag)
+ {
+ }
+
+ AWSHttpResourceClient::~AWSHttpResourceClient()
+ {
+ }
+
+ Aws::String AWSHttpResourceClient::GetResource(const char* endpoint, const char* resource, const char* authToken) const
+ {
+ return GetResourceWithAWSWebServiceResult(endpoint, resource, authToken).GetPayload();
+ }
+
+ AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const char *endpoint, const char *resource, const char *authToken) const
+ {
+ Aws::StringStream ss;
+ ss << endpoint;
+ if (resource)
+ {
+ ss << resource;
+ }
+ std::shared_ptr<HttpRequest> request(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+
+ request->SetUserAgent(ComputeUserAgentString());
+
+ if (authToken)
+ {
+ request->SetHeaderValue(Aws::Http::AWS_AUTHORIZATION_HEADER, authToken);
+ }
+
+ return GetResourceWithAWSWebServiceResult(request);
+ }
+
+ AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const std::shared_ptr<HttpRequest> &httpRequest) const
{
- Aws::StringStream ss;
- ss << endpoint;
- if (resource)
- {
- ss << resource;
- }
- std::shared_ptr<HttpRequest> request(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
-
- request->SetUserAgent(ComputeUserAgentString());
-
- if (authToken)
- {
- request->SetHeaderValue(Aws::Http::AWS_AUTHORIZATION_HEADER, authToken);
- }
-
- return GetResourceWithAWSWebServiceResult(request);
- }
-
- AmazonWebServiceResult<Aws::String> AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const std::shared_ptr<HttpRequest> &httpRequest) const
- {
- AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Retrieving credentials from " << httpRequest->GetURIString());
-
- for (long retries = 0;; retries++)
- {
- std::shared_ptr<HttpResponse> response(m_httpClient->MakeRequest(httpRequest));
-
- if (response->GetResponseCode() == HttpResponseCode::OK)
- {
- Aws::IStreamBufIterator eos;
- return {Aws::String(Aws::IStreamBufIterator(response->GetResponseBody()), eos), response->GetHeaders(), HttpResponseCode::OK};
- }
-
- const Aws::Client::AWSError<Aws::Client::CoreErrors> error = [this, &response]() {
- if (response->HasClientError() || response->GetResponseBody().tellp() < 1)
- {
- AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Http request to retrieve credentials failed");
- return AWSError<CoreErrors>(CoreErrors::NETWORK_CONNECTION, true); // Retryable
- }
- else if (m_errorMarshaller)
- {
- return m_errorMarshaller->Marshall(*response);
- }
- else
- {
- const auto responseCode = response->GetResponseCode();
-
- AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Http request to retrieve credentials failed with error code "
- << static_cast<int>(responseCode));
- return CoreErrorsMapper::GetErrorForHttpResponseCode(responseCode);
- }
- }();
-
- if (!m_retryStrategy->ShouldRetry(error, retries))
- {
- AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Can not retrive resource from " << httpRequest->GetURIString());
- return {{}, response->GetHeaders(), error.GetResponseCode()};
- }
- auto sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(error, retries);
- AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Request failed, now waiting " << sleepMillis << " ms before attempting again.");
- m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis));
- }
- }
-
- EC2MetadataClient::EC2MetadataClient(const char* endpoint)
- : AWSHttpResourceClient(EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true)
- {
- }
-
- EC2MetadataClient::EC2MetadataClient(const Aws::Client::ClientConfiguration &clientConfiguration, const char *endpoint)
- : AWSHttpResourceClient(clientConfiguration, EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true)
- {
- }
-
- EC2MetadataClient::~EC2MetadataClient()
- {
-
- }
-
- Aws::String EC2MetadataClient::GetResource(const char* resourcePath) const
- {
- return GetResource(m_endpoint.c_str(), resourcePath, nullptr/*authToken*/);
- }
-
- Aws::String EC2MetadataClient::GetDefaultCredentials() const
- {
- std::unique_lock<std::recursive_mutex> locker(m_tokenMutex);
- if (m_tokenRequired)
- {
- return GetDefaultCredentialsSecurely();
- }
-
- AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting default credentials for ec2 instance");
- auto result = GetResourceWithAWSWebServiceResult(m_endpoint.c_str(), EC2_SECURITY_CREDENTIALS_RESOURCE, nullptr);
- Aws::String credentialsString = result.GetPayload();
- auto httpResponseCode = result.GetResponseCode();
-
- // Note, if service is insane, it might return 404 for our initial secure call,
- // then when we fall back to insecure call, it might return 401 ask for secure call,
- // Then, SDK might get into a recursive loop call situation between secure and insecure call.
- if (httpResponseCode == Http::HttpResponseCode::UNAUTHORIZED)
- {
- m_tokenRequired = true;
- return {};
- }
- locker.unlock();
-
- Aws::String trimmedCredentialsString = StringUtils::Trim(credentialsString.c_str());
- if (trimmedCredentialsString.empty()) return {};
-
- Aws::Vector<Aws::String> securityCredentials = StringUtils::Split(trimmedCredentialsString, '\n');
-
- AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource, " << EC2_SECURITY_CREDENTIALS_RESOURCE
- << " returned credential string " << trimmedCredentialsString);
-
- if (securityCredentials.size() == 0)
- {
- AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Initial call to ec2Metadataservice to get credentials failed");
- return {};
- }
-
- Aws::StringStream ss;
- ss << EC2_SECURITY_CREDENTIALS_RESOURCE << "/" << securityCredentials[0];
- AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str());
- return GetResource(ss.str().c_str());
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Retrieving credentials from " << httpRequest->GetURIString());
+
+ for (long retries = 0;; retries++)
+ {
+ std::shared_ptr<HttpResponse> response(m_httpClient->MakeRequest(httpRequest));
+
+ if (response->GetResponseCode() == HttpResponseCode::OK)
+ {
+ Aws::IStreamBufIterator eos;
+ return {Aws::String(Aws::IStreamBufIterator(response->GetResponseBody()), eos), response->GetHeaders(), HttpResponseCode::OK};
+ }
+
+ const Aws::Client::AWSError<Aws::Client::CoreErrors> error = [this, &response]() {
+ if (response->HasClientError() || response->GetResponseBody().tellp() < 1)
+ {
+ AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Http request to retrieve credentials failed");
+ return AWSError<CoreErrors>(CoreErrors::NETWORK_CONNECTION, true); // Retryable
+ }
+ else if (m_errorMarshaller)
+ {
+ return m_errorMarshaller->Marshall(*response);
+ }
+ else
+ {
+ const auto responseCode = response->GetResponseCode();
+
+ AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Http request to retrieve credentials failed with error code "
+ << static_cast<int>(responseCode));
+ return CoreErrorsMapper::GetErrorForHttpResponseCode(responseCode);
+ }
+ }();
+
+ if (!m_retryStrategy->ShouldRetry(error, retries))
+ {
+ AWS_LOGSTREAM_ERROR(m_logtag.c_str(), "Can not retrive resource from " << httpRequest->GetURIString());
+ return {{}, response->GetHeaders(), error.GetResponseCode()};
+ }
+ auto sleepMillis = m_retryStrategy->CalculateDelayBeforeNextRetry(error, retries);
+ AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Request failed, now waiting " << sleepMillis << " ms before attempting again.");
+ m_httpClient->RetryRequestSleep(std::chrono::milliseconds(sleepMillis));
+ }
}
- Aws::String EC2MetadataClient::GetDefaultCredentialsSecurely() const
- {
- std::unique_lock<std::recursive_mutex> locker(m_tokenMutex);
- if (!m_tokenRequired)
- {
- return GetDefaultCredentials();
- }
+ EC2MetadataClient::EC2MetadataClient(const char* endpoint)
+ : AWSHttpResourceClient(EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true)
+ {
+ }
- Aws::StringStream ss;
- ss << m_endpoint << EC2_IMDS_TOKEN_RESOURCE;
- std::shared_ptr<HttpRequest> tokenRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_PUT,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
- tokenRequest->SetHeaderValue(EC2_IMDS_TOKEN_TTL_HEADER, EC2_IMDS_TOKEN_TTL_DEFAULT_VALUE);
- auto userAgentString = ComputeUserAgentString();
- tokenRequest->SetUserAgent(userAgentString);
- AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Calling EC2MetadataService to get token");
- auto result = GetResourceWithAWSWebServiceResult(tokenRequest);
- Aws::String tokenString = result.GetPayload();
- Aws::String trimmedTokenString = StringUtils::Trim(tokenString.c_str());
-
- if (result.GetResponseCode() == HttpResponseCode::BAD_REQUEST)
- {
- return {};
- }
- else if (result.GetResponseCode() != HttpResponseCode::OK || trimmedTokenString.empty())
- {
- m_tokenRequired = false;
- AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Calling EC2MetadataService to get token failed, falling back to less secure way.");
- return GetDefaultCredentials();
- }
- m_token = trimmedTokenString;
- locker.unlock();
- ss.str("");
- ss << m_endpoint << EC2_SECURITY_CREDENTIALS_RESOURCE;
- std::shared_ptr<HttpRequest> profileRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
- profileRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, trimmedTokenString);
- profileRequest->SetUserAgent(userAgentString);
- Aws::String profileString = GetResourceWithAWSWebServiceResult(profileRequest).GetPayload();
-
- Aws::String trimmedProfileString = StringUtils::Trim(profileString.c_str());
- Aws::Vector<Aws::String> securityCredentials = StringUtils::Split(trimmedProfileString, '\n');
-
- AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource, " << EC2_SECURITY_CREDENTIALS_RESOURCE
- << " with token returned profile string " << trimmedProfileString);
- if (securityCredentials.size() == 0)
- {
- AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Calling EC2Metadataservice to get profiles failed");
- return {};
- }
-
- ss.str("");
- ss << m_endpoint << EC2_SECURITY_CREDENTIALS_RESOURCE << "/" << securityCredentials[0];
- std::shared_ptr<HttpRequest> credentialsRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
- credentialsRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, trimmedTokenString);
- credentialsRequest->SetUserAgent(userAgentString);
- AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str() << " with token.");
- return GetResourceWithAWSWebServiceResult(credentialsRequest).GetPayload();
- }
-
- Aws::String EC2MetadataClient::GetCurrentRegion() const
+ EC2MetadataClient::EC2MetadataClient(const Aws::Client::ClientConfiguration &clientConfiguration, const char *endpoint)
+ : AWSHttpResourceClient(clientConfiguration, EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true)
{
- if (!m_region.empty())
- {
- return m_region;
- }
-
- AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting current region for ec2 instance");
-
- Aws::StringStream ss;
- ss << m_endpoint << EC2_REGION_RESOURCE;
- std::shared_ptr<HttpRequest> regionRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
- {
- std::lock_guard<std::recursive_mutex> locker(m_tokenMutex);
- if (m_tokenRequired)
- {
- regionRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, m_token);
- }
- }
- regionRequest->SetUserAgent(ComputeUserAgentString());
- Aws::String azString = GetResourceWithAWSWebServiceResult(regionRequest).GetPayload();
-
- if (azString.empty())
- {
- AWS_LOGSTREAM_INFO(m_logtag.c_str() ,
- "Unable to pull region from instance metadata service ");
- return {};
- }
-
- Aws::String trimmedAZString = StringUtils::Trim(azString.c_str());
- AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource "
- << EC2_REGION_RESOURCE << " , returned credential string " << trimmedAZString);
-
- Aws::String region;
- region.reserve(trimmedAZString.length());
-
- bool digitFound = false;
- for (auto character : trimmedAZString)
- {
- if(digitFound && !isdigit(character))
- {
- break;
- }
- if (isdigit(character))
- {
- digitFound = true;
- }
-
- region.append(1, character);
- }
-
- AWS_LOGSTREAM_INFO(m_logtag.c_str(), "Detected current region as " << region);
- m_region = region;
- return region;
}
- #ifdef _MSC_VER
- // VS2015 compiler's bug, warning s_ec2metadataClient: symbol will be dynamically initialized (implementation limitation)
- AWS_SUPPRESS_WARNING(4592,
- static std::shared_ptr<EC2MetadataClient> s_ec2metadataClient(nullptr);
- )
- #else
- static std::shared_ptr<EC2MetadataClient> s_ec2metadataClient(nullptr);
- #endif
-
- void InitEC2MetadataClient()
- {
- if (s_ec2metadataClient)
+ EC2MetadataClient::~EC2MetadataClient()
+ {
+
+ }
+
+ Aws::String EC2MetadataClient::GetResource(const char* resourcePath) const
+ {
+ return GetResource(m_endpoint.c_str(), resourcePath, nullptr/*authToken*/);
+ }
+
+ Aws::String EC2MetadataClient::GetDefaultCredentials() const
+ {
+ std::unique_lock<std::recursive_mutex> locker(m_tokenMutex);
+ if (m_tokenRequired)
{
- return;
+ return GetDefaultCredentialsSecurely();
}
- s_ec2metadataClient = Aws::MakeShared<EC2MetadataClient>(EC2_METADATA_CLIENT_LOG_TAG);
- }
-
- void CleanupEC2MetadataClient()
- {
- if (!s_ec2metadataClient)
+
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting default credentials for ec2 instance");
+ auto result = GetResourceWithAWSWebServiceResult(m_endpoint.c_str(), EC2_SECURITY_CREDENTIALS_RESOURCE, nullptr);
+ Aws::String credentialsString = result.GetPayload();
+ auto httpResponseCode = result.GetResponseCode();
+
+ // Note, if service is insane, it might return 404 for our initial secure call,
+ // then when we fall back to insecure call, it might return 401 ask for secure call,
+ // Then, SDK might get into a recursive loop call situation between secure and insecure call.
+ if (httpResponseCode == Http::HttpResponseCode::UNAUTHORIZED)
{
- return;
+ m_tokenRequired = true;
+ return {};
+ }
+ locker.unlock();
+
+ Aws::String trimmedCredentialsString = StringUtils::Trim(credentialsString.c_str());
+ if (trimmedCredentialsString.empty()) return {};
+
+ Aws::Vector<Aws::String> securityCredentials = StringUtils::Split(trimmedCredentialsString, '\n');
+
+ AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource, " << EC2_SECURITY_CREDENTIALS_RESOURCE
+ << " returned credential string " << trimmedCredentialsString);
+
+ if (securityCredentials.size() == 0)
+ {
+ AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Initial call to ec2Metadataservice to get credentials failed");
+ return {};
}
- s_ec2metadataClient = nullptr;
- }
- std::shared_ptr<EC2MetadataClient> GetEC2MetadataClient()
+ Aws::StringStream ss;
+ ss << EC2_SECURITY_CREDENTIALS_RESOURCE << "/" << securityCredentials[0];
+ AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str());
+ return GetResource(ss.str().c_str());
+ }
+
+ Aws::String EC2MetadataClient::GetDefaultCredentialsSecurely() const
{
- return s_ec2metadataClient;
+ std::unique_lock<std::recursive_mutex> locker(m_tokenMutex);
+ if (!m_tokenRequired)
+ {
+ return GetDefaultCredentials();
+ }
+
+ Aws::StringStream ss;
+ ss << m_endpoint << EC2_IMDS_TOKEN_RESOURCE;
+ std::shared_ptr<HttpRequest> tokenRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_PUT,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+ tokenRequest->SetHeaderValue(EC2_IMDS_TOKEN_TTL_HEADER, EC2_IMDS_TOKEN_TTL_DEFAULT_VALUE);
+ auto userAgentString = ComputeUserAgentString();
+ tokenRequest->SetUserAgent(userAgentString);
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Calling EC2MetadataService to get token");
+ auto result = GetResourceWithAWSWebServiceResult(tokenRequest);
+ Aws::String tokenString = result.GetPayload();
+ Aws::String trimmedTokenString = StringUtils::Trim(tokenString.c_str());
+
+ if (result.GetResponseCode() == HttpResponseCode::BAD_REQUEST)
+ {
+ return {};
+ }
+ else if (result.GetResponseCode() != HttpResponseCode::OK || trimmedTokenString.empty())
+ {
+ m_tokenRequired = false;
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Calling EC2MetadataService to get token failed, falling back to less secure way.");
+ return GetDefaultCredentials();
+ }
+ m_token = trimmedTokenString;
+ locker.unlock();
+ ss.str("");
+ ss << m_endpoint << EC2_SECURITY_CREDENTIALS_RESOURCE;
+ std::shared_ptr<HttpRequest> profileRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+ profileRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, trimmedTokenString);
+ profileRequest->SetUserAgent(userAgentString);
+ Aws::String profileString = GetResourceWithAWSWebServiceResult(profileRequest).GetPayload();
+
+ Aws::String trimmedProfileString = StringUtils::Trim(profileString.c_str());
+ Aws::Vector<Aws::String> securityCredentials = StringUtils::Split(trimmedProfileString, '\n');
+
+ AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource, " << EC2_SECURITY_CREDENTIALS_RESOURCE
+ << " with token returned profile string " << trimmedProfileString);
+ if (securityCredentials.size() == 0)
+ {
+ AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Calling EC2Metadataservice to get profiles failed");
+ return {};
+ }
+
+ ss.str("");
+ ss << m_endpoint << EC2_SECURITY_CREDENTIALS_RESOURCE << "/" << securityCredentials[0];
+ std::shared_ptr<HttpRequest> credentialsRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+ credentialsRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, trimmedTokenString);
+ credentialsRequest->SetUserAgent(userAgentString);
+ AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str() << " with token.");
+ return GetResourceWithAWSWebServiceResult(credentialsRequest).GetPayload();
}
-
- ECSCredentialsClient::ECSCredentialsClient(const char* resourcePath, const char* endpoint, const char* token)
- : AWSHttpResourceClient(ECS_CREDENTIALS_CLIENT_LOG_TAG),
- m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token)
+ Aws::String EC2MetadataClient::GetCurrentRegion() const
+ {
+ if (!m_region.empty())
+ {
+ return m_region;
+ }
+
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting current region for ec2 instance");
+
+ Aws::StringStream ss;
+ ss << m_endpoint << EC2_REGION_RESOURCE;
+ std::shared_ptr<HttpRequest> regionRequest(CreateHttpRequest(ss.str(), HttpMethod::HTTP_GET,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_tokenMutex);
+ if (m_tokenRequired)
+ {
+ regionRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, m_token);
+ }
+ }
+ regionRequest->SetUserAgent(ComputeUserAgentString());
+ Aws::String azString = GetResourceWithAWSWebServiceResult(regionRequest).GetPayload();
+
+ if (azString.empty())
+ {
+ AWS_LOGSTREAM_INFO(m_logtag.c_str() ,
+ "Unable to pull region from instance metadata service ");
+ return {};
+ }
+
+ Aws::String trimmedAZString = StringUtils::Trim(azString.c_str());
+ AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource "
+ << EC2_REGION_RESOURCE << " , returned credential string " << trimmedAZString);
+
+ Aws::String region;
+ region.reserve(trimmedAZString.length());
+
+ bool digitFound = false;
+ for (auto character : trimmedAZString)
+ {
+ if(digitFound && !isdigit(character))
+ {
+ break;
+ }
+ if (isdigit(character))
+ {
+ digitFound = true;
+ }
+
+ region.append(1, character);
+ }
+
+ AWS_LOGSTREAM_INFO(m_logtag.c_str(), "Detected current region as " << region);
+ m_region = region;
+ return region;
+ }
+
+ #ifdef _MSC_VER
+ // VS2015 compiler's bug, warning s_ec2metadataClient: symbol will be dynamically initialized (implementation limitation)
+ AWS_SUPPRESS_WARNING(4592,
+ static std::shared_ptr<EC2MetadataClient> s_ec2metadataClient(nullptr);
+ )
+ #else
+ static std::shared_ptr<EC2MetadataClient> s_ec2metadataClient(nullptr);
+ #endif
+
+ void InitEC2MetadataClient()
+ {
+ if (s_ec2metadataClient)
+ {
+ return;
+ }
+ s_ec2metadataClient = Aws::MakeShared<EC2MetadataClient>(EC2_METADATA_CLIENT_LOG_TAG);
+ }
+
+ void CleanupEC2MetadataClient()
+ {
+ if (!s_ec2metadataClient)
+ {
+ return;
+ }
+ s_ec2metadataClient = nullptr;
+ }
+
+ std::shared_ptr<EC2MetadataClient> GetEC2MetadataClient()
+ {
+ return s_ec2metadataClient;
+ }
+
+
+ ECSCredentialsClient::ECSCredentialsClient(const char* resourcePath, const char* endpoint, const char* token)
+ : AWSHttpResourceClient(ECS_CREDENTIALS_CLIENT_LOG_TAG),
+ m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token)
{
}
-
- ECSCredentialsClient::ECSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* resourcePath, const char* endpoint, const char* token)
- : AWSHttpResourceClient(clientConfiguration, ECS_CREDENTIALS_CLIENT_LOG_TAG),
- m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token)
+
+ ECSCredentialsClient::ECSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration, const char* resourcePath, const char* endpoint, const char* token)
+ : AWSHttpResourceClient(clientConfiguration, ECS_CREDENTIALS_CLIENT_LOG_TAG),
+ m_resourcePath(resourcePath), m_endpoint(endpoint), m_token(token)
{
}
- static const char STS_RESOURCE_CLIENT_LOG_TAG[] = "STSResourceClient";
- STSCredentialsClient::STSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration)
- : AWSHttpResourceClient(clientConfiguration, STS_RESOURCE_CLIENT_LOG_TAG)
- {
- SetErrorMarshaller(Aws::MakeUnique<Aws::Client::XmlErrorMarshaller>(STS_RESOURCE_CLIENT_LOG_TAG));
-
- Aws::StringStream ss;
- if (clientConfiguration.scheme == Aws::Http::Scheme::HTTP)
- {
- ss << "http://";
- }
- else
- {
- ss << "https://";
- }
-
- static const int CN_NORTH_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTH_1);
- static const int CN_NORTHWEST_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTHWEST_1);
- auto hash = Aws::Utils::HashingUtils::HashString(clientConfiguration.region.c_str());
-
- ss << "sts." << clientConfiguration.region << ".amazonaws.com";
- if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
- {
- ss << ".cn";
- }
- m_endpoint = ss.str();
-
- AWS_LOGSTREAM_INFO(STS_RESOURCE_CLIENT_LOG_TAG, "Creating STS ResourceClient with endpoint: " << m_endpoint);
- }
-
- STSCredentialsClient::STSAssumeRoleWithWebIdentityResult STSCredentialsClient::GetAssumeRoleWithWebIdentityCredentials(const STSAssumeRoleWithWebIdentityRequest& request)
- {
- //Calculate query string
- Aws::StringStream ss;
- ss << "Action=AssumeRoleWithWebIdentity"
- << "&Version=2011-06-15"
- << "&RoleSessionName=" << Aws::Utils::StringUtils::URLEncode(request.roleSessionName.c_str())
- << "&RoleArn=" << Aws::Utils::StringUtils::URLEncode(request.roleArn.c_str())
- << "&WebIdentityToken=" << Aws::Utils::StringUtils::URLEncode(request.webIdentityToken.c_str());
-
- std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(m_endpoint, HttpMethod::HTTP_POST,
- Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
-
- httpRequest->SetUserAgent(ComputeUserAgentString());
-
- std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::StringStream>("STS_RESOURCE_CLIENT_LOG_TAG");
- *body << ss.str();
-
- httpRequest->AddContentBody(body);
- body->seekg(0, body->end);
- auto streamSize = body->tellg();
- body->seekg(0, body->beg);
- Aws::StringStream contentLength;
- contentLength << streamSize;
- httpRequest->SetContentLength(contentLength.str());
- httpRequest->SetContentType("application/x-www-form-urlencoded");
-
- Aws::String credentialsStr = GetResourceWithAWSWebServiceResult(httpRequest).GetPayload();
-
- //Parse credentials
- STSAssumeRoleWithWebIdentityResult result;
- if (credentialsStr.empty())
- {
- AWS_LOGSTREAM_WARN(STS_RESOURCE_CLIENT_LOG_TAG, "Get an empty credential from sts");
- return result;
- }
-
- const Utils::Xml::XmlDocument xmlDocument = XmlDocument::CreateFromXmlString(credentialsStr);
- XmlNode rootNode = xmlDocument.GetRootElement();
- XmlNode resultNode = rootNode;
- if (!rootNode.IsNull() && (rootNode.GetName() != "AssumeRoleWithWebIdentityResult"))
- {
- resultNode = rootNode.FirstChild("AssumeRoleWithWebIdentityResult");
- }
-
- if (!resultNode.IsNull())
- {
- XmlNode credentialsNode = resultNode.FirstChild("Credentials");
- if (!credentialsNode.IsNull())
- {
- XmlNode accessKeyIdNode = credentialsNode.FirstChild("AccessKeyId");
- if (!accessKeyIdNode.IsNull())
- {
- result.creds.SetAWSAccessKeyId(accessKeyIdNode.GetText());
- }
-
- XmlNode secretAccessKeyNode = credentialsNode.FirstChild("SecretAccessKey");
- if (!secretAccessKeyNode.IsNull())
- {
- result.creds.SetAWSSecretKey(secretAccessKeyNode.GetText());
- }
-
- XmlNode sessionTokenNode = credentialsNode.FirstChild("SessionToken");
- if (!sessionTokenNode.IsNull())
- {
- result.creds.SetSessionToken(sessionTokenNode.GetText());
- }
-
- XmlNode expirationNode = credentialsNode.FirstChild("Expiration");
- if (!expirationNode.IsNull())
- {
- result.creds.SetExpiration(DateTime(StringUtils::Trim(expirationNode.GetText().c_str()).c_str(), DateFormat::ISO_8601));
- }
- }
- }
- return result;
- }
- }
+ static const char STS_RESOURCE_CLIENT_LOG_TAG[] = "STSResourceClient";
+ STSCredentialsClient::STSCredentialsClient(const Aws::Client::ClientConfiguration& clientConfiguration)
+ : AWSHttpResourceClient(clientConfiguration, STS_RESOURCE_CLIENT_LOG_TAG)
+ {
+ SetErrorMarshaller(Aws::MakeUnique<Aws::Client::XmlErrorMarshaller>(STS_RESOURCE_CLIENT_LOG_TAG));
+
+ Aws::StringStream ss;
+ if (clientConfiguration.scheme == Aws::Http::Scheme::HTTP)
+ {
+ ss << "http://";
+ }
+ else
+ {
+ ss << "https://";
+ }
+
+ static const int CN_NORTH_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTH_1);
+ static const int CN_NORTHWEST_1_HASH = Aws::Utils::HashingUtils::HashString(Aws::Region::CN_NORTHWEST_1);
+ auto hash = Aws::Utils::HashingUtils::HashString(clientConfiguration.region.c_str());
+
+ ss << "sts." << clientConfiguration.region << ".amazonaws.com";
+ if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
+ {
+ ss << ".cn";
+ }
+ m_endpoint = ss.str();
+
+ AWS_LOGSTREAM_INFO(STS_RESOURCE_CLIENT_LOG_TAG, "Creating STS ResourceClient with endpoint: " << m_endpoint);
+ }
+
+ STSCredentialsClient::STSAssumeRoleWithWebIdentityResult STSCredentialsClient::GetAssumeRoleWithWebIdentityCredentials(const STSAssumeRoleWithWebIdentityRequest& request)
+ {
+ //Calculate query string
+ Aws::StringStream ss;
+ ss << "Action=AssumeRoleWithWebIdentity"
+ << "&Version=2011-06-15"
+ << "&RoleSessionName=" << Aws::Utils::StringUtils::URLEncode(request.roleSessionName.c_str())
+ << "&RoleArn=" << Aws::Utils::StringUtils::URLEncode(request.roleArn.c_str())
+ << "&WebIdentityToken=" << Aws::Utils::StringUtils::URLEncode(request.webIdentityToken.c_str());
+
+ std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(m_endpoint, HttpMethod::HTTP_POST,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+
+ httpRequest->SetUserAgent(ComputeUserAgentString());
+
+ std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::StringStream>("STS_RESOURCE_CLIENT_LOG_TAG");
+ *body << ss.str();
+
+ httpRequest->AddContentBody(body);
+ body->seekg(0, body->end);
+ auto streamSize = body->tellg();
+ body->seekg(0, body->beg);
+ Aws::StringStream contentLength;
+ contentLength << streamSize;
+ httpRequest->SetContentLength(contentLength.str());
+ httpRequest->SetContentType("application/x-www-form-urlencoded");
+
+ Aws::String credentialsStr = GetResourceWithAWSWebServiceResult(httpRequest).GetPayload();
+
+ //Parse credentials
+ STSAssumeRoleWithWebIdentityResult result;
+ if (credentialsStr.empty())
+ {
+ AWS_LOGSTREAM_WARN(STS_RESOURCE_CLIENT_LOG_TAG, "Get an empty credential from sts");
+ return result;
+ }
+
+ const Utils::Xml::XmlDocument xmlDocument = XmlDocument::CreateFromXmlString(credentialsStr);
+ XmlNode rootNode = xmlDocument.GetRootElement();
+ XmlNode resultNode = rootNode;
+ if (!rootNode.IsNull() && (rootNode.GetName() != "AssumeRoleWithWebIdentityResult"))
+ {
+ resultNode = rootNode.FirstChild("AssumeRoleWithWebIdentityResult");
+ }
+
+ if (!resultNode.IsNull())
+ {
+ XmlNode credentialsNode = resultNode.FirstChild("Credentials");
+ if (!credentialsNode.IsNull())
+ {
+ XmlNode accessKeyIdNode = credentialsNode.FirstChild("AccessKeyId");
+ if (!accessKeyIdNode.IsNull())
+ {
+ result.creds.SetAWSAccessKeyId(accessKeyIdNode.GetText());
+ }
+
+ XmlNode secretAccessKeyNode = credentialsNode.FirstChild("SecretAccessKey");
+ if (!secretAccessKeyNode.IsNull())
+ {
+ result.creds.SetAWSSecretKey(secretAccessKeyNode.GetText());
+ }
+
+ XmlNode sessionTokenNode = credentialsNode.FirstChild("SessionToken");
+ if (!sessionTokenNode.IsNull())
+ {
+ result.creds.SetSessionToken(sessionTokenNode.GetText());
+ }
+
+ XmlNode expirationNode = credentialsNode.FirstChild("Expiration");
+ if (!expirationNode.IsNull())
+ {
+ result.creds.SetExpiration(DateTime(StringUtils::Trim(expirationNode.GetText().c_str()).c_str(), DateFormat::ISO_8601));
+ }
+ }
+ }
+ return result;
+ }
+ }
}