aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source
diff options
context:
space:
mode:
authordakovalkov <dakovalkov@yandex-team.com>2023-12-03 13:33:55 +0300
committerdakovalkov <dakovalkov@yandex-team.com>2023-12-03 14:04:39 +0300
commit2a718325637e5302334b6d0a6430f63168f8dbb3 (patch)
tree64be81080b7df9ec1d86d053a0c394ae53fcf1fe /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source
parente0d94a470142d95c3007e9c5d80380994940664a (diff)
downloadydb-2a718325637e5302334b6d0a6430f63168f8dbb3.tar.gz
Update contrib/libs/aws-sdk-cpp to 1.11.37
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source')
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp14
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp45
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp48
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Region.cpp17
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp806
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp74
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp6
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/SSOCredentialsProvider.cpp32
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp11
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/DefaultBearerTokenProviderChain.cpp35
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/SSOBearerTokenProvider.cpp244
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/BearerTokenAuthSignerProvider.cpp46
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/DefaultAuthSignerProvider.cpp (renamed from contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp)13
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthBearerSigner.cpp50
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp320
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerCommon.cpp14
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerHelper.cpp103
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp580
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSNullSigner.cpp14
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp686
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp19
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp212
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp236
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp180
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp228
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp322
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp20
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp2
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp103
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp336
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp14
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSConfigFileProfileConfigLoader.cpp629
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp571
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoaderBase.cpp50
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/ConfigAndCredentialsCacheManager.cpp206
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp112
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/defaults/ClientConfigurationDefaults.cpp197
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSEndpoint.cpp86
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSPartitions.cpp153
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/BuiltInParameters.cpp135
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/ClientContextParameters.cpp61
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp236
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp20
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/internal/AWSEndpointAttribute.cpp82
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp31
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp16
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp4
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp105
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpResponse.cpp24
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp181
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp5
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp108
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp11
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp8
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp175
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp69
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp12
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Document.cpp673
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp27
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CRC32.cpp218
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp14
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha1.cpp10
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp12
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp73
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp136
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamDecoder.cpp8
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp101
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp17
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogSystem.cpp107
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogging.cpp31
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp6
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp63
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp10
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp15
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp2
75 files changed, 7557 insertions, 2083 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp
index a6b0406683c..c0f89adad01 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/AmazonWebServiceRequest.cpp
@@ -18,3 +18,17 @@ AmazonWebServiceRequest::AmazonWebServiceRequest() :
{
}
+AmazonWebServiceRequest::EndpointParameters AmazonWebServiceRequest::GetEndpointContextParams() const
+{
+ return AmazonWebServiceRequest::EndpointParameters();
+}
+
+const Aws::Http::HeaderValueCollection& AmazonWebServiceRequest::GetAdditionalCustomHeaders() const
+{
+ return m_additionalCustomHeaders;
+}
+
+void AmazonWebServiceRequest::SetAdditionalCustomHeaderValue(const Aws::String& headerName, const Aws::String& headerValue)
+{
+ m_additionalCustomHeaders[Utils::StringUtils::ToLower(headerName.c_str())] = Utils::StringUtils::Trim(headerValue.c_str());
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp
index 0711fd69d66..4fd97618f30 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Aws.cpp
@@ -7,6 +7,7 @@
#include <aws/core/Aws.h>
#include <aws/core/client/CoreErrors.h>
#include <aws/core/utils/logging/AWSLogging.h>
+#include <aws/core/utils/logging/CRTLogging.h>
#include <aws/core/utils/logging/DefaultLogSystem.h>
#include <aws/core/Globals.h>
#include <aws/core/external/cjson/cJSON.h>
@@ -27,6 +28,7 @@ namespace Aws
Aws::Utils::Memory::InitializeAWSMemorySystem(*options.memoryManagementOptions.memoryManager);
}
#endif // USE_AWS_MEMORY_MANAGEMENT
+ Aws::InitializeCrt();
Aws::Client::CoreErrorsMapper::InitCoreErrorsMapper();
if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off)
{
@@ -39,12 +41,46 @@ namespace Aws
Aws::Utils::Logging::InitializeAWSLogging(
Aws::MakeShared<Aws::Utils::Logging::DefaultLogSystem>(ALLOCATION_TAG, options.loggingOptions.logLevel, options.loggingOptions.defaultLogPrefix));
}
+ if(options.loggingOptions.crt_logger_create_fn)
+ {
+ Aws::Utils::Logging::InitializeCRTLogging(options.loggingOptions.crt_logger_create_fn());
+ }
+ else
+ {
+ Aws::Utils::Logging::InitializeCRTLogging(
+ Aws::MakeShared<Aws::Utils::Logging::DefaultCRTLogSystem>(ALLOCATION_TAG, options.loggingOptions.logLevel));
+ }
// For users to better debugging in case multiple versions of SDK installed
AWS_LOGSTREAM_INFO(ALLOCATION_TAG, "Initiate AWS SDK for C++ with Version:" << Aws::String(Aws::Version::GetVersionString()));
}
Aws::Config::InitConfigAndCredentialsCacheManager();
+ if (options.ioOptions.clientBootstrap_create_fn)
+ {
+ Aws::SetDefaultClientBootstrap(options.ioOptions.clientBootstrap_create_fn());
+ }
+ else
+ {
+ Aws::Crt::Io::EventLoopGroup eventLoopGroup;
+ Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8, 30);
+ auto clientBootstrap = Aws::MakeShared<Aws::Crt::Io::ClientBootstrap>(ALLOCATION_TAG, eventLoopGroup, defaultHostResolver);
+ clientBootstrap->EnableBlockingShutdown();
+ Aws::SetDefaultClientBootstrap(clientBootstrap);
+ }
+
+ if (options.ioOptions.tlsConnectionOptions_create_fn)
+ {
+ Aws::SetDefaultTlsConnectionOptions(options.ioOptions.tlsConnectionOptions_create_fn());
+ }
+ else
+ {
+ Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient();
+ Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT);
+ auto tlsConnectionOptions = Aws::MakeShared<Aws::Crt::Io::TlsConnectionOptions>(ALLOCATION_TAG, tlsContext.NewConnectionOptions());
+ Aws::SetDefaultTlsConnectionOptions(tlsConnectionOptions);
+ }
+
if (options.cryptoOptions.aes_CBCFactory_create_fn)
{
Aws::Utils::Crypto::SetAES_CBCFactory(options.cryptoOptions.aes_CBCFactory_create_fn());
@@ -100,6 +136,7 @@ namespace Aws
Aws::Http::SetInitCleanupCurlFlag(options.httpOptions.initAndCleanupCurl);
Aws::Http::SetInstallSigPipeHandlerFlag(options.httpOptions.installSigPipeHandler);
+ Aws::Http::SetCompliantRfc3986Encoding(options.httpOptions.compliantRfc3986Encoding);
Aws::Http::InitHttp();
Aws::InitializeEnumOverflowContainer();
cJSON_AS4CPP_Hooks hooks;
@@ -122,13 +159,13 @@ namespace Aws
Aws::Config::CleanupConfigAndCredentialsCacheManager();
- if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off)
+ Aws::Client::CoreErrorsMapper::CleanupCoreErrorsMapper();
+ Aws::CleanupCrt();
+ if (options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off)
{
+ Aws::Utils::Logging::ShutdownCRTLogging();
Aws::Utils::Logging::ShutdownAWSLogging();
}
-
- Aws::Client::CoreErrorsMapper::CleanupCoreErrorsMapper();
-
#ifdef USE_AWS_MEMORY_MANAGEMENT
if(options.memoryManagementOptions.memoryManager)
{
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp
index 55f2ee92203..8c26d2389dd 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Globals.cpp
@@ -2,13 +2,61 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
+
+#include <aws/crt/Api.h>
+#include <aws/crt/io/TlsOptions.h>
+#include <aws/crt/io/Bootstrap.h>
#include <aws/core/Globals.h>
#include <aws/core/utils/EnumParseOverflowContainer.h>
#include <aws/core/utils/memory/AWSMemory.h>
+#include <aws/auth/auth.h>
namespace Aws
{
static const char TAG[] = "GlobalEnumOverflowContainer";
+
+ static Aws::Crt::ApiHandle* g_apiHandle;
+ static std::shared_ptr<Aws::Crt::Io::ClientBootstrap> g_defaultClientBootstrap(nullptr);
+ static std::shared_ptr<Aws::Crt::Io::TlsConnectionOptions> g_defaultTlsConnectionOptions(nullptr);
+
+ Aws::Crt::ApiHandle* GetApiHandle()
+ {
+ return g_apiHandle;
+ }
+
+ void SetDefaultClientBootstrap(const std::shared_ptr<Aws::Crt::Io::ClientBootstrap>& clientBootstrap)
+ {
+ g_defaultClientBootstrap = clientBootstrap;
+ }
+
+ Aws::Crt::Io::ClientBootstrap* GetDefaultClientBootstrap()
+ {
+ return g_defaultClientBootstrap.get();
+ }
+
+ void SetDefaultTlsConnectionOptions(const std::shared_ptr<Aws::Crt::Io::TlsConnectionOptions>& tlsConnectionOptions)
+ {
+ g_defaultTlsConnectionOptions = tlsConnectionOptions;
+ }
+
+ Aws::Crt::Io::TlsConnectionOptions* GetDefaultTlsConnectionOptions()
+ {
+ return g_defaultTlsConnectionOptions.get();
+ }
+
+ void InitializeCrt()
+ {
+ g_apiHandle = Aws::New<Aws::Crt::ApiHandle>(TAG, Aws::get_aws_allocator());
+ }
+
+ void CleanupCrt()
+ {
+ Aws::SetDefaultClientBootstrap(nullptr);
+ Aws::SetDefaultTlsConnectionOptions(nullptr);
+ Aws::Delete(g_apiHandle);
+ g_apiHandle = nullptr;
+ }
+
static Utils::EnumParseOverflowContainer* g_enumOverflow;
Utils::EnumParseOverflowContainer* GetEnumOverflowContainer()
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Region.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Region.cpp
index 4b18bf2a2af..620923d6cdd 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Region.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/Region.cpp
@@ -15,6 +15,10 @@ namespace Aws
{
return Aws::Region::US_EAST_1;
}
+ else if (region == "fips-aws-global")
+ {
+ return Aws::Region::US_EAST_1;
+ }
else if (region == "s3-external-1")
{
return Aws::Region::US_EAST_1;
@@ -32,5 +36,18 @@ namespace Aws
return region;
}
}
+
+ bool IsFipsRegion(const Aws::String& region)
+ {
+ if (region.size() >= 5 && region.compare(0, 5, "fips-") == 0)
+ {
+ return true;
+ }
+ else if (region.size() >= 5 && region.compare(region.size() - 5, 5, "-fips") == 0)
+ {
+ return true;
+ }
+ return false;
+ }
}
} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp
deleted file mode 100644
index 0baa00058f9..00000000000
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp
+++ /dev/null
@@ -1,806 +0,0 @@
-/**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
-
-#include <aws/core/auth/AWSAuthSigner.h>
-
-#include <aws/core/auth/AWSCredentialsProvider.h>
-#include <aws/core/client/ClientConfiguration.h>
-#include <aws/core/http/HttpRequest.h>
-#include <aws/core/http/HttpResponse.h>
-#include <aws/core/utils/DateTime.h>
-#include <aws/core/utils/HashingUtils.h>
-#include <aws/core/utils/Outcome.h>
-#include <aws/core/utils/StringUtils.h>
-#include <aws/core/utils/logging/LogMacros.h>
-#include <aws/core/utils/memory/AWSMemory.h>
-#include <aws/core/utils/crypto/Sha256.h>
-#include <aws/core/utils/crypto/Sha256HMAC.h>
-#include <aws/core/utils/stream/PreallocatedStreamBuf.h>
-#include <aws/core/utils/event/EventMessage.h>
-#include <aws/core/utils/event/EventHeader.h>
-
-#include <cstdio>
-#include <iomanip>
-#include <math.h>
-#include <cstring>
-
-using namespace Aws;
-using namespace Aws::Client;
-using namespace Aws::Auth;
-using namespace Aws::Http;
-using namespace Aws::Utils;
-using namespace Aws::Utils::Logging;
-
-static const char* EQ = "=";
-static const char* AWS_HMAC_SHA256 = "AWS4-HMAC-SHA256";
-static const char* EVENT_STREAM_CONTENT_SHA256 = "STREAMING-AWS4-HMAC-SHA256-EVENTS";
-static const char* EVENT_STREAM_PAYLOAD = "AWS4-HMAC-SHA256-PAYLOAD";
-static const char* AWS4_REQUEST = "aws4_request";
-static const char* SIGNED_HEADERS = "SignedHeaders";
-static const char* CREDENTIAL = "Credential";
-static const char* NEWLINE = "\n";
-static const char* X_AMZ_SIGNED_HEADERS = "X-Amz-SignedHeaders";
-static const char* X_AMZ_ALGORITHM = "X-Amz-Algorithm";
-static const char* X_AMZ_CREDENTIAL = "X-Amz-Credential";
-static const char* UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
-static const char* X_AMZ_SIGNATURE = "X-Amz-Signature";
-static const char* X_AMZN_TRACE_ID = "x-amzn-trace-id";
-static const char* X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256";
-static const char* USER_AGENT = "user-agent";
-static const char* SIGNING_KEY = "AWS4";
-static const char* SIMPLE_DATE_FORMAT_STR = "%Y%m%d";
-static const char* EMPTY_STRING_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
-
-static const char v4LogTag[] = "AWSAuthV4Signer";
-static const char v4StreamingLogTag[] = "AWSAuthEventStreamV4Signer";
-
-namespace Aws
-{
- namespace Auth
- {
- const char SIGNATURE[] = "Signature";
- const char SIGV4_SIGNER[] = "SignatureV4";
- const char EVENTSTREAM_SIGV4_SIGNER[] = "EventStreamSignatureV4";
- const char EVENTSTREAM_SIGNATURE_HEADER[] = ":chunk-signature";
- const char EVENTSTREAM_DATE_HEADER[] = ":date";
- const char NULL_SIGNER[] = "NullSigner";
- }
-}
-
-static Aws::String CanonicalizeRequestSigningString(HttpRequest& request, bool urlEscapePath)
-{
- request.CanonicalizeRequest();
- Aws::StringStream signingStringStream;
- signingStringStream << HttpMethodMapper::GetNameForHttpMethod(request.GetMethod());
-
- URI uriCpy = request.GetUri();
- // Many AWS services do not decode the URL before calculating SignatureV4 on their end.
- // This results in the signature getting calculated with a double encoded URL.
- // That means we have to double encode it here for the signature to match on the service side.
- if(urlEscapePath)
- {
- // RFC3986 is how we encode the URL before sending it on the wire.
- auto rfc3986EncodedPath = URI::URLEncodePathRFC3986(uriCpy.GetPath());
- uriCpy.SetPath(rfc3986EncodedPath);
- // However, SignatureV4 uses this URL encoding scheme
- signingStringStream << NEWLINE << uriCpy.GetURLEncodedPath() << NEWLINE;
- }
- else
- {
- // For the services that DO decode the URL first; we don't need to double encode it.
- uriCpy.SetPath(uriCpy.GetURLEncodedPath());
- signingStringStream << NEWLINE << uriCpy.GetPath() << NEWLINE;
- }
-
- if (request.GetQueryString().find('=') != std::string::npos)
- {
- signingStringStream << request.GetQueryString().substr(1) << NEWLINE;
- }
- else if (request.GetQueryString().size() > 1)
- {
- signingStringStream << request.GetQueryString().substr(1) << "=" << NEWLINE;
- }
- else
- {
- signingStringStream << NEWLINE;
- }
-
- return signingStringStream.str();
-}
-
-static Http::HeaderValueCollection CanonicalizeHeaders(Http::HeaderValueCollection&& headers)
-{
- Http::HeaderValueCollection canonicalHeaders;
- for (const auto& header : headers)
- {
- auto trimmedHeaderName = StringUtils::Trim(header.first.c_str());
- auto trimmedHeaderValue = StringUtils::Trim(header.second.c_str());
-
- //multiline gets converted to line1,line2,etc...
- auto headerMultiLine = StringUtils::SplitOnLine(trimmedHeaderValue);
- Aws::String headerValue = headerMultiLine.size() == 0 ? "" : headerMultiLine[0];
-
- if (headerMultiLine.size() > 1)
- {
- for(size_t i = 1; i < headerMultiLine.size(); ++i)
- {
- headerValue += ",";
- headerValue += StringUtils::Trim(headerMultiLine[i].c_str());
- }
- }
-
- //duplicate spaces need to be converted to one.
- Aws::String::iterator new_end =
- std::unique(headerValue.begin(), headerValue.end(),
- [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
- );
- headerValue.erase(new_end, headerValue.end());
-
- canonicalHeaders[trimmedHeaderName] = headerValue;
- }
-
- return canonicalHeaders;
-}
-
-AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& credentialsProvider,
- const char* serviceName, const Aws::String& region, PayloadSigningPolicy signingPolicy, bool urlEscapePath) :
- m_includeSha256HashHeader(true),
- m_credentialsProvider(credentialsProvider),
- m_serviceName(serviceName),
- m_region(region),
- m_hash(Aws::MakeUnique<Aws::Utils::Crypto::Sha256>(v4LogTag)),
- m_HMAC(Aws::MakeUnique<Aws::Utils::Crypto::Sha256HMAC>(v4LogTag)),
- m_unsignedHeaders({USER_AGENT, X_AMZN_TRACE_ID}),
- m_payloadSigningPolicy(signingPolicy),
- m_urlEscapePath(urlEscapePath)
-{
- //go ahead and warm up the signing cache.
- ComputeHash(credentialsProvider->GetAWSCredentials().GetAWSSecretKey(), DateTime::CalculateGmtTimestampAsString(SIMPLE_DATE_FORMAT_STR), region, m_serviceName);
-}
-
-AWSAuthV4Signer::~AWSAuthV4Signer()
-{
- // empty destructor in .cpp file to keep from needing the implementation of (AWSCredentialsProvider, Sha256, Sha256HMAC) in the header file
-}
-
-
-bool AWSAuthV4Signer::ShouldSignHeader(const Aws::String& header) const
-{
- return m_unsignedHeaders.find(Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend();
-}
-
-bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool signBody) const
-{
- AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
-
- //don't sign anonymous requests
- if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
- {
- return true;
- }
-
- if (!credentials.GetSessionToken().empty())
- {
- request.SetAwsSessionToken(credentials.GetSessionToken());
- }
-
- Aws::String payloadHash(UNSIGNED_PAYLOAD);
- switch(m_payloadSigningPolicy)
- {
- case PayloadSigningPolicy::Always:
- signBody = true;
- break;
- case PayloadSigningPolicy::Never:
- signBody = false;
- break;
- case PayloadSigningPolicy::RequestDependent:
- // respect the request setting
- default:
- break;
- }
-
- if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS)
- {
- payloadHash = ComputePayloadHash(request);
- if (payloadHash.empty())
- {
- return false;
- }
- }
- else
- {
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody
- << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme()));
- }
-
- if(m_includeSha256HashHeader)
- {
- request.SetHeaderValue(X_AMZ_CONTENT_SHA256, payloadHash);
- }
-
- //calculate date header to use in internal signature (this also goes into date header).
- DateTime now = GetSigningTimestamp();
- Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
- request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue);
-
- Aws::StringStream headersStream;
- Aws::StringStream signedHeadersStream;
-
- for (const auto& header : CanonicalizeHeaders(request.GetHeaders()))
- {
- if(ShouldSignHeader(header.first))
- {
- headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE;
- signedHeadersStream << header.first.c_str() << ";";
- }
- }
-
- Aws::String canonicalHeadersString = headersStream.str();
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString);
-
- //calculate signed headers parameter
- Aws::String signedHeadersValue = signedHeadersStream.str();
- //remove that last semi-colon
- if (!signedHeadersValue.empty())
- {
- signedHeadersValue.pop_back();
- }
-
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value:" << signedHeadersValue);
-
- //generate generalized canonicalized request string.
- Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath);
-
- //append v4 stuff to the canonical request string.
- canonicalRequestString.append(canonicalHeadersString);
- canonicalRequestString.append(NEWLINE);
- canonicalRequestString.append(signedHeadersValue);
- canonicalRequestString.append(NEWLINE);
- canonicalRequestString.append(payloadHash);
-
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString);
-
- //now compute sha256 on that request string
- auto hashResult = m_hash->Calculate(canonicalRequestString);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string");
- AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\"");
- return false;
- }
-
- auto sha256Digest = hashResult.GetResult();
- Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
- Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR);
-
- Aws::String signingRegion = region ? region : m_region;
- Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
- Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
- auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
-
- Aws::StringStream ss;
- ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate
- << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST << ", " << SIGNED_HEADERS << EQ
- << signedHeadersValue << ", " << SIGNATURE << EQ << finalSignature;
-
- auto awsAuthString = ss.str();
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Signing request with: " << awsAuthString);
- request.SetAwsAuthorization(awsAuthString);
- request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
- request.SetSigningRegion(signingRegion);
- return true;
-}
-
-bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, long long expirationTimeInSeconds) const
-{
- return PresignRequest(request, m_region.c_str(), expirationTimeInSeconds);
-}
-
-bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, long long expirationInSeconds) const
-{
- return PresignRequest(request, region, m_serviceName.c_str(), expirationInSeconds);
-}
-
-bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, long long expirationTimeInSeconds) const
-{
- AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
-
- //don't sign anonymous requests
- if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
- {
- return true;
- }
-
- Aws::StringStream intConversionStream;
- intConversionStream << expirationTimeInSeconds;
- request.AddQueryStringParameter(Http::X_AMZ_EXPIRES_HEADER, intConversionStream.str());
-
- if (!credentials.GetSessionToken().empty())
- {
- request.AddQueryStringParameter(Http::AWS_SECURITY_TOKEN, credentials.GetSessionToken());
- }
-
- //calculate date header to use in internal signature (this also goes into date header).
- DateTime now = GetSigningTimestamp();
- Aws::String dateQueryValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
- request.AddQueryStringParameter(Http::AWS_DATE_HEADER, dateQueryValue);
-
- Aws::StringStream headersStream;
- Aws::StringStream signedHeadersStream;
- for (const auto& header : CanonicalizeHeaders(request.GetHeaders()))
- {
- if(ShouldSignHeader(header.first))
- {
- headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE;
- signedHeadersStream << header.first.c_str() << ";";
- }
- }
-
- Aws::String canonicalHeadersString = headersStream.str();
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString);
-
- //calculate signed headers parameter
- Aws::String signedHeadersValue(signedHeadersStream.str());
- //remove that last semi-colon
- if (!signedHeadersValue.empty())
- {
- signedHeadersValue.pop_back();
- }
-
- request.AddQueryStringParameter(X_AMZ_SIGNED_HEADERS, signedHeadersValue);
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value: " << signedHeadersValue);
-
- Aws::StringStream ss;
- Aws::String signingRegion = region ? region : m_region;
- Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
- Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR);
- ss << credentials.GetAWSAccessKeyId() << "/" << simpleDate
- << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST;
-
- request.AddQueryStringParameter(X_AMZ_ALGORITHM, AWS_HMAC_SHA256);
- request.AddQueryStringParameter(X_AMZ_CREDENTIAL, ss.str());
- ss.str("");
-
- request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
- request.SetSigningRegion(signingRegion);
-
- //generate generalized canonicalized request string.
- Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, m_urlEscapePath);
-
- //append v4 stuff to the canonical request string.
- canonicalRequestString.append(canonicalHeadersString);
- canonicalRequestString.append(NEWLINE);
- canonicalRequestString.append(signedHeadersValue);
- canonicalRequestString.append(NEWLINE);
- if (ServiceRequireUnsignedPayload(signingServiceName))
- {
- canonicalRequestString.append(UNSIGNED_PAYLOAD);
- }
- else
- {
- canonicalRequestString.append(EMPTY_STRING_SHA256);
- }
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString);
-
- //now compute sha256 on that request string
- auto hashResult = m_hash->Calculate(canonicalRequestString);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string");
- AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\"");
- return false;
- }
-
- auto sha256Digest = hashResult.GetResult();
- auto canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
-
- auto stringToSign = GenerateStringToSign(dateQueryValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
- auto finalSigningHash = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
- if (finalSigningHash.empty())
- {
- return false;
- }
-
- //add that the signature to the query string
- request.AddQueryStringParameter(X_AMZ_SIGNATURE, finalSigningHash);
-
- return true;
-}
-
-bool AWSAuthV4Signer::ServiceRequireUnsignedPayload(const Aws::String& serviceName) const
-{
- // S3 uses a magic string (instead of the empty string) for its body hash for presigned URLs as outlined here:
- // https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
- // this is true for PUT, POST, GET, DELETE and HEAD operations.
- // However, other services (for example RDS) implement the specification as outlined here:
- // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
- // which states that body-less requests should use the empty-string SHA256 hash.
- return "s3" == serviceName || "s3-object-lambda" == serviceName;
-}
-
-Aws::String AWSAuthV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign,
- const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
-{
- auto key = ComputeHash(credentials.GetAWSSecretKey(), simpleDate, region, serviceName);
- return GenerateSignature(stringToSign, key);
-}
-
-Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const
-{
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Final String to sign: " << stringToSign);
-
- Aws::StringStream ss;
-
- auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string");
- AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\"");
- return {};
- }
-
- //now we finally sign our request string with our hex encoded derived hash.
- auto finalSigningDigest = hashResult.GetResult();
-
- auto finalSigningHash = HashingUtils::HexEncode(finalSigningDigest);
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Final computed signing hash: " << finalSigningHash);
-
- return finalSigningHash;
-}
-
-Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) const
-{
- if (!request.GetContentBody())
- {
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty.");
- return EMPTY_STRING_SHA256;
- }
-
- //compute hash on payload if it exists.
- auto hashResult = m_hash->Calculate(*request.GetContentBody());
-
- if(request.GetContentBody())
- {
- request.GetContentBody()->clear();
- request.GetContentBody()->seekg(0);
- }
-
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body");
- return {};
- }
-
- auto sha256Digest = hashResult.GetResult();
-
- Aws::String payloadHash(HashingUtils::HexEncode(sha256Digest));
- AWS_LOGSTREAM_DEBUG(v4LogTag, "Calculated sha256 " << payloadHash << " for payload.");
- return payloadHash;
-}
-
-Aws::String AWSAuthV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate,
- const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const
-{
- //generate the actual string we will use in signing the final request.
- Aws::StringStream ss;
-
- ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/"
- << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash;
-
- return ss.str();
-}
-
-Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey,
- const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
-{
- Aws::String signingKey(SIGNING_KEY);
- signingKey.append(secretKey);
- auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()),
- ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length()));
-
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\"");
- return {};
- }
-
- auto kDate = hashResult.GetResult();
- hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) region string \"" << region << "\"");
- return {};
- }
-
- auto kRegion = hashResult.GetResult();
- hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\"");
- return {};
- }
-
- auto kService = hashResult.GetResult();
- hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to HMAC (SHA256) request string");
- AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << AWS4_REQUEST << "\"");
- return {};
- }
- return hashResult.GetResult();
-}
-
-AWSAuthEventStreamV4Signer::AWSAuthEventStreamV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>&
- credentialsProvider, const char* serviceName, const Aws::String& region) :
- m_serviceName(serviceName),
- m_region(region),
- m_credentialsProvider(credentialsProvider)
-{
-
- m_unsignedHeaders.emplace_back(X_AMZN_TRACE_ID);
- m_unsignedHeaders.emplace_back(USER_AGENT_HEADER);
-}
-
-bool AWSAuthEventStreamV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool /* signBody */) const
-{
- AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
-
- //don't sign anonymous requests
- if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
- {
- return true;
- }
-
- if (!credentials.GetSessionToken().empty())
- {
- request.SetAwsSessionToken(credentials.GetSessionToken());
- }
-
- request.SetHeaderValue(X_AMZ_CONTENT_SHA256, EVENT_STREAM_CONTENT_SHA256);
-
- //calculate date header to use in internal signature (this also goes into date header).
- DateTime now = GetSigningTimestamp();
- Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
- request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue);
-
- Aws::StringStream headersStream;
- Aws::StringStream signedHeadersStream;
-
- for (const auto& header : CanonicalizeHeaders(request.GetHeaders()))
- {
- if(ShouldSignHeader(header.first))
- {
- headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE;
- signedHeadersStream << header.first.c_str() << ";";
- }
- }
-
- Aws::String canonicalHeadersString = headersStream.str();
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Header String: " << canonicalHeadersString);
-
- //calculate signed headers parameter
- Aws::String signedHeadersValue = signedHeadersStream.str();
- //remove that last semi-colon
- if (!signedHeadersValue.empty())
- {
- signedHeadersValue.pop_back();
- }
-
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signed Headers value:" << signedHeadersValue);
-
- //generate generalized canonicalized request string.
- Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, true/* m_urlEscapePath */);
-
- //append v4 stuff to the canonical request string.
- canonicalRequestString.append(canonicalHeadersString);
- canonicalRequestString.append(NEWLINE);
- canonicalRequestString.append(signedHeadersValue);
- canonicalRequestString.append(NEWLINE);
- canonicalRequestString.append(EVENT_STREAM_CONTENT_SHA256);
-
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Request String: " << canonicalRequestString);
-
- //now compute sha256 on that request string
- auto hashResult = m_hash.Calculate(canonicalRequestString);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) request string");
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << canonicalRequestString << "\"");
- return false;
- }
-
- auto sha256Digest = hashResult.GetResult();
- Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
- Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR);
-
- Aws::String signingRegion = region ? region : m_region;
- Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
- Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
- auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
-
- Aws::StringStream ss;
- ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate
- << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST << ", " << SIGNED_HEADERS << EQ
- << signedHeadersValue << ", " << SIGNATURE << EQ << HashingUtils::HexEncode(finalSignature);
-
- auto awsAuthString = ss.str();
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signing request with: " << awsAuthString);
- request.SetAwsAuthorization(awsAuthString);
- request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
- request.SetSigningRegion(signingRegion);
- return true;
-}
-
-// this works regardless if the current machine is Big/Little Endian
-static void WriteBigEndian(Aws::String& str, uint64_t n)
-{
- int shift = 56;
- while(shift >= 0)
- {
- str.push_back((n >> shift) & 0xFF);
- shift -= 8;
- }
-}
-
-bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws::String& priorSignature) const
-{
- using Event::EventHeaderValue;
-
- Aws::StringStream stringToSign;
- stringToSign << EVENT_STREAM_PAYLOAD << NEWLINE;
- const DateTime now = GetSigningTimestamp();
- const auto simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR);
- stringToSign << now.ToGmtString(DateFormat::ISO_8601_BASIC) << NEWLINE
- << simpleDate << "/" << m_region << "/"
- << m_serviceName << "/aws4_request" << NEWLINE << priorSignature << NEWLINE;
-
-
- Aws::String nonSignatureHeaders;
- nonSignatureHeaders.push_back(char(sizeof(EVENTSTREAM_DATE_HEADER) - 1)); // length of the string
- nonSignatureHeaders += EVENTSTREAM_DATE_HEADER;
- nonSignatureHeaders.push_back(static_cast<char>(EventHeaderValue::EventHeaderType::TIMESTAMP)); // type of the value
- WriteBigEndian(nonSignatureHeaders, static_cast<uint64_t>(now.Millis())); // the value of the timestamp in big-endian
-
- auto hashOutcome = m_hash.Calculate(nonSignatureHeaders);
- if (!hashOutcome.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
- return false;
- }
-
- const auto nonSignatureHeadersHash = hashOutcome.GetResult();
- stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << NEWLINE;
-
- if (message.GetEventPayload().empty())
- {
- AWS_LOGSTREAM_WARN(v4StreamingLogTag, "Attempting to sign an empty message (no payload and no headers). "
- "It is unlikely that this is the intended behavior.");
- }
- else
- {
- // use a preallocatedStreamBuf to avoid making a copy.
- // The Hashing API requires either Aws::String or IStream as input.
- // TODO: the hashing API should be accept 'unsigned char*' as input.
- Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size());
- Aws::IOStream payload(&streamBuf);
- hashOutcome = m_hash.Calculate(payload);
-
- if (!hashOutcome.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
- return false;
- }
- const auto payloadHash = hashOutcome.GetResult();
- stringToSign << HashingUtils::HexEncode(payloadHash);
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash));
- }
-
- Utils::ByteBuffer finalSignatureDigest = GenerateSignature(m_credentialsProvider->GetAWSCredentials(), stringToSign.str(), simpleDate, m_region, m_serviceName);
- const auto finalSignature = HashingUtils::HexEncode(finalSignatureDigest);
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final computed signing hash: " << finalSignature);
- priorSignature = finalSignature;
-
- message.InsertEventHeader(EVENTSTREAM_DATE_HEADER, EventHeaderValue(now.Millis(), EventHeaderValue::EventHeaderType::TIMESTAMP));
- message.InsertEventHeader(EVENTSTREAM_SIGNATURE_HEADER, std::move(finalSignatureDigest));
-
- AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Event chunk final signature - " << finalSignature);
- return true;
-}
-
-bool AWSAuthEventStreamV4Signer::ShouldSignHeader(const Aws::String& header) const
-{
- return std::find(m_unsignedHeaders.cbegin(), m_unsignedHeaders.cend(), Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend();
-}
-
-Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign,
- const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
-{
- Utils::Threading::ReaderLockGuard guard(m_derivedKeyLock);
- const auto& secretKey = credentials.GetAWSSecretKey();
- if (secretKey != m_currentSecretKey || simpleDate != m_currentDateStr)
- {
- guard.UpgradeToWriterLock();
- // double-checked lock to prevent updating twice
- if (m_currentDateStr != simpleDate || m_currentSecretKey != secretKey)
- {
- m_currentSecretKey = secretKey;
- m_currentDateStr = simpleDate;
- m_derivedKey = ComputeHash(m_currentSecretKey, m_currentDateStr, region, serviceName);
- }
-
- }
- return GenerateSignature(stringToSign, m_derivedKey);
-}
-
-Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const
-{
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final String to sign: " << stringToSign);
-
- Aws::StringStream ss;
-
- auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to hmac (sha256) final string");
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The final string is: \"" << stringToSign << "\"");
- return {};
- }
-
- return hashResult.GetResult();
-}
-
-Aws::String AWSAuthEventStreamV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate,
- const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const
-{
- //generate the actual string we will use in signing the final request.
- Aws::StringStream ss;
-
- ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/"
- << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash;
-
- return ss.str();
-}
-
-Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::ComputeHash(const Aws::String& secretKey,
- const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
-{
- Aws::String signingKey(SIGNING_KEY);
- signingKey.append(secretKey);
- auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()),
- ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length()));
-
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\"");
- return {};
- }
-
- auto kDate = hashResult.GetResult();
- hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) region string \"" << region << "\"");
- return {};
- }
-
- auto kRegion = hashResult.GetResult();
- hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\"");
- return {};
- }
-
- auto kService = hashResult.GetResult();
- hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService);
- if (!hashResult.IsSuccess())
- {
- AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to HMAC (SHA256) request string");
- AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << AWS4_REQUEST << "\"");
- return {};
- }
- return hashResult.GetResult();
-}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp
index bf20ede35e1..084e4bca6e2 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp
@@ -48,7 +48,7 @@ static const char DEFAULT_CREDENTIALS_FILE[] = "credentials";
extern const char DEFAULT_CONFIG_FILE[] = "config";
-static const int EXPIRATION_GRACE_PERIOD = 5 * 1000;
+static const int AWS_CREDENTIAL_PROVIDER_EXPIRATION_GRACE_PERIOD = 5 * 1000;
void AWSCredentialsProvider::Reload()
{
@@ -183,9 +183,10 @@ AWSCredentials ProfileConfigFileAWSCredentialsProvider::GetAWSCredentials()
{
RefreshIfExpired();
ReaderLockGuard guard(m_reloadLock);
- auto credsFileProfileIter = m_credentialsFileLoader.GetProfiles().find(m_profileToUse);
+ const Aws::Map<Aws::String, Aws::Config::Profile>& profiles = m_credentialsFileLoader.GetProfiles();
+ auto credsFileProfileIter = profiles.find(m_profileToUse);
- if(credsFileProfileIter != m_credentialsFileLoader.GetProfiles().end())
+ if(credsFileProfileIter != profiles.end())
{
return credsFileProfileIter->second.GetCredentials();
}
@@ -239,37 +240,71 @@ AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials()
{
RefreshIfExpired();
ReaderLockGuard guard(m_reloadLock);
+ if (m_ec2MetadataConfigLoader)
+ {
+ const Aws::Map<Aws::String, Aws::Config::Profile> &profiles = m_ec2MetadataConfigLoader->GetProfiles();
+ auto profileIter = profiles.find(Aws::Config::INSTANCE_PROFILE_KEY);
+
+ if (profileIter != profiles.end()) {
+ return profileIter->second.GetCredentials();
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(INSTANCE_LOG_TAG, "EC2 Metadata config loader is a nullptr");
+ }
+
+ return AWSCredentials();
+}
+
+bool InstanceProfileCredentialsProvider::ExpiresSoon() const
+{
+ ReaderLockGuard guard(m_reloadLock);
auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY);
+ AWSCredentials credentials;
if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end())
{
- return profileIter->second.GetCredentials();
+ credentials = profileIter->second.GetCredentials();
}
- return AWSCredentials();
+ return ((credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < AWS_CREDENTIAL_PROVIDER_EXPIRATION_GRACE_PERIOD);
}
void InstanceProfileCredentialsProvider::Reload()
{
- AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to repull from EC2 Metadata Service.");
- m_ec2MetadataConfigLoader->Load();
- AWSCredentialsProvider::Reload();
+ AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Credentials have expired attempting to re-pull from EC2 Metadata Service.");
+ if (m_ec2MetadataConfigLoader) {
+ m_ec2MetadataConfigLoader->Load();
+ AWSCredentialsProvider::Reload();
+ } else {
+ AWS_LOGSTREAM_ERROR(INSTANCE_LOG_TAG, "EC2 Metadata config loader is a nullptr");
+ }
}
void InstanceProfileCredentialsProvider::RefreshIfExpired()
{
AWS_LOGSTREAM_DEBUG(INSTANCE_LOG_TAG, "Checking if latest credential pull has expired.");
ReaderLockGuard guard(m_reloadLock);
- if (!IsTimeToRefresh(m_loadFrequencyMs))
- {
- return;
- }
+ auto profileIter = m_ec2MetadataConfigLoader->GetProfiles().find(Aws::Config::INSTANCE_PROFILE_KEY);
+ AWSCredentials credentials;
- guard.UpgradeToWriterLock();
- if (!IsTimeToRefresh(m_loadFrequencyMs)) // double-checked lock to avoid refreshing twice
+ if(profileIter != m_ec2MetadataConfigLoader->GetProfiles().end())
{
- return;
+ credentials = profileIter->second.GetCredentials();
+
+ if (!credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon())
+ {
+ return;
+ }
+
+ guard.UpgradeToWriterLock();
+ if (!credentials.IsEmpty() && !IsTimeToRefresh(m_loadFrequencyMs) && !ExpiresSoon()) // double-checked lock to avoid refreshing twice
+ {
+ return;
+ }
}
+
Reload();
}
@@ -306,12 +341,17 @@ AWSCredentials TaskRoleCredentialsProvider::GetAWSCredentials()
bool TaskRoleCredentialsProvider::ExpiresSoon() const
{
- return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < EXPIRATION_GRACE_PERIOD);
+ return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < AWS_CREDENTIAL_PROVIDER_EXPIRATION_GRACE_PERIOD);
}
void TaskRoleCredentialsProvider::Reload()
{
- AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to repull from ECS IAM Service.");
+ AWS_LOGSTREAM_INFO(TASK_ROLE_LOG_TAG, "Credentials have expired or will expire, attempting to re-pull from ECS IAM Service.");
+ if (!m_ecsCredentialsClient)
+ {
+ AWS_LOGSTREAM_ERROR(INSTANCE_LOG_TAG, "ECS Credentials client is a nullptr");
+ return;
+ }
auto credentialsStr = m_ecsCredentialsClient->GetECSCredentials();
if (credentialsStr.empty()) return;
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp
index 8b019a16642..403bd380c46 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp
@@ -77,3 +77,9 @@ DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain() : AWSCr
AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added EC2 metadata service credentials provider to the provider chain.");
}
}
+
+DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain(const DefaultAWSCredentialsProviderChain& chain) {
+ for (const auto& provider: chain.GetProviders()) {
+ AddProvider(provider);
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/SSOCredentialsProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/SSOCredentialsProvider.cpp
index e8f780762ea..9576e9d9999 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/SSOCredentialsProvider.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/SSOCredentialsProvider.cpp
@@ -33,7 +33,8 @@ SSOCredentialsProvider::SSOCredentialsProvider() : m_profileToUse(GetConfigProfi
AWS_LOGSTREAM_INFO(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Setting sso credentials provider to read config from " << m_profileToUse);
}
-SSOCredentialsProvider::SSOCredentialsProvider(const Aws::String& profile) : m_profileToUse(profile)
+SSOCredentialsProvider::SSOCredentialsProvider(const Aws::String& profile) : m_profileToUse(profile),
+ m_bearerTokenProvider(profile)
{
AWS_LOGSTREAM_INFO(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Setting sso credentials provider to read config from " << m_profileToUse);
}
@@ -48,15 +49,24 @@ AWSCredentials SSOCredentialsProvider::GetAWSCredentials()
void SSOCredentialsProvider::Reload()
{
auto profile = Aws::Config::GetCachedConfigProfile(m_profileToUse);
-
- Aws::String hashedStartUrl = Aws::Utils::HashingUtils::HexEncode(Aws::Utils::HashingUtils::CalculateSHA1(profile.GetSsoStartUrl()));
- auto profileDirectory = ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory();
- Aws::StringStream ssToken;
- ssToken << profileDirectory;
- ssToken << PATH_DELIM << "sso" << PATH_DELIM << "cache" << PATH_DELIM << hashedStartUrl << ".json";
- auto ssoTokenPath = ssToken.str();
- AWS_LOGSTREAM_DEBUG(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Loading token from: " << ssoTokenPath)
- Aws::String accessToken = LoadAccessTokenFile(ssoTokenPath);
+ const auto accessToken = [&]() -> Aws::String {
+ // If we have an SSO Session set, use the refreshed token.
+ if (profile.IsSsoSessionSet()) {
+ m_ssoRegion = profile.GetSsoSession().GetSsoRegion();
+ auto token = m_bearerTokenProvider.GetAWSBearerToken();
+ m_expiresAt = token.GetExpiration();
+ return token.GetToken();
+ }
+ Aws::String hashedStartUrl = Aws::Utils::HashingUtils::HexEncode(Aws::Utils::HashingUtils::CalculateSHA1(profile.GetSsoStartUrl()));
+ auto profileDirectory = ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory();
+ Aws::StringStream ssToken;
+ ssToken << profileDirectory;
+ ssToken << PATH_DELIM << "sso" << PATH_DELIM << "cache" << PATH_DELIM << hashedStartUrl << ".json";
+ auto ssoTokenPath = ssToken.str();
+ AWS_LOGSTREAM_DEBUG(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Loading token from: " << ssoTokenPath)
+ m_ssoRegion = profile.GetSsoRegion();
+ return LoadAccessTokenFile(ssoTokenPath);
+ }();
if (accessToken.empty()) {
AWS_LOGSTREAM_TRACE(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Access token for SSO not available");
return;
@@ -72,7 +82,7 @@ void SSOCredentialsProvider::Reload()
Aws::Client::ClientConfiguration config;
config.scheme = Aws::Http::Scheme::HTTPS;
- config.region = profile.GetSsoRegion();
+ config.region = m_ssoRegion;
AWS_LOGSTREAM_DEBUG(SSO_CREDENTIALS_PROVIDER_LOG_TAG, "Passing config to client for region: " << m_ssoRegion);
Aws::Vector<Aws::String> retryableErrors;
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp
index 3f48c9e0c7d..b861e6132b1 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp
@@ -30,6 +30,8 @@ using Aws::Utils::Threading::ReaderLockGuard;
using Aws::Utils::Threading::WriterLockGuard;
static const char STS_ASSUME_ROLE_WEB_IDENTITY_LOG_TAG[] = "STSAssumeRoleWithWebIdentityCredentialsProvider";
+static const int STS_CREDENTIAL_PROVIDER_EXPIRATION_GRACE_PERIOD = 5 * 1000;
+
STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentialsProvider() :
m_initialized(false)
{
@@ -145,16 +147,21 @@ void STSAssumeRoleWebIdentityCredentialsProvider::Reload()
m_credentials = result.creds;
}
+bool STSAssumeRoleWebIdentityCredentialsProvider::ExpiresSoon() const
+{
+ return ((m_credentials.GetExpiration() - Aws::Utils::DateTime::Now()).count() < STS_CREDENTIAL_PROVIDER_EXPIRATION_GRACE_PERIOD);
+}
+
void STSAssumeRoleWebIdentityCredentialsProvider::RefreshIfExpired()
{
ReaderLockGuard guard(m_reloadLock);
- if (!m_credentials.IsExpiredOrEmpty())
+ if (!m_credentials.IsEmpty() && !ExpiresSoon())
{
return;
}
guard.UpgradeToWriterLock();
- if (!m_credentials.IsExpiredOrEmpty()) // double-checked lock to avoid refreshing twice
+ if (!m_credentials.IsExpiredOrEmpty() && !ExpiresSoon()) // double-checked lock to avoid refreshing twice
{
return;
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/DefaultBearerTokenProviderChain.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/DefaultBearerTokenProviderChain.cpp
new file mode 100644
index 00000000000..16b301cd678
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/DefaultBearerTokenProviderChain.cpp
@@ -0,0 +1,35 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/bearer-token-provider/DefaultBearerTokenProviderChain.h>
+#include <aws/core/auth/AWSBearerToken.h>
+#include <aws/core/auth/bearer-token-provider/SSOBearerTokenProvider.h>
+#include <aws/core/utils/logging/LogMacros.h>
+
+
+static const char SSO_DEFAULT_BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG[] = "SSOBearerTokenProvider";
+
+Aws::Auth::AWSBearerToken Aws::Auth::DefaultBearerTokenProviderChain::GetAWSBearerToken()
+{
+ for (auto&& bearerTokenProvider : m_providerChain)
+ {
+ if(!bearerTokenProvider) {
+ AWS_LOGSTREAM_FATAL(SSO_DEFAULT_BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG,
+ "Unexpected nullptr in DefaultBearerTokenProviderChain::m_providerChain");
+ break;
+ }
+ AWSBearerToken bearerToken = bearerTokenProvider->GetAWSBearerToken();
+ if(!bearerToken.IsExpiredOrEmpty())
+ {
+ return bearerToken;
+ }
+ }
+ return AWSBearerToken("", Aws::Utils::DateTime(0.0));
+}
+
+Aws::Auth::DefaultBearerTokenProviderChain::DefaultBearerTokenProviderChain()
+{
+ AddProvider(Aws::MakeShared<Aws::Auth::SSOBearerTokenProvider>(SSO_DEFAULT_BEARER_TOKEN_PROVIDER_CHAIN_LOG_TAG));
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/SSOBearerTokenProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/SSOBearerTokenProvider.cpp
new file mode 100644
index 00000000000..b55131e340d
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/bearer-token-provider/SSOBearerTokenProvider.cpp
@@ -0,0 +1,244 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/auth/bearer-token-provider/SSOBearerTokenProvider.h>
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/config/AWSProfileConfigLoader.h>
+#include <aws/core/internal/AWSHttpResourceClient.h>
+#include <aws/core/platform/Environment.h>
+#include <aws/core/platform/FileSystem.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/FileSystemUtils.h>
+#include <aws/core/client/SpecifiedRetryableErrorsRetryStrategy.h>
+#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/json/JsonSerializer.h>
+
+using namespace Aws::Auth;
+
+using Aws::Utils::Threading::ReaderLockGuard;
+
+
+static const char SSO_BEARER_TOKEN_PROVIDER_LOG_TAG[] = "SSOBearerTokenProvider";
+static const char SSO_GRANT_TYPE[] = "refresh_token";
+
+const size_t SSOBearerTokenProvider::REFRESH_WINDOW_BEFORE_EXPIRATION_S = 600;
+const size_t SSOBearerTokenProvider::REFRESH_ATTEMPT_INTERVAL_S = 30;
+
+SSOBearerTokenProvider::SSOBearerTokenProvider()
+ : m_profileToUse(Aws::Auth::GetConfigProfileName()),
+ m_lastUpdateAttempt((int64_t) 0)
+{
+ AWS_LOGSTREAM_INFO(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Setting sso bearerToken provider to read config from " << m_profileToUse);
+}
+
+SSOBearerTokenProvider::SSOBearerTokenProvider(const Aws::String& awsProfile)
+ : m_profileToUse(awsProfile),
+ m_lastUpdateAttempt((int64_t) 0)
+{
+ AWS_LOGSTREAM_INFO(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Setting sso bearerToken provider to read config from " << m_profileToUse);
+}
+
+AWSBearerToken SSOBearerTokenProvider::GetAWSBearerToken()
+{
+ Aws::Utils::Threading::ReaderLockGuard guard(m_reloadLock);
+ if(m_token.IsEmpty())
+ {
+ Reload();
+ }
+ if(!m_token.IsEmpty())
+ {
+ const Aws::Utils::DateTime now = Aws::Utils::DateTime::Now();
+ if (now >= m_token.GetExpiration() - std::chrono::seconds(REFRESH_WINDOW_BEFORE_EXPIRATION_S) &&
+ m_lastUpdateAttempt + std::chrono::seconds(REFRESH_ATTEMPT_INTERVAL_S) < now)
+ {
+ guard.UpgradeToWriterLock();
+ RefreshFromSso();
+ }
+ }
+
+ if(m_token.IsExpiredOrEmpty())
+ {
+ /* If a loaded token has expired and has insufficient metadata to perform a refresh the SSO token
+ provider must raise an exception that the token has expired and cannot be refreshed.
+ Error logging and returning an empty object instead because of disabled exceptions and poor legacy API design. */
+ AWS_LOGSTREAM_ERROR(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "SSOBearerTokenProvider is unable to provide a token");
+ return Aws::Auth::AWSBearerToken("", Aws::Utils::DateTime(0.0));
+ }
+ return m_token;
+}
+
+void SSOBearerTokenProvider::Reload()
+{
+ CachedSsoToken cachedSsoToken = LoadAccessTokenFile();
+ if(cachedSsoToken.accessToken.empty()) {
+ AWS_LOGSTREAM_TRACE(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Access token for SSO not available");
+ return;
+ }
+ const Aws::Utils::DateTime now = Aws::Utils::DateTime::Now();
+ if(cachedSsoToken.expiresAt < now) {
+ AWS_LOGSTREAM_ERROR(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Cached Token is already expired at " << cachedSsoToken.expiresAt.ToGmtString(Aws::Utils::DateFormat::ISO_8601));
+ return;
+ }
+
+ m_token.SetToken(cachedSsoToken.accessToken);
+ m_token.SetExpiration(cachedSsoToken.expiresAt);
+}
+
+void SSOBearerTokenProvider::RefreshFromSso()
+{
+ CachedSsoToken cachedSsoToken = LoadAccessTokenFile();
+
+ if(!m_client)
+ {
+ Aws::Client::ClientConfiguration config;
+ config.scheme = Aws::Http::Scheme::HTTPS;
+ /* The SSO token provider must not resolve if any SSO configuration values are present directly on the profile
+ * instead of an `sso-session` section. The SSO token provider must ignore these configuration values if these
+ * values are present directly on the profile instead of an `sso-session` section. */
+ // config.region = m_profile.GetSsoRegion(); // <- intentionally not used per comment above
+ config.region = cachedSsoToken.region;
+ m_client = Aws::MakeUnique<Aws::Internal::SSOCredentialsClient>(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, config);
+ }
+
+ Aws::Internal::SSOCredentialsClient::SSOCreateTokenRequest ssoCreateTokenRequest;
+ ssoCreateTokenRequest.clientId = cachedSsoToken.clientId;
+ ssoCreateTokenRequest.clientSecret = cachedSsoToken.clientSecret;
+ ssoCreateTokenRequest.grantType = SSO_GRANT_TYPE;
+ ssoCreateTokenRequest.refreshToken = cachedSsoToken.refreshToken;
+
+ if(!m_client) {
+ AWS_LOGSTREAM_FATAL(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Unexpected nullptr in SSOBearerTokenProvider::m_client");
+ return;
+ }
+ Aws::Internal::SSOCredentialsClient::SSOCreateTokenResult result = m_client->CreateToken(ssoCreateTokenRequest);
+ if(!result.accessToken.empty())
+ {
+ cachedSsoToken.accessToken = result.accessToken;
+ cachedSsoToken.expiresAt = Aws::Utils::DateTime::Now() + std::chrono::seconds(result.expiresIn);
+ if(!result.refreshToken.empty()) {
+ cachedSsoToken.refreshToken = result.refreshToken;
+ }
+ if(!result.clientId.empty()) {
+ cachedSsoToken.clientId = result.clientId;
+ }
+ }
+
+ if(WriteAccessTokenFile(cachedSsoToken))
+ {
+ m_token.SetToken(cachedSsoToken.accessToken);
+ m_token.SetExpiration(cachedSsoToken.expiresAt);
+ }
+
+}
+
+SSOBearerTokenProvider::CachedSsoToken SSOBearerTokenProvider::LoadAccessTokenFile() const
+{
+ SSOBearerTokenProvider::CachedSsoToken retValue;
+
+ const Aws::Config::Profile& profile = Aws::Config::GetCachedConfigProfile(m_profileToUse);
+ if(!profile.IsSsoSessionSet()) {
+ AWS_LOGSTREAM_ERROR(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "SSOBearerTokenProvider set to use a profile " << m_profileToUse << " without a sso_session. Unable to load cached token.");
+ return retValue;
+ }
+
+ Aws::String hashedStartUrl = Aws::Utils::HashingUtils::HexEncode(Aws::Utils::HashingUtils::CalculateSHA1(profile.GetSsoSession().GetName()));
+ Aws::String profileDirectory = ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory();
+ Aws::StringStream ssToken;
+ ssToken << profileDirectory;
+ ssToken << Aws::FileSystem::PATH_DELIM << "sso" << Aws::FileSystem::PATH_DELIM << "cache" << Aws::FileSystem::PATH_DELIM << hashedStartUrl << ".json";
+ auto ssoAccessTokenPath = ssToken.str();
+ AWS_LOGSTREAM_DEBUG(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Preparing to load token from: " << ssoAccessTokenPath);
+
+ Aws::IFStream inputFile(ssoAccessTokenPath.c_str());
+ if(inputFile)
+ {
+ AWS_LOGSTREAM_DEBUG(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Reading content from token file: " << ssoAccessTokenPath);
+
+ Aws::Utils::Json::JsonValue tokenDoc(inputFile);
+ if (!tokenDoc.WasParseSuccessful())
+ {
+ AWS_LOGSTREAM_ERROR(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Failed to parse token file: " << ssoAccessTokenPath);
+ return retValue;
+ }
+ Utils::Json::JsonView tokenView(tokenDoc);
+
+ retValue.accessToken = tokenView.GetString("accessToken");
+ retValue.expiresAt = Aws::Utils::DateTime(tokenView.GetString("expiresAt"), Aws::Utils::DateFormat::ISO_8601);
+ retValue.refreshToken = tokenView.GetString("refreshToken");
+ retValue.clientId = tokenView.GetString("clientId");
+ retValue.clientSecret = tokenView.GetString("clientSecret");
+ retValue.registrationExpiresAt = Aws::Utils::DateTime(tokenView.GetString("registrationExpiresAt"), Aws::Utils::DateFormat::ISO_8601);
+ retValue.region = tokenView.GetString("region");
+ retValue.startUrl = tokenView.GetString("startUrl");
+
+ return retValue;
+ }
+ else
+ {
+ AWS_LOGSTREAM_INFO(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Unable to open token file on path: " << ssoAccessTokenPath);
+ return retValue;
+ }
+}
+
+bool SSOBearerTokenProvider::WriteAccessTokenFile(const CachedSsoToken& token) const
+{
+ const Aws::Config::Profile& profile = Aws::Config::GetCachedConfigProfile(m_profileToUse);
+ if(!profile.IsSsoSessionSet()) {
+ AWS_LOGSTREAM_ERROR(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "SSOBearerTokenProvider set to use a profile "
+ << m_profileToUse << " without a sso_session. Unable to write a cached token.");
+ return false;
+ }
+
+ Aws::String hashedStartUrl = Aws::Utils::HashingUtils::HexEncode(Aws::Utils::HashingUtils::CalculateSHA1(profile.GetSsoSession().GetName()));
+ Aws::String profileDirectory = ProfileConfigFileAWSCredentialsProvider::GetProfileDirectory();
+ Aws::StringStream ssToken;
+ ssToken << profileDirectory;
+ ssToken << Aws::FileSystem::PATH_DELIM << "sso" << Aws::FileSystem::PATH_DELIM << "cache" << Aws::FileSystem::PATH_DELIM << hashedStartUrl << ".json";
+ auto ssoAccessTokenPath = ssToken.str();
+ AWS_LOGSTREAM_DEBUG(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Preparing to write token to: " << ssoAccessTokenPath);
+
+ Aws::OFStream outputFileStream(ssoAccessTokenPath.c_str(), std::ios_base::out | std::ios_base::trunc);
+ if(outputFileStream && outputFileStream.good())
+ {
+ AWS_LOGSTREAM_DEBUG(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Writing content to token file: " << ssoAccessTokenPath);
+
+ Aws::Utils::Json::JsonValue cachedTokenDoc;
+ if(!token.accessToken.empty()) {
+ cachedTokenDoc.WithString("accessToken", token.accessToken);
+ }
+ if(token.expiresAt != 0.0) {
+ cachedTokenDoc.WithString("expiresAt", token.expiresAt.ToGmtString(Aws::Utils::DateFormat::ISO_8601));
+ }
+ if(!token.refreshToken.empty()) {
+ cachedTokenDoc.WithString("refreshToken", token.refreshToken);
+ }
+ if(!token.clientId.empty()) {
+ cachedTokenDoc.WithString("clientId", token.clientId);
+ }
+ if(!token.clientSecret.empty()) {
+ cachedTokenDoc.WithString("clientSecret", token.clientSecret);
+ }
+ if(token.registrationExpiresAt != 0.0) {
+ cachedTokenDoc.WithString("registrationExpiresAt", token.registrationExpiresAt.ToGmtString(Aws::Utils::DateFormat::ISO_8601));
+ }
+ if(!token.region.empty()) {
+ cachedTokenDoc.WithString("region", token.region);
+ }
+ if(!token.startUrl.empty()) {
+ cachedTokenDoc.WithString("startUrl", token.startUrl);
+ }
+
+ const Aws::String& resultingJsonStr = cachedTokenDoc.View().WriteReadable();;
+ outputFileStream << resultingJsonStr;
+
+ return outputFileStream.good();
+ }
+ else
+ {
+ AWS_LOGSTREAM_INFO(SSO_BEARER_TOKEN_PROVIDER_LOG_TAG, "Unable to open token file on path for writing: " << ssoAccessTokenPath);
+ return false;
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/BearerTokenAuthSignerProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/BearerTokenAuthSignerProvider.cpp
new file mode 100644
index 00000000000..9bb9c5edae7
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/BearerTokenAuthSignerProvider.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer-provider/BearerTokenAuthSignerProvider.h>
+
+#include <aws/core/auth/signer/AWSNullSigner.h>
+
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/utils/memory/stl/AWSAllocator.h>
+
+const char BEARER_TOKEN_AUTH_SIGNER_PROVIDER_ALLOC_TAG[] = "BearerTokenAuthSignerProvider";
+
+using namespace Aws::Auth;
+
+BearerTokenAuthSignerProvider::BearerTokenAuthSignerProvider(const std::shared_ptr<Aws::Auth::AWSBearerTokenProviderBase> bearerTokenProvider)
+{
+ m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSAuthBearerSigner>(BEARER_TOKEN_AUTH_SIGNER_PROVIDER_ALLOC_TAG, bearerTokenProvider));
+ m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSNullSigner>(BEARER_TOKEN_AUTH_SIGNER_PROVIDER_ALLOC_TAG));
+}
+
+std::shared_ptr<Aws::Client::AWSAuthSigner> BearerTokenAuthSignerProvider::GetSigner(const Aws::String& signerName) const
+{
+ for(const auto& signer : m_signers)
+ {
+ if(!signer) {
+ AWS_LOGSTREAM_FATAL(BEARER_TOKEN_AUTH_SIGNER_PROVIDER_ALLOC_TAG, "Unexpected nullptr in BearerTokenAuthSignerProvider::m_signers");
+ break;
+ }
+ if(signer->GetName() == signerName)
+ {
+ return signer;
+ }
+ }
+ AWS_LOGSTREAM_ERROR(BEARER_TOKEN_AUTH_SIGNER_PROVIDER_ALLOC_TAG, "Request's signer: '" << signerName << "' is not found in the signer's map.");
+ assert(false);
+ return nullptr;
+}
+
+void BearerTokenAuthSignerProvider::AddSigner(std::shared_ptr<Aws::Client::AWSAuthSigner>& signer)
+{
+ assert(signer);
+ m_signers.emplace_back(signer);
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/DefaultAuthSignerProvider.cpp
index 31fd6c006ba..fb7e0cfa406 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSignerProvider.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer-provider/DefaultAuthSignerProvider.cpp
@@ -2,10 +2,14 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
+
+#include <aws/core/auth/signer-provider/DefaultAuthSignerProvider.h>
+
+#include <aws/core/auth/signer/AWSAuthEventStreamV4Signer.h>
+#include <aws/core/auth/signer/AWSNullSigner.h>
+
#include <aws/core/utils/logging/LogMacros.h>
-#include <aws/core/auth/AWSAuthSignerProvider.h>
-#include <aws/core/auth/AWSAuthSigner.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/utils/memory/stl/AWSAllocator.h>
@@ -14,9 +18,10 @@ const char CLASS_TAG[] = "AuthSignerProvider";
using namespace Aws::Auth;
DefaultAuthSignerProvider::DefaultAuthSignerProvider(const std::shared_ptr<AWSCredentialsProvider>& credentialsProvider,
- const Aws::String& serviceName, const Aws::String& region)
+ const Aws::String& serviceName, const Aws::String& region, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy signingPolicy, bool urlEscapePath)
{
- m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSAuthV4Signer>(CLASS_TAG, credentialsProvider, serviceName.c_str(), region));
+ m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSAuthV4Signer>(CLASS_TAG, credentialsProvider, serviceName.c_str(), region, signingPolicy, urlEscapePath, AWSSigningAlgorithm::SIGV4));
+ m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSAuthV4Signer>(CLASS_TAG, credentialsProvider, serviceName.c_str(), region, signingPolicy, urlEscapePath, AWSSigningAlgorithm::ASYMMETRIC_SIGV4));
m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSAuthEventStreamV4Signer>(CLASS_TAG, credentialsProvider, serviceName.c_str(), region));
m_signers.emplace_back(Aws::MakeShared<Aws::Client::AWSNullSigner>(CLASS_TAG));
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthBearerSigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthBearerSigner.cpp
new file mode 100644
index 00000000000..ff14c8a3712
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthBearerSigner.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSAuthBearerSigner.h>
+#include <aws/core/auth/bearer-token-provider/AWSBearerTokenProviderBase.h>
+
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/http/HttpRequest.h>
+
+namespace Aws
+{
+ namespace Auth
+ {
+ const char BEARER_SIGNER[] = "Bearer";
+ }
+
+ namespace Client
+ {
+ static const char LOGGING_TAG[] = "AWSAuthBearerSigner";
+ static const char AUTHORIZATION_HEADER[] = "authorization";
+
+ bool AWSAuthBearerSigner::SignRequest(Aws::Http::HttpRequest& ioRequest) const
+ {
+ if(Aws::Http::Scheme::HTTPS != ioRequest.GetUri().GetScheme())
+ {
+ // Clients MUST always use TLS (https) or equivalent transport security
+ // when making requests with bearer tokens.
+ // https://datatracker.ietf.org/doc/html/rfc6750
+ AWS_LOGSTREAM_ERROR(LOGGING_TAG, "HTTPS scheme must be used with a bearer token authorization");
+ return false;
+ }
+ if(!m_bearerTokenProvider)
+ {
+ AWS_LOGSTREAM_FATAL(LOGGING_TAG, "Unexpected nullptr AWSAuthBearerSigner::m_bearerTokenProvider");
+ return false;
+ }
+ const Aws::Auth::AWSBearerToken& token = m_bearerTokenProvider->GetAWSBearerToken();
+ if(token.IsExpiredOrEmpty())
+ {
+ AWS_LOGSTREAM_ERROR(LOGGING_TAG, "Invalid bearer token to use: expired or empty");
+ return false;
+ }
+
+ ioRequest.SetHeaderValue(AUTHORIZATION_HEADER, "Bearer " + token.GetToken());
+ return true;
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp
new file mode 100644
index 00000000000..195e83a751a
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp
@@ -0,0 +1,320 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSAuthEventStreamV4Signer.h>
+#include <aws/core/auth/signer/AWSAuthSignerCommon.h>
+#include <aws/core/auth/signer/AWSAuthSignerHelper.h>
+
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/http/HttpRequest.h>
+#include <aws/core/utils/DateTime.h>
+#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+#include <aws/core/utils/crypto/Sha256HMAC.h>
+#include <aws/core/utils/stream/PreallocatedStreamBuf.h>
+#include <aws/core/utils/event/EventMessage.h>
+#include <aws/core/utils/event/EventHeader.h>
+
+#include <aws/crt/auth/Credentials.h>
+#include <aws/crt/http/HttpRequestResponse.h>
+
+#include <iomanip>
+#include <cstring>
+
+using namespace Aws;
+using namespace Aws::Client;
+using namespace Aws::Auth;
+using namespace Aws::Http;
+using namespace Aws::Utils;
+using namespace Aws::Utils::Logging;
+
+static const char* EVENT_STREAM_CONTENT_SHA256 = "STREAMING-AWS4-HMAC-SHA256-EVENTS";
+static const char* EVENT_STREAM_PAYLOAD = "AWS4-HMAC-SHA256-PAYLOAD";
+static const char* v4StreamingLogTag = "AWSAuthEventStreamV4Signer";
+
+namespace Aws
+{
+ namespace Auth
+ {
+ const char EVENTSTREAM_SIGV4_SIGNER[] = "EventStreamSignatureV4";
+ const char EVENTSTREAM_SIGNATURE_HEADER[] = ":chunk-signature";
+ const char EVENTSTREAM_DATE_HEADER[] = ":date";
+ }
+}
+
+AWSAuthEventStreamV4Signer::AWSAuthEventStreamV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>&
+ credentialsProvider, const char* serviceName, const Aws::String& region) :
+ m_serviceName(serviceName),
+ m_region(region),
+ m_credentialsProvider(credentialsProvider)
+{
+
+ m_unsignedHeaders.emplace_back(Aws::Auth::AWSAuthHelper::X_AMZN_TRACE_ID);
+ m_unsignedHeaders.emplace_back(USER_AGENT_HEADER);
+}
+
+bool AWSAuthEventStreamV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool /* signBody */) const
+{
+ AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
+
+ //don't sign anonymous requests
+ if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
+ {
+ return true;
+ }
+
+ if (!credentials.GetSessionToken().empty())
+ {
+ request.SetAwsSessionToken(credentials.GetSessionToken());
+ }
+
+ request.SetHeaderValue(Aws::Auth::AWSAuthHelper::X_AMZ_CONTENT_SHA256, EVENT_STREAM_CONTENT_SHA256);
+
+ //calculate date header to use in internal signature (this also goes into date header).
+ DateTime now = GetSigningTimestamp();
+ Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
+ request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue);
+
+ Aws::StringStream headersStream;
+ Aws::StringStream signedHeadersStream;
+
+ for (const auto& header : Aws::Auth::AWSAuthHelper::CanonicalizeHeaders(request.GetHeaders()))
+ {
+ if(ShouldSignHeader(header.first))
+ {
+ headersStream << header.first.c_str() << ":" << header.second.c_str() << Aws::Auth::AWSAuthHelper::NEWLINE;
+ signedHeadersStream << header.first.c_str() << ";";
+ }
+ }
+
+ Aws::String canonicalHeadersString = headersStream.str();
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Header String: " << canonicalHeadersString);
+
+ //calculate signed headers parameter
+ Aws::String signedHeadersValue = signedHeadersStream.str();
+ //remove that last semi-colon
+ if (!signedHeadersValue.empty())
+ {
+ signedHeadersValue.pop_back();
+ }
+
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signed Headers value:" << signedHeadersValue);
+
+ //generate generalized canonicalized request string.
+ Aws::String canonicalRequestString = Aws::Auth::AWSAuthHelper::CanonicalizeRequestSigningString(request, true/* m_urlEscapePath */);
+
+ //append v4 stuff to the canonical request string.
+ canonicalRequestString.append(canonicalHeadersString);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ canonicalRequestString.append(signedHeadersValue);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ canonicalRequestString.append(EVENT_STREAM_CONTENT_SHA256);
+
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Request String: " << canonicalRequestString);
+
+ //now compute sha256 on that request string
+ auto hashResult = m_hash.Calculate(canonicalRequestString);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) request string");
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << canonicalRequestString << "\"");
+ return false;
+ }
+
+ auto sha256Digest = hashResult.GetResult();
+ Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
+ Aws::String simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR);
+
+ Aws::String signingRegion = region ? region : m_region;
+ Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
+ Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
+ auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
+
+ Aws::StringStream ss;
+ ss << Aws::Auth::AWSAuthHelper::AWS_HMAC_SHA256 << " " << Aws::Auth::AWSAuthHelper::CREDENTIAL << Aws::Auth::AWSAuthHelper::EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate
+ << "/" << signingRegion << "/" << signingServiceName << "/" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << ", " << Aws::Auth::AWSAuthHelper::SIGNED_HEADERS << Aws::Auth::AWSAuthHelper::EQ
+ << signedHeadersValue << ", " << SIGNATURE << Aws::Auth::AWSAuthHelper::EQ << HashingUtils::HexEncode(finalSignature);
+
+ auto awsAuthString = ss.str();
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signing request with: " << awsAuthString);
+ request.SetAwsAuthorization(awsAuthString);
+ request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
+ request.SetSigningRegion(signingRegion);
+ return true;
+}
+
+// this works regardless if the current machine is Big/Little Endian
+static void WriteBigEndian(Aws::String& str, uint64_t n)
+{
+ int shift = 56;
+ while(shift >= 0)
+ {
+ str.push_back((n >> shift) & 0xFF);
+ shift -= 8;
+ }
+}
+
+bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws::String& priorSignature) const
+{
+ using Event::EventHeaderValue;
+
+ Aws::StringStream stringToSign;
+ stringToSign << EVENT_STREAM_PAYLOAD << Aws::Auth::AWSAuthHelper::NEWLINE;
+ const DateTime now = GetSigningTimestamp();
+ const auto simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR);
+ stringToSign << now.ToGmtString(DateFormat::ISO_8601_BASIC) << Aws::Auth::AWSAuthHelper::NEWLINE
+ << simpleDate << "/" << m_region << "/"
+ << m_serviceName << "/aws4_request" << Aws::Auth::AWSAuthHelper::NEWLINE << priorSignature << Aws::Auth::AWSAuthHelper::NEWLINE;
+
+
+ Aws::String nonSignatureHeaders;
+ nonSignatureHeaders.push_back(char(sizeof(EVENTSTREAM_DATE_HEADER) - 1)); // length of the string
+ nonSignatureHeaders += EVENTSTREAM_DATE_HEADER;
+ nonSignatureHeaders.push_back(static_cast<char>(EventHeaderValue::EventHeaderType::TIMESTAMP)); // type of the value
+ WriteBigEndian(nonSignatureHeaders, static_cast<uint64_t>(now.Millis())); // the value of the timestamp in big-endian
+
+ auto hashOutcome = m_hash.Calculate(nonSignatureHeaders);
+ if (!hashOutcome.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
+ return false;
+ }
+
+ const auto nonSignatureHeadersHash = hashOutcome.GetResult();
+ stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << Aws::Auth::AWSAuthHelper::NEWLINE;
+
+ if (message.GetEventPayload().empty())
+ {
+ AWS_LOGSTREAM_WARN(v4StreamingLogTag, "Attempting to sign an empty message (no payload and no headers). "
+ "It is unlikely that this is the intended behavior.");
+ }
+ else
+ {
+ // use a preallocatedStreamBuf to avoid making a copy.
+ // The Hashing API requires either Aws::String or IStream as input.
+ // TODO: the hashing API should be accept 'unsigned char*' as input.
+ Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size());
+ Aws::IOStream payload(&streamBuf);
+ hashOutcome = m_hash.Calculate(payload);
+
+ if (!hashOutcome.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
+ return false;
+ }
+ const auto payloadHash = hashOutcome.GetResult();
+ stringToSign << HashingUtils::HexEncode(payloadHash);
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash));
+ }
+
+ Aws::Utils::ByteBuffer finalSignatureDigest = GenerateSignature(m_credentialsProvider->GetAWSCredentials(), stringToSign.str(), simpleDate, m_region, m_serviceName);
+ const auto finalSignature = HashingUtils::HexEncode(finalSignatureDigest);
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final computed signing hash: " << finalSignature);
+ priorSignature = finalSignature;
+
+ message.InsertEventHeader(EVENTSTREAM_DATE_HEADER, EventHeaderValue(now.Millis(), EventHeaderValue::EventHeaderType::TIMESTAMP));
+ message.InsertEventHeader(EVENTSTREAM_SIGNATURE_HEADER, std::move(finalSignatureDigest));
+
+ AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Event chunk final signature - " << finalSignature);
+ return true;
+}
+
+bool AWSAuthEventStreamV4Signer::ShouldSignHeader(const Aws::String& header) const
+{
+ return std::find(m_unsignedHeaders.cbegin(), m_unsignedHeaders.cend(), Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend();
+}
+
+Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign,
+ const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
+{
+ Utils::Threading::ReaderLockGuard guard(m_derivedKeyLock);
+ const auto& secretKey = credentials.GetAWSSecretKey();
+ if (secretKey != m_currentSecretKey || simpleDate != m_currentDateStr)
+ {
+ guard.UpgradeToWriterLock();
+ // double-checked lock to prevent updating twice
+ if (m_currentDateStr != simpleDate || m_currentSecretKey != secretKey)
+ {
+ m_currentSecretKey = secretKey;
+ m_currentDateStr = simpleDate;
+ m_derivedKey = ComputeHash(m_currentSecretKey, m_currentDateStr, region, serviceName);
+ }
+
+ }
+ return GenerateSignature(stringToSign, m_derivedKey);
+}
+
+Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const
+{
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final String to sign: " << stringToSign);
+
+ Aws::StringStream ss;
+
+ auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to hmac (sha256) final string");
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The final string is: \"" << stringToSign << "\"");
+ return {};
+ }
+
+ return hashResult.GetResult();
+}
+
+Aws::String AWSAuthEventStreamV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate,
+ const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const
+{
+ //generate the actual string we will use in signing the final request.
+ Aws::StringStream ss;
+
+ ss << Aws::Auth::AWSAuthHelper::AWS_HMAC_SHA256 << Aws::Auth::AWSAuthHelper::NEWLINE << dateValue << Aws::Auth::AWSAuthHelper::NEWLINE << simpleDate << "/" << region << "/"
+ << serviceName << "/" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << Aws::Auth::AWSAuthHelper::NEWLINE << canonicalRequestHash;
+
+ return ss.str();
+}
+
+Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::ComputeHash(const Aws::String& secretKey,
+ const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
+{
+ Aws::String signingKey(Aws::Auth::AWSAuthHelper::SIGNING_KEY);
+ signingKey.append(secretKey);
+ auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()),
+ ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length()));
+
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\"");
+ return {};
+ }
+
+ auto kDate = hashResult.GetResult();
+ hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) region string \"" << region << "\"");
+ return {};
+ }
+
+ auto kRegion = hashResult.GetResult();
+ hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\"");
+ return {};
+ }
+
+ auto kService = hashResult.GetResult();
+ hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), kService);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to HMAC (SHA256) request string");
+ AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << "\"");
+ return {};
+ }
+ return hashResult.GetResult();
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerCommon.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerCommon.cpp
new file mode 100644
index 00000000000..d26f41e6b30
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerCommon.cpp
@@ -0,0 +1,14 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSAuthSignerCommon.h>
+
+namespace Aws
+{
+namespace Auth
+{
+const char SIGNATURE[] = "Signature";
+} // namespace Auth
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerHelper.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerHelper.cpp
new file mode 100644
index 00000000000..5f7005d1da2
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthSignerHelper.cpp
@@ -0,0 +1,103 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSAuthSignerHelper.h>
+#include <aws/core/http/HttpTypes.h>
+
+#include <aws/core/http/HttpRequest.h>
+#include <aws/core/http/URI.h>
+#include <aws/core/utils/StringUtils.h>
+
+namespace Aws
+{
+namespace Auth
+{
+
+const char* AWSAuthHelper::EQ = "=";
+const char* AWSAuthHelper::AWS_HMAC_SHA256 = "AWS4-HMAC-SHA256";
+const char* AWSAuthHelper::AWS4_REQUEST = "aws4_request";
+const char* AWSAuthHelper::SIGNED_HEADERS = "SignedHeaders";
+const char* AWSAuthHelper::CREDENTIAL = "Credential";
+const char* AWSAuthHelper::NEWLINE = "\n";
+const char* AWSAuthHelper::X_AMZN_TRACE_ID = "x-amzn-trace-id";
+const char* AWSAuthHelper::X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256";
+const char* AWSAuthHelper::SIGNING_KEY = "AWS4";
+const char* AWSAuthHelper::SIMPLE_DATE_FORMAT_STR = "%Y%m%d";
+
+Aws::String Aws::Auth::AWSAuthHelper::CanonicalizeRequestSigningString(Aws::Http::HttpRequest& request, bool urlEscapePath)
+{
+ request.CanonicalizeRequest();
+ Aws::StringStream signingStringStream;
+ signingStringStream << Aws::Http::HttpMethodMapper::GetNameForHttpMethod(request.GetMethod());
+
+ Aws::Http::URI uriCpy = request.GetUri();
+ // Many AWS services do not decode the URL before calculating SignatureV4 on their end.
+ // This results in the signature getting calculated with a double encoded URL.
+ // That means we have to double encode it here for the signature to match on the service side.
+ if(urlEscapePath)
+ {
+ // RFC3986 is how we encode the URL before sending it on the wire.
+ uriCpy.SetPath(uriCpy.GetURLEncodedPathRFC3986());
+ // However, SignatureV4 uses this URL encoding scheme
+ signingStringStream << AWSAuthHelper::NEWLINE << uriCpy.GetURLEncodedPath() << AWSAuthHelper::NEWLINE;
+ }
+ else
+ {
+ // For the services that DO decode the URL first; we don't need to double encode it.
+ signingStringStream << AWSAuthHelper::NEWLINE << uriCpy.GetURLEncodedPath() << AWSAuthHelper::NEWLINE;
+ }
+
+ if (request.GetQueryString().find('=') != std::string::npos)
+ {
+ signingStringStream << request.GetQueryString().substr(1) << AWSAuthHelper::NEWLINE;
+ }
+ else if (request.GetQueryString().size() > 1)
+ {
+ signingStringStream << request.GetQueryString().substr(1) << "=" << AWSAuthHelper::NEWLINE;
+ }
+ else
+ {
+ signingStringStream << AWSAuthHelper::NEWLINE;
+ }
+
+ return signingStringStream.str();
+}
+
+Aws::Http::HeaderValueCollection Aws::Auth::AWSAuthHelper::CanonicalizeHeaders(Aws::Http::HeaderValueCollection&& headers)
+{
+ Aws::Http::HeaderValueCollection canonicalHeaders;
+ for (const auto& header : headers)
+ {
+ auto trimmedHeaderName = Aws::Utils::StringUtils::Trim(header.first.c_str());
+ auto trimmedHeaderValue = Aws::Utils::StringUtils::Trim(header.second.c_str());
+
+ //multiline gets converted to line1,line2,etc...
+ auto headerMultiLine = Aws::Utils::StringUtils::SplitOnLine(trimmedHeaderValue);
+ Aws::String headerValue = headerMultiLine.size() == 0 ? "" : headerMultiLine[0];
+
+ if (headerMultiLine.size() > 1)
+ {
+ for(size_t i = 1; i < headerMultiLine.size(); ++i)
+ {
+ headerValue += " ";
+ headerValue += Aws::Utils::StringUtils::Trim(headerMultiLine[i].c_str());
+ }
+ }
+
+ //duplicate spaces need to be converted to one.
+ Aws::String::iterator new_end =
+ std::unique(headerValue.begin(), headerValue.end(),
+ [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
+ );
+ headerValue.erase(new_end, headerValue.end());
+
+ canonicalHeaders[trimmedHeaderName] = headerValue;
+ }
+
+ return canonicalHeaders;
+}
+
+} // namespace Auth
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp
new file mode 100644
index 00000000000..f8bfdbf8671
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp
@@ -0,0 +1,580 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSAuthV4Signer.h>
+#include <aws/core/auth/signer/AWSAuthSignerCommon.h>
+#include <aws/core/auth/signer/AWSAuthSignerHelper.h>
+
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/http/HttpRequest.h>
+#include <aws/core/http/URI.h>
+#include <aws/core/utils/DateTime.h>
+#include <aws/core/utils/HashingUtils.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+#include <aws/core/utils/crypto/Sha256.h>
+#include <aws/core/utils/crypto/Sha256HMAC.h>
+
+#include <aws/crt/auth/Credentials.h>
+#include <aws/crt/http/HttpRequestResponse.h>
+
+#include <iomanip>
+#include <cstring>
+
+using namespace Aws;
+using namespace Aws::Client;
+using namespace Aws::Auth;
+using namespace Aws::Http;
+using namespace Aws::Utils;
+using namespace Aws::Utils::Logging;
+
+static const char* X_AMZ_SIGNED_HEADERS = "X-Amz-SignedHeaders";
+static const char* X_AMZ_ALGORITHM = "X-Amz-Algorithm";
+static const char* X_AMZ_CREDENTIAL = "X-Amz-Credential";
+static const char* UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
+static const char* STREAMING_UNSIGNED_PAYLOAD_TRAILER = "STREAMING-UNSIGNED-PAYLOAD-TRAILER";
+static const char* X_AMZ_SIGNATURE = "X-Amz-Signature";
+static const char* USER_AGENT = "user-agent";
+static const char* EMPTY_STRING_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+
+static const char v4LogTag[] = "AWSAuthV4Signer";
+static const char v4AsymmetricLogTag[] = "AWSAuthSymmetricV4Signer";
+
+namespace Aws
+{
+ namespace Auth
+ {
+ const char SIGV4_SIGNER[] = "SignatureV4";
+ const char ASYMMETRIC_SIGV4_SIGNER[] = "AsymmetricSignatureV4";
+ }
+}
+
+AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& credentialsProvider, const char* serviceName,
+ const Aws::String& region, PayloadSigningPolicy signingPolicy, bool urlEscapePath, AWSSigningAlgorithm signingAlgorithm) :
+ m_includeSha256HashHeader(true),
+ m_signingAlgorithm(signingAlgorithm),
+ m_credentialsProvider(credentialsProvider),
+ m_serviceName(serviceName),
+ m_region(region),
+ m_hash(Aws::MakeUnique<Aws::Utils::Crypto::Sha256>(v4LogTag)),
+ m_HMAC(Aws::MakeUnique<Aws::Utils::Crypto::Sha256HMAC>(v4LogTag)),
+ m_unsignedHeaders({USER_AGENT, Aws::Auth::AWSAuthHelper::X_AMZN_TRACE_ID}),
+ m_payloadSigningPolicy(signingPolicy),
+ m_urlEscapePath(urlEscapePath)
+{
+ //go ahead and warm up the signing cache.
+ ComputeHash(credentialsProvider->GetAWSCredentials().GetAWSSecretKey(), DateTime::CalculateGmtTimestampAsString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR), region, m_serviceName);
+}
+
+AWSAuthV4Signer::~AWSAuthV4Signer()
+{
+ // empty destructor in .cpp file to keep from needing the implementation of (AWSCredentialsProvider, Sha256, Sha256HMAC) in the header file
+}
+
+bool AWSAuthV4Signer::SignRequestWithSigV4a(Aws::Http::HttpRequest& request, const char* region, const char* serviceName,
+ bool signBody, long long expirationTimeInSeconds, Aws::Crt::Auth::SignatureType signatureType) const
+{
+ AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
+ auto crtCredentials = Aws::MakeShared<Aws::Crt::Auth::Credentials>(v4AsymmetricLogTag,
+ Aws::Crt::ByteCursorFromCString(credentials.GetAWSAccessKeyId().c_str()),
+ Aws::Crt::ByteCursorFromCString(credentials.GetAWSSecretKey().c_str()),
+ Aws::Crt::ByteCursorFromCString(credentials.GetSessionToken().c_str()),
+ credentials.GetExpiration().Seconds());
+
+ Aws::Crt::Auth::AwsSigningConfig awsSigningConfig;
+ awsSigningConfig.SetSigningAlgorithm(static_cast<Aws::Crt::Auth::SigningAlgorithm>(AWSSigningAlgorithm::ASYMMETRIC_SIGV4));
+ awsSigningConfig.SetSignatureType(signatureType);
+ awsSigningConfig.SetRegion(region);
+ awsSigningConfig.SetService(serviceName);
+ awsSigningConfig.SetSigningTimepoint(GetSigningTimestamp().UnderlyingTimestamp());
+ awsSigningConfig.SetUseDoubleUriEncode(m_urlEscapePath);
+ awsSigningConfig.SetShouldNormalizeUriPath(true);
+ awsSigningConfig.SetOmitSessionToken(false);
+ awsSigningConfig.SetShouldSignHeaderUserData(reinterpret_cast<void*>(const_cast<Aws::Set<Aws::String>*>(&m_unsignedHeaders)));
+ awsSigningConfig.SetShouldSignHeaderCallback([](const Aws::Crt::ByteCursor *name, void *user_data) {
+ Aws::Set<Aws::String>* unsignedHeaders = static_cast<Aws::Set<Aws::String>*>(user_data);
+ Aws::String headerKey(reinterpret_cast<const char*>(name->ptr), name->len);
+ return unsignedHeaders->find(Aws::Utils::StringUtils::ToLower(headerKey.c_str())) == unsignedHeaders->cend();
+ });
+ if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
+ {
+ Aws::String payloadHash(UNSIGNED_PAYLOAD);
+ if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS)
+ {
+ if (!request.GetContentBody())
+ {
+ AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty.");
+ payloadHash = EMPTY_STRING_SHA256;
+ }
+ else
+ {
+ // The hash will be calculated from the payload during signing.
+ payloadHash = {};
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody
+ << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme()));
+ }
+ awsSigningConfig.SetSignedBodyValue(payloadHash.c_str());
+ awsSigningConfig.SetSignedBodyHeader(m_includeSha256HashHeader ? Aws::Crt::Auth::SignedBodyHeaderType::XAmzContentSha256 : Aws::Crt::Auth::SignedBodyHeaderType::None);
+ }
+ else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
+ {
+ if (ServiceRequireUnsignedPayload(serviceName))
+ {
+ awsSigningConfig.SetSignedBodyValue(UNSIGNED_PAYLOAD);
+ }
+ else
+ {
+ awsSigningConfig.SetSignedBodyValue(EMPTY_STRING_SHA256);
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "The signature type should be either \"HttpRequestViaHeaders\" or \"HttpRequestViaQueryParams\"");
+ return false;
+ }
+ awsSigningConfig.SetExpirationInSeconds(static_cast<uint64_t>(expirationTimeInSeconds));
+ awsSigningConfig.SetCredentials(crtCredentials);
+
+ std::shared_ptr<Aws::Crt::Http::HttpRequest> crtHttpRequest = request.ToCrtHttpRequest();
+
+ auto sigv4HttpRequestSigner = Aws::MakeShared<Aws::Crt::Auth::Sigv4HttpRequestSigner>(v4AsymmetricLogTag);
+ bool success = true;
+ sigv4HttpRequestSigner->SignRequest(crtHttpRequest, awsSigningConfig,
+ [&request, &success, signatureType](const std::shared_ptr<Aws::Crt::Http::HttpRequest>& signedCrtHttpRequest, int errorCode) {
+ success = (errorCode == AWS_ERROR_SUCCESS);
+ if (success)
+ {
+ if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
+ {
+ for (size_t i = 0; i < signedCrtHttpRequest->GetHeaderCount(); i++)
+ {
+ Aws::Crt::Optional<Aws::Crt::Http::HttpHeader> httpHeader = signedCrtHttpRequest->GetHeader(i);
+ request.SetHeaderValue(Aws::String(reinterpret_cast<const char*>(httpHeader->name.ptr), httpHeader->name.len),
+ Aws::String(reinterpret_cast<const char*>(httpHeader->value.ptr), httpHeader->value.len));
+ }
+ }
+ else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
+ {
+ Aws::Http::URI newPath(reinterpret_cast<const char*>(signedCrtHttpRequest->GetPath()->ptr));
+ request.GetUri().SetQueryString(newPath.GetQueryString());
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "No action to take when signature type is neither \"HttpRequestViaHeaders\" nor \"HttpRequestViaQueryParams\"");
+ success = false;
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "Encountered internal error during signing process with AWS signature version 4 (Asymmetric):" << aws_error_str(errorCode));
+ }
+ }
+ );
+ return success;
+}
+
+bool AWSAuthV4Signer::ShouldSignHeader(const Aws::String& header) const
+{
+ return m_unsignedHeaders.find(Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend();
+}
+
+bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool signBody) const
+{
+ Aws::String signingRegion = region ? region : m_region;
+ Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
+ AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
+
+ //don't sign anonymous requests
+ if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
+ {
+ return true;
+ }
+
+ request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
+ request.SetSigningRegion(signingRegion);
+
+ Aws::String payloadHash(UNSIGNED_PAYLOAD);
+ switch(m_payloadSigningPolicy)
+ {
+ case PayloadSigningPolicy::Always:
+ signBody = true;
+ break;
+ case PayloadSigningPolicy::Never:
+ signBody = false;
+ break;
+ case PayloadSigningPolicy::RequestDependent:
+ // respect the request setting
+ default:
+ break;
+ }
+
+ if (m_signingAlgorithm == AWSSigningAlgorithm::ASYMMETRIC_SIGV4)
+ {
+ // Replace m_serviceName with signingServiceName after rebasing on S3 outposts.
+ return SignRequestWithSigV4a(request, signingRegion.c_str(), m_serviceName.c_str(), signBody,
+ 0 /* expirationTimeInSeconds doesn't matter for HttpRequestViaHeaders */, Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders);
+ }
+
+ if (!credentials.GetSessionToken().empty())
+ {
+ request.SetAwsSessionToken(credentials.GetSessionToken());
+ }
+
+ if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS)
+ {
+ payloadHash = ComputePayloadHash(request);
+ if (payloadHash.empty())
+ {
+ return false;
+ }
+ if (request.GetRequestHash().second != nullptr)
+ {
+ Aws::String checksumHeaderKey = Aws::String("x-amz-checksum-") + request.GetRequestHash().first;
+ Aws::String checksumHeaderValue = HashingUtils::Base64Encode(request.GetRequestHash().second->Calculate(*(request.GetContentBody())).GetResult());
+ request.SetHeaderValue(checksumHeaderKey, checksumHeaderValue);
+ request.SetRequestHash("", nullptr);
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody
+ << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme()));
+ if (request.GetRequestHash().second != nullptr)
+ {
+ payloadHash = STREAMING_UNSIGNED_PAYLOAD_TRAILER;
+ Aws::String trailerHeaderValue = Aws::String("x-amz-checksum-") + request.GetRequestHash().first;
+ request.SetHeaderValue(Http::AWS_TRAILER_HEADER, trailerHeaderValue);
+ request.SetTransferEncoding(CHUNKED_VALUE);
+ request.SetHeaderValue(Http::CONTENT_ENCODING_HEADER, Http::AWS_CHUNKED_VALUE);
+ request.SetHeaderValue(Http::DECODED_CONTENT_LENGTH_HEADER, request.GetHeaderValue(Http::CONTENT_LENGTH_HEADER));
+ request.DeleteHeader(Http::CONTENT_LENGTH_HEADER);
+ }
+ }
+
+ if(m_includeSha256HashHeader)
+ {
+ request.SetHeaderValue(Aws::Auth::AWSAuthHelper::X_AMZ_CONTENT_SHA256, payloadHash);
+ }
+
+ //calculate date header to use in internal signature (this also goes into date header).
+ DateTime now = GetSigningTimestamp();
+ Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
+ request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue);
+
+ Aws::StringStream headersStream;
+ Aws::StringStream signedHeadersStream;
+
+ for (const auto& header : Aws::Auth::AWSAuthHelper::CanonicalizeHeaders(request.GetHeaders()))
+ {
+ if(ShouldSignHeader(header.first))
+ {
+ headersStream << header.first.c_str() << ":" << header.second.c_str() << Aws::Auth::AWSAuthHelper::NEWLINE;
+ signedHeadersStream << header.first.c_str() << ";";
+ }
+ }
+
+ Aws::String canonicalHeadersString = headersStream.str();
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString);
+
+ //calculate signed headers parameter
+ Aws::String signedHeadersValue = signedHeadersStream.str();
+ //remove that last semi-colon
+ if (!signedHeadersValue.empty())
+ {
+ signedHeadersValue.pop_back();
+ }
+
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value:" << signedHeadersValue);
+
+ //generate generalized canonicalized request string.
+ Aws::String canonicalRequestString = Aws::Auth::AWSAuthHelper::CanonicalizeRequestSigningString(request, m_urlEscapePath);
+
+ //append v4 stuff to the canonical request string.
+ canonicalRequestString.append(canonicalHeadersString);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ canonicalRequestString.append(signedHeadersValue);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ canonicalRequestString.append(payloadHash);
+
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString);
+
+ //now compute sha256 on that request string
+ auto hashResult = m_hash->Calculate(canonicalRequestString);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string");
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\"");
+ return false;
+ }
+
+ auto sha256Digest = hashResult.GetResult();
+ Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
+ Aws::String simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR);
+
+ Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
+ auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
+
+ Aws::StringStream ss;
+ ss << Aws::Auth::AWSAuthHelper::AWS_HMAC_SHA256 << " " << Aws::Auth::AWSAuthHelper::CREDENTIAL << Aws::Auth::AWSAuthHelper::EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate
+ << "/" << signingRegion << "/" << signingServiceName << "/" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << ", " << Aws::Auth::AWSAuthHelper::SIGNED_HEADERS << Aws::Auth::AWSAuthHelper::EQ
+ << signedHeadersValue << ", " << SIGNATURE << Aws::Auth::AWSAuthHelper::EQ << finalSignature;
+
+ auto awsAuthString = ss.str();
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Signing request with: " << awsAuthString);
+ request.SetAwsAuthorization(awsAuthString);
+ return true;
+}
+
+bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, long long expirationTimeInSeconds) const
+{
+ return PresignRequest(request, m_region.c_str(), expirationTimeInSeconds);
+}
+
+bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, long long expirationInSeconds) const
+{
+ return PresignRequest(request, region, m_serviceName.c_str(), expirationInSeconds);
+}
+
+bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, long long expirationTimeInSeconds) const
+{
+ Aws::String signingRegion = region ? region : m_region;
+ Aws::String signingServiceName = serviceName ? serviceName : m_serviceName;
+ AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials();
+
+ //don't sign anonymous requests
+ if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty())
+ {
+ return true;
+ }
+
+ if (m_signingAlgorithm == AWSSigningAlgorithm::ASYMMETRIC_SIGV4)
+ {
+ return SignRequestWithSigV4a(request, signingRegion.c_str(), signingServiceName.c_str(), false /* signBody doesn't matter for HttpRequestViaHeaders */,
+ expirationTimeInSeconds, Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams);
+ }
+
+ Aws::StringStream intConversionStream;
+ intConversionStream << expirationTimeInSeconds;
+ request.AddQueryStringParameter(Http::X_AMZ_EXPIRES_HEADER, intConversionStream.str());
+
+ if (!credentials.GetSessionToken().empty())
+ {
+ request.AddQueryStringParameter(Http::AWS_SECURITY_TOKEN, credentials.GetSessionToken());
+ }
+
+ //calculate date header to use in internal signature (this also goes into date header).
+ DateTime now = GetSigningTimestamp();
+ Aws::String dateQueryValue = now.ToGmtString(DateFormat::ISO_8601_BASIC);
+ request.AddQueryStringParameter(Http::AWS_DATE_HEADER, dateQueryValue);
+
+ Aws::StringStream headersStream;
+ Aws::StringStream signedHeadersStream;
+ for (const auto& header : Aws::Auth::AWSAuthHelper::CanonicalizeHeaders(request.GetHeaders()))
+ {
+ if(ShouldSignHeader(header.first))
+ {
+ headersStream << header.first.c_str() << ":" << header.second.c_str() << Aws::Auth::AWSAuthHelper::NEWLINE;
+ signedHeadersStream << header.first.c_str() << ";";
+ }
+ }
+
+ Aws::String canonicalHeadersString = headersStream.str();
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Header String: " << canonicalHeadersString);
+
+ //calculate signed headers parameter
+ Aws::String signedHeadersValue(signedHeadersStream.str());
+ //remove that last semi-colon
+ if (!signedHeadersValue.empty())
+ {
+ signedHeadersValue.pop_back();
+ }
+
+ request.AddQueryStringParameter(X_AMZ_SIGNED_HEADERS, signedHeadersValue);
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value: " << signedHeadersValue);
+
+ Aws::StringStream ss;
+ Aws::String simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR);
+ ss << credentials.GetAWSAccessKeyId() << "/" << simpleDate
+ << "/" << signingRegion << "/" << signingServiceName << "/" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST;
+
+ request.AddQueryStringParameter(X_AMZ_ALGORITHM, Aws::Auth::AWSAuthHelper::AWS_HMAC_SHA256);
+ request.AddQueryStringParameter(X_AMZ_CREDENTIAL, ss.str());
+ ss.str("");
+
+ request.SetSigningAccessKey(credentials.GetAWSAccessKeyId());
+ request.SetSigningRegion(signingRegion);
+
+ //generate generalized canonicalized request string.
+ Aws::String canonicalRequestString = Aws::Auth::AWSAuthHelper::CanonicalizeRequestSigningString(request, m_urlEscapePath);
+
+ //append v4 stuff to the canonical request string.
+ canonicalRequestString.append(canonicalHeadersString);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ canonicalRequestString.append(signedHeadersValue);
+ canonicalRequestString.append(Aws::Auth::AWSAuthHelper::NEWLINE);
+ if (ServiceRequireUnsignedPayload(signingServiceName))
+ {
+ canonicalRequestString.append(UNSIGNED_PAYLOAD);
+ }
+ else
+ {
+ canonicalRequestString.append(EMPTY_STRING_SHA256);
+ }
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString);
+
+ //now compute sha256 on that request string
+ auto hashResult = m_hash->Calculate(canonicalRequestString);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string");
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\"");
+ return false;
+ }
+
+ auto sha256Digest = hashResult.GetResult();
+ auto canonicalRequestHash = HashingUtils::HexEncode(sha256Digest);
+
+ auto stringToSign = GenerateStringToSign(dateQueryValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName);
+ auto finalSigningHash = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName);
+ if (finalSigningHash.empty())
+ {
+ return false;
+ }
+
+ //add that the signature to the query string
+ request.AddQueryStringParameter(X_AMZ_SIGNATURE, finalSigningHash);
+
+ return true;
+}
+
+bool AWSAuthV4Signer::ServiceRequireUnsignedPayload(const Aws::String& serviceName) const
+{
+ // S3 uses a magic string (instead of the empty string) for its body hash for presigned URLs as outlined here:
+ // https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
+ // this is true for PUT, POST, GET, DELETE and HEAD operations.
+ // However, other services (for example RDS) implement the specification as outlined here:
+ // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
+ // which states that body-less requests should use the empty-string SHA256 hash.
+ return "s3" == serviceName || "s3-object-lambda" == serviceName;
+}
+
+Aws::String AWSAuthV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign,
+ const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
+{
+ auto key = ComputeHash(credentials.GetAWSSecretKey(), simpleDate, region, serviceName);
+ return GenerateSignature(stringToSign, key);
+}
+
+Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const
+{
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Final String to sign: " << stringToSign);
+
+ Aws::StringStream ss;
+
+ auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string");
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\"");
+ return {};
+ }
+
+ //now we finally sign our request string with our hex encoded derived hash.
+ auto finalSigningDigest = hashResult.GetResult();
+
+ auto finalSigningHash = HashingUtils::HexEncode(finalSigningDigest);
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Final computed signing hash: " << finalSigningHash);
+
+ return finalSigningHash;
+}
+
+Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) const
+{
+ if (!request.GetContentBody())
+ {
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty.");
+ return EMPTY_STRING_SHA256;
+ }
+
+ //compute hash on payload if it exists.
+ auto hashResult = m_hash->Calculate(*request.GetContentBody());
+
+ if(request.GetContentBody())
+ {
+ request.GetContentBody()->clear();
+ request.GetContentBody()->seekg(0);
+ }
+
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body");
+ return {};
+ }
+
+ auto sha256Digest = hashResult.GetResult();
+
+ Aws::String payloadHash(HashingUtils::HexEncode(sha256Digest));
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "Calculated sha256 " << payloadHash << " for payload.");
+ return payloadHash;
+}
+
+Aws::String AWSAuthV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate,
+ const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const
+{
+ //generate the actual string we will use in signing the final request.
+ Aws::StringStream ss;
+
+ ss << Aws::Auth::AWSAuthHelper::AWS_HMAC_SHA256 << Aws::Auth::AWSAuthHelper::NEWLINE << dateValue << Aws::Auth::AWSAuthHelper::NEWLINE << simpleDate << "/" << region << "/"
+ << serviceName << "/" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << Aws::Auth::AWSAuthHelper::NEWLINE << canonicalRequestHash;
+
+ return ss.str();
+}
+
+Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey,
+ const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const
+{
+ Aws::String signingKey(Aws::Auth::AWSAuthHelper::SIGNING_KEY);
+ signingKey.append(secretKey);
+ auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()),
+ ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length()));
+
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\"");
+ return {};
+ }
+
+ auto kDate = hashResult.GetResult();
+ hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) region string \"" << region << "\"");
+ return {};
+ }
+
+ auto kRegion = hashResult.GetResult();
+ hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\"");
+ return {};
+ }
+
+ auto kService = hashResult.GetResult();
+ hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), kService);
+ if (!hashResult.IsSuccess())
+ {
+ AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to HMAC (SHA256) request string");
+ AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << "\"");
+ return {};
+ }
+ return hashResult.GetResult();
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSNullSigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSNullSigner.cpp
new file mode 100644
index 00000000000..d94cb421f2b
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/signer/AWSNullSigner.cpp
@@ -0,0 +1,14 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/auth/signer/AWSNullSigner.h>
+
+namespace Aws
+{
+ namespace Auth
+ {
+ const char NULL_SIGNER[] = "NullSigner";
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp
index 4b2a38b4e68..d1a6f262c9d 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp
@@ -7,11 +7,13 @@
#include <aws/core/AmazonWebServiceRequest.h>
#include <aws/core/auth/AWSAuthSigner.h>
#include <aws/core/auth/AWSAuthSignerProvider.h>
+#include <aws/core/client/AWSUrlPresigner.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/client/AWSErrorMarshaller.h>
#include <aws/core/client/ClientConfiguration.h>
#include <aws/core/client/CoreErrors.h>
#include <aws/core/client/RetryStrategy.h>
+#include <aws/core/client/RequestCompression.h>
#include <aws/core/http/HttpClient.h>
#include <aws/core/http/HttpClientFactory.h>
#include <aws/core/http/HttpResponse.h>
@@ -27,6 +29,9 @@
#include <aws/core/Globals.h>
#include <aws/core/utils/EnumParseOverflowContainer.h>
#include <aws/core/utils/crypto/MD5.h>
+#include <aws/core/utils/crypto/CRC32.h>
+#include <aws/core/utils/crypto/Sha256.h>
+#include <aws/core/utils/crypto/Sha1.h>
#include <aws/core/utils/HashingUtils.h>
#include <aws/core/utils/crypto/Factories.h>
#include <aws/core/utils/event/EventStream.h>
@@ -35,10 +40,12 @@
#include <aws/core/Region.h>
#include <aws/core/utils/DNS.h>
#include <aws/core/Version.h>
+#include <aws/core/platform/Environment.h>
#include <aws/core/platform/OSVersionInfo.h>
#include <cstring>
#include <cassert>
+#include <iomanip>
using namespace Aws;
using namespace Aws::Client;
@@ -51,12 +58,15 @@ static const int SUCCESS_RESPONSE_MIN = 200;
static const int SUCCESS_RESPONSE_MAX = 299;
static const char AWS_CLIENT_LOG_TAG[] = "AWSClient";
+static const char AWS_LAMBDA_FUNCTION_NAME[] = "AWS_LAMBDA_FUNCTION_NAME";
+static const char X_AMZN_TRACE_ID[] = "_X_AMZN_TRACE_ID";
+
//4 Minutes
static const std::chrono::milliseconds TIME_DIFF_MAX = std::chrono::minutes(4);
//-4 Minutes
static const std::chrono::milliseconds TIME_DIFF_MIN = std::chrono::minutes(-4);
-static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode)
+CoreErrors AWSClient::GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode)
{
switch (responseCode)
{
@@ -70,6 +80,14 @@ static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCod
}
}
+bool AWSClient::DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response)
+{
+ if (response->HasClientError()) return true;
+
+ int responseCode = static_cast<int>(response->GetResponseCode());
+ return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX;
+}
+
struct RequestInfo
{
Aws::Utils::DateTime ttl;
@@ -107,9 +125,10 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration,
m_customizedUserAgent(!m_userAgent.empty()),
m_hash(Aws::Utils::Crypto::CreateMD5Implementation()),
m_requestTimeoutMs(configuration.requestTimeoutMs),
- m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment)
+ m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment),
+ m_requestCompressionConfig(configuration.requestCompressionConfig)
{
- SetServiceClientName("AWSBaseClient");
+ AWSClient::SetServiceClientName("AWSBaseClient");
}
AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration,
@@ -126,9 +145,10 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration,
m_customizedUserAgent(!m_userAgent.empty()),
m_hash(Aws::Utils::Crypto::CreateMD5Implementation()),
m_requestTimeoutMs(configuration.requestTimeoutMs),
- m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment)
+ m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment),
+ m_requestCompressionConfig(configuration.requestCompressionConfig)
{
- SetServiceClientName("AWSBaseClient");
+ AWSClient::SetServiceClientName("AWSBaseClient");
}
void AWSClient::SetServiceClientName(const Aws::String& name)
@@ -136,10 +156,7 @@ void AWSClient::SetServiceClientName(const Aws::String& name)
m_serviceName = name;
if (!m_customizedUserAgent)
{
- Aws::StringStream ss;
- ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString()
- << " " << Version::GetCompilerVersionString();
- m_userAgent = ss.str();
+ m_userAgent = Aws::Client::ComputeUserAgentString();
}
}
@@ -232,16 +249,24 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri,
const char* signerRegion = signerRegionOverride;
Aws::String regionFromResponse;
- Aws::String invocationId = UUID::RandomUUID();
+ Aws::String invocationId = Aws::Utils::UUID::RandomUUID();
RequestInfo requestInfo;
requestInfo.attempt = 1;
requestInfo.maxAttempts = 0;
httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId);
httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo);
+ AppendRecursionDetectionHeader(httpRequest);
for (long retries = 0;; retries++)
{
- m_retryStrategy->GetSendToken();
+ if(!m_retryStrategy->HasSendToken())
+ {
+ return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::SLOW_DOWN,
+ "",
+ "Unable to acquire enough send tokens to execute request.",
+ false/*retryable*/));
+
+ };
httpRequest->SetEventStreamRequest(request.IsEventStreamRequest());
outcome = AttemptOneRequest(httpRequest, request, signerName, signerRegion, signerServiceNameOverride);
@@ -358,16 +383,24 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri,
const char* signerRegion = signerRegionOverride;
Aws::String regionFromResponse;
- Aws::String invocationId = UUID::RandomUUID();
+ Aws::String invocationId = Aws::Utils::UUID::RandomUUID();
RequestInfo requestInfo;
requestInfo.attempt = 1;
requestInfo.maxAttempts = 0;
httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId);
httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo);
+ AppendRecursionDetectionHeader(httpRequest);
for (long retries = 0;; retries++)
{
- m_retryStrategy->GetSendToken();
+ if(!m_retryStrategy->HasSendToken())
+ {
+ return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::SLOW_DOWN,
+ "",
+ "Unable to acquire enough send tokens to execute request.",
+ false/*retryable*/));
+
+ };
outcome = AttemptOneRequest(httpRequest, signerName, requestName, signerRegion, signerServiceNameOverride);
if (retries == 0)
{
@@ -452,15 +485,6 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri,
return outcome;
}
-static bool DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response)
-{
- if (response->HasClientError()) return true;
-
- int responseCode = static_cast<int>(response->GetResponseCode());
- return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX;
-
-}
-
HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpRequest>& httpRequest, const Aws::AmazonWebServiceRequest& request,
const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const
{
@@ -481,7 +505,31 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpReque
std::shared_ptr<HttpResponse> httpResponse(
m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get()));
- if (DoesResponseGenerateError(httpResponse))
+ if (request.ShouldValidateResponseChecksum())
+ {
+ for (const auto& hashIterator : httpRequest->GetResponseValidationHashes())
+ {
+ Aws::String checksumHeaderKey = Aws::String("x-amz-checksum-") + hashIterator.first;
+ // TODO: If checksum ends with -#, then skip
+ if (httpResponse->HasHeader(checksumHeaderKey.c_str()))
+ {
+ Aws::String checksumHeaderValue = httpResponse->GetHeader(checksumHeaderKey.c_str());
+ if (HashingUtils::Base64Encode(hashIterator.second->GetHash().GetResult()) != checksumHeaderValue)
+ {
+ AWSError<CoreErrors> error(CoreErrors::VALIDATION, "", "Response checksums mismatch", false/*retryable*/);
+ error.SetResponseHeaders(httpResponse->GetHeaders());
+ error.SetResponseCode(httpResponse->GetResponseCode());
+ error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
+ AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error);
+ return HttpResponseOutcome(error);
+ }
+ // Validate only a single checksum returned in an HTTP response
+ break;
+ }
+ }
+ }
+
+ if (DoesResponseGenerateError(httpResponse) || request.HasEmbeddedError(httpResponse->GetResponseBody(), httpResponse->GetHeaders()))
{
AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response");
auto error = BuildAWSError(httpResponse);
@@ -560,6 +608,54 @@ StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::Http::URI& u
return StreamOutcome(std::move(httpResponseOutcome));
}
+StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Endpoint::AWSEndpoint& endpoint,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+
+ return MakeRequestWithUnparsedResponse(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
+}
+
+XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Endpoint::AWSEndpoint& endpoint,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+
+ return MakeRequestWithEventStream(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
+}
+
XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::Http::URI& uri,
const Aws::AmazonWebServiceRequest& request,
Http::HttpMethod method,
@@ -603,6 +699,119 @@ void AWSClient::AddHeadersToRequest(const std::shared_ptr<Aws::Http::HttpRequest
AddCommonHeaders(*httpRequest);
}
+void AWSClient::AppendHeaderValueToRequest(const std::shared_ptr<HttpRequest> &httpRequest, const String header, const String value) const
+{
+ if (!httpRequest->HasHeader(header.c_str()))
+ {
+ httpRequest->SetHeaderValue(header, value);
+ }
+ else
+ {
+ Aws::String contentEncoding = httpRequest->GetHeaderValue(header.c_str());
+ contentEncoding.append(",").append(value);
+ httpRequest->SetHeaderValue(header, contentEncoding);
+ }
+}
+
+void AWSClient::AddChecksumToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest,
+ const Aws::AmazonWebServiceRequest& request) const
+{
+ Aws::String checksumAlgorithmName = Aws::Utils::StringUtils::ToLower(request.GetChecksumAlgorithmName().c_str());
+
+ // Request checksums
+ if (!checksumAlgorithmName.empty())
+ {
+ // For non-streaming payload, the resolved checksum location is always header.
+ // For streaming payload, the resolved checksum location depends on whether it is an unsigned payload, we let AwsAuthSigner decide it.
+ if (checksumAlgorithmName == "crc32")
+ {
+ if (request.IsStreaming())
+ {
+ httpRequest->SetRequestHash("crc32", Aws::MakeShared<Crypto::CRC32>(AWS_CLIENT_LOG_TAG));
+ }
+ else
+ {
+ httpRequest->SetHeaderValue("x-amz-checksum-crc32", HashingUtils::Base64Encode(HashingUtils::CalculateCRC32(*(GetBodyStream(request)))));
+ }
+ }
+ else if (checksumAlgorithmName == "crc32c")
+ {
+ if (request.IsStreaming())
+ {
+ httpRequest->SetRequestHash("crc32c", Aws::MakeShared<Crypto::CRC32C>(AWS_CLIENT_LOG_TAG));
+ }
+ else
+ {
+ httpRequest->SetHeaderValue("x-amz-checksum-crc32c", HashingUtils::Base64Encode(HashingUtils::CalculateCRC32C(*(GetBodyStream(request)))));
+ }
+ }
+ else if (checksumAlgorithmName == "sha256")
+ {
+ if (request.IsStreaming())
+ {
+ httpRequest->SetRequestHash("sha256", Aws::MakeShared<Crypto::Sha256>(AWS_CLIENT_LOG_TAG));
+ }
+ else
+ {
+ httpRequest->SetHeaderValue("x-amz-checksum-sha256", HashingUtils::Base64Encode(HashingUtils::CalculateSHA256(*(GetBodyStream(request)))));
+ }
+ }
+ else if (checksumAlgorithmName == "sha1")
+ {
+ if (request.IsStreaming())
+ {
+ httpRequest->SetRequestHash("sha1", Aws::MakeShared<Crypto::Sha1>(AWS_CLIENT_LOG_TAG));
+ }
+ else
+ {
+ httpRequest->SetHeaderValue("x-amz-checksum-sha1", HashingUtils::Base64Encode(HashingUtils::CalculateSHA1(*(GetBodyStream(request)))));
+ }
+ }
+ else if (checksumAlgorithmName == "md5")
+ {
+ httpRequest->SetHeaderValue(Http::CONTENT_MD5_HEADER, HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*(GetBodyStream(request)))));
+ }
+ else
+ {
+ AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Checksum algorithm: " << checksumAlgorithmName << "is not supported by SDK.");
+ }
+ }
+
+ // Response checksums
+ if (request.ShouldValidateResponseChecksum())
+ {
+ for (const Aws::String& responseChecksumAlgorithmName : request.GetResponseChecksumAlgorithmNames())
+ {
+ checksumAlgorithmName = Aws::Utils::StringUtils::ToLower(responseChecksumAlgorithmName.c_str());
+
+ if (checksumAlgorithmName == "crc32c")
+ {
+ std::shared_ptr<Aws::Utils::Crypto::CRC32C> crc32c = Aws::MakeShared<Aws::Utils::Crypto::CRC32C>(AWS_CLIENT_LOG_TAG);
+ httpRequest->AddResponseValidationHash("crc32c", crc32c);
+ }
+ else if (checksumAlgorithmName == "crc32")
+ {
+ std::shared_ptr<Aws::Utils::Crypto::CRC32> crc32 = Aws::MakeShared<Aws::Utils::Crypto::CRC32>(AWS_CLIENT_LOG_TAG);
+ httpRequest->AddResponseValidationHash("crc", crc32);
+ }
+ else if (checksumAlgorithmName == "sha1")
+ {
+ std::shared_ptr<Aws::Utils::Crypto::Sha1> sha1 = Aws::MakeShared<Aws::Utils::Crypto::Sha1>(AWS_CLIENT_LOG_TAG);
+ httpRequest->AddResponseValidationHash("sha1", sha1);
+ }
+ else if (checksumAlgorithmName == "sha256")
+ {
+ std::shared_ptr<Aws::Utils::Crypto::Sha256> sha256 = Aws::MakeShared<Aws::Utils::Crypto::Sha256>(AWS_CLIENT_LOG_TAG);
+ httpRequest->AddResponseValidationHash("sha256", sha256);
+ }
+ else
+ {
+ AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Checksum algorithm: " << checksumAlgorithmName << " is not supported in validating response body yet.");
+ }
+ }
+ }
+}
+
void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest,
const std::shared_ptr<Aws::IOStream>& body, bool needsContentMd5, bool isChunked) const
{
@@ -610,7 +819,7 @@ void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpReq
//If there is no body, we have a content length of 0
//note: we also used to remove content-type, but S3 actually needs content-type on InitiateMultipartUpload and it isn't
- //forbiden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal.
+ //forbidden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal.
if (!body)
{
AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "No content body, content-length headers");
@@ -682,11 +891,11 @@ Aws::String Aws::Client::GetAuthorizationHeader(const Aws::Http::HttpRequest& ht
return authHeader.substr(signaturePosition + strlen(Aws::Auth::SIGNATURE) + 1);
}
-void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request,
- const std::shared_ptr<HttpRequest>& httpRequest) const
+void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, const std::shared_ptr<HttpRequest>& httpRequest) const
{
- //do headers first since the request likely will set content-length as it's own header.
+ //do headers first since the request likely will set content-length as its own header.
AddHeadersToRequest(httpRequest, request.GetHeaders());
+ AddHeadersToRequest(httpRequest, request.GetAdditionalCustomHeaders());
if (request.IsEventStreamRequest())
{
@@ -694,9 +903,31 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request,
}
else
{
- AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding());
+ //Check if compression is required
+ CompressionAlgorithm selectedCompressionAlgorithm =
+ request.GetSelectedCompressionAlgorithm(m_requestCompressionConfig);
+ if (Aws::Client::CompressionAlgorithm::NONE != selectedCompressionAlgorithm) {
+ Aws::Client::RequestCompression rc;
+ auto compressOutcome = rc.compress(request.GetBody(), selectedCompressionAlgorithm);
+
+ if (compressOutcome.IsSuccess()) {
+ Aws::String compressionAlgorithmId = Aws::Client::GetCompressionAlgorithmId(selectedCompressionAlgorithm);
+ AppendHeaderValueToRequest(httpRequest, CONTENT_ENCODING_HEADER, compressionAlgorithmId);
+ AddContentBodyToRequest(
+ httpRequest, compressOutcome.GetResult(),
+ request.ShouldComputeContentMd5(),
+ request.IsStreaming() && request.IsChunked() &&
+ m_httpClient->SupportsChunkedTransferEncoding());
+ } else {
+ AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Failed to compress request, submitting uncompressed");
+ AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding());
+ }
+ } else {
+ AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding());
+ }
}
+ AddChecksumToRequest(httpRequest, request);
// Pass along handlers for processing data sent/received in bytes
httpRequest->SetDataReceivedEventHandler(request.GetDataReceivedEventHandler());
httpRequest->SetDataSentEventHandler(request.GetDataSentEventHandler());
@@ -710,389 +941,132 @@ void AWSClient::AddCommonHeaders(HttpRequest& httpRequest) const
httpRequest.SetUserAgent(m_userAgent);
}
-Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, long long expirationInSeconds)
+Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, long long expirationInSeconds)
{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
-}
-
-Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
-{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- for (const auto& it: customizedHeaders)
- {
- request->SetHeaderValue(it.first.c_str(), it.second);
- }
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const char* region, long long expirationInSeconds) const
+Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, region, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, customizedHeaders, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const char* region, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
+Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const char* region, long long expirationInSeconds) const
{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- for (const auto& it: customizedHeaders)
- {
- request->SetHeaderValue(it.first.c_str(), it.second);
- }
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, region, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const
+Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const char* region, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, customizedHeaders, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const
{
- std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
- for (const auto& it: customizedHeaders)
- {
- request->SetHeaderValue(it.first.c_str(), it.second);
- }
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds))
- {
- return request->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region,
- const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
{
- std::shared_ptr<HttpRequest> httpRequest =
- ConvertToRequestForPresigning(request, uri, method, extraParams);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*httpRequest, region, expirationInSeconds))
- {
- return httpRequest->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, customizedHeaders, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName,
-const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const char* signerName, long long expirationInSeconds) const
{
- std::shared_ptr<HttpRequest> httpRequest =
- ConvertToRequestForPresigning(request, uri, method, extraParams);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*httpRequest, region, serviceName, expirationInSeconds))
- {
- return httpRequest->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, signerName, expirationInSeconds);
}
-Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method,
- const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const char* signerName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds)
{
- std::shared_ptr<HttpRequest> httpRequest =
- ConvertToRequestForPresigning(request, uri, method, extraParams);
- auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER);
- if (signer->PresignRequest(*httpRequest, expirationInSeconds))
- {
- return httpRequest->GetURIString();
- }
-
- return {};
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, signerName, customizedHeaders, expirationInSeconds);
}
-std::shared_ptr<Aws::Http::HttpRequest> AWSClient::ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri,
- Aws::Http::HttpMethod method, const Aws::Http::QueryStringParameterCollection& extraParams) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::Endpoint::AWSEndpoint& endpoint,
+ Aws::Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const Aws::Http::HeaderValueCollection& customizedHeaders /* = {} */,
+ uint64_t expirationInSeconds /* = 0 */,
+ const char* signerName /* = Aws::Auth::SIGV4_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */)
{
- request.PutToPresignedUrl(uri);
- std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
-
- for (auto& param : extraParams)
- {
- httpRequest->AddQueryStringParameter(param.first.c_str(), param.second);
- }
-
- return httpRequest;
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(endpoint, method, customizedHeaders, expirationInSeconds, signerName, signerRegionOverride, signerServiceNameOverride);
}
-std::shared_ptr<Aws::Http::HttpResponse> AWSClient::MakeHttpRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region,
+ const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
{
- return m_httpClient->MakeRequest(request, m_readRateLimiter.get(), m_writeRateLimiter.get());
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, extraParams, expirationInSeconds);
}
-
-////////////////////////////////////////////////////////////////////////////
-AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signer, errorMarshaller)
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName,
+ const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
{
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, serviceName, extraParams, expirationInSeconds);
}
-AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signerProvider, errorMarshaller)
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* region,
+ const char* serviceName,
+ const char* signerName,
+ const Aws::Http::QueryStringParameterCollection& extraParams,
+ long long expirationInSeconds) const
{
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, serviceName, signerName, extraParams, expirationInSeconds);
}
-
-JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
- const Aws::AmazonWebServiceRequest& request,
- Http::HttpMethod method,
- const char* signerName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
+Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method,
+ const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const
{
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return JsonOutcome(std::move(httpOutcome));
- }
-
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
-
- else
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+ return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, extraParams, expirationInSeconds);
}
-JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
- Http::HttpMethod method,
- const char* signerName,
- const char* requestName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
-{
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return JsonOutcome(std::move(httpOutcome));
- }
-
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- {
- JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
- if (!jsonValue.WasParseSuccessful())
- {
- return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
- }
-
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
+std::shared_ptr<Aws::IOStream> AWSClient::GetBodyStream(const Aws::AmazonWebServiceRequest& request) const {
+ if (request.GetBody() != nullptr) {
+ return request.GetBody();
}
-
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+ // Return an empty string stream for no body
+ return Aws::MakeShared<Aws::StringStream>(AWS_CLIENT_LOG_TAG, "");
}
-JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
+std::shared_ptr<Aws::Http::HttpResponse> AWSClient::MakeHttpRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
{
- // request is assumed to be signed
- std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request);
-
- if (DoesResponseGenerateError(httpResponse))
- {
- AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response");
- auto error = BuildAWSError(httpResponse);
- return JsonOutcome(std::move(error));
- }
-
- AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response.");
-
- HttpResponseOutcome httpOutcome(std::move(httpResponse));
-
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- {
- JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
- if (!jsonValue.WasParseSuccessful())
- {
- return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
- }
-
- //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
- httpOutcome.GetResult()->GetHeaders(),
- httpOutcome.GetResult()->GetResponseCode()));
- }
-
- return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+ return m_httpClient->MakeRequest(request, m_readRateLimiter.get(), m_writeRateLimiter.get());
}
-AWSError<CoreErrors> AWSJsonClient::BuildAWSError(
- const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const
+void AWSClient::AppendRecursionDetectionHeader(std::shared_ptr<Aws::Http::HttpRequest> ioRequest)
{
- AWSError<CoreErrors> error;
- if (httpResponse->HasClientError())
- {
- bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
- error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
+ if(!ioRequest || ioRequest->HasHeader(Aws::Http::X_AMZN_TRACE_ID_HEADER)) {
+ return;
}
- else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
- {
- auto responseCode = httpResponse->GetResponseCode();
- auto errorCode = GuessBodylessErrorType(responseCode);
-
- Aws::StringStream ss;
- ss << "No response body.";
- error = AWSError<CoreErrors>(errorCode, "", ss.str(),
- IsRetryableHttpResponseCode(responseCode));
- }
- else
- {
- assert(httpResponse->GetResponseCode() != HttpResponseCode::OK);
- error = GetErrorMarshaller()->Marshall(*httpResponse);
+ Aws::String awsLambdaFunctionName = Aws::Environment::GetEnv(AWS_LAMBDA_FUNCTION_NAME);
+ if(awsLambdaFunctionName.empty()) {
+ return;
}
-
- error.SetResponseHeaders(httpResponse->GetHeaders());
- error.SetResponseCode(httpResponse->GetResponseCode());
- error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
- AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error);
- return error;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signer, errorMarshaller)
-{
-}
-
-AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration,
- const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
- const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
- BASECLASS(configuration, signerProvider, errorMarshaller)
-{
-}
-
-XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri,
- const Aws::AmazonWebServiceRequest& request,
- Http::HttpMethod method,
- const char* signerName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
-{
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return XmlOutcome(std::move(httpOutcome));
+ Aws::String xAmznTraceIdVal = Aws::Environment::GetEnv(X_AMZN_TRACE_ID);
+ if(xAmznTraceIdVal.empty()) {
+ return;
}
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ // Escape all non-printable ASCII characters by percent encoding
+ Aws::OStringStream xAmznTraceIdValEncodedStr;
+ for(const char ch : xAmznTraceIdVal)
{
- XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody());
-
- if (!xmlDoc.WasParseSuccessful())
+ if (ch >= 0x20 && ch <= 0x7e) // ascii chars [32-126] or [' ' to '~'] are not escaped
{
- AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str());
- return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false);
+ xAmznTraceIdValEncodedStr << ch;
}
-
- return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc),
- httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode()));
- }
-
- return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders()));
-}
-
-XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri,
- Http::HttpMethod method,
- const char* signerName,
- const char* requestName,
- const char* signerRegionOverride,
- const char* signerServiceNameOverride) const
-{
- HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
- if (!httpOutcome.IsSuccess())
- {
- return XmlOutcome(std::move(httpOutcome));
- }
-
- if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
- {
- return XmlOutcome(AmazonWebServiceResult<XmlDocument>(
- XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()),
- httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode()));
- }
-
- return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders()));
-}
-
-AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const
-{
- AWSError<CoreErrors> error;
- if (httpResponse->HasClientError())
- {
- bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
- error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
- }
- else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
- {
- auto responseCode = httpResponse->GetResponseCode();
- auto errorCode = GuessBodylessErrorType(responseCode);
-
- Aws::StringStream ss;
- ss << "No response body.";
- error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode));
- }
- else
- {
- assert(httpResponse->GetResponseCode() != HttpResponseCode::OK);
-
- // When trying to build an AWS Error from a response which is an FStream, we need to rewind the
- // file pointer back to the beginning in order to correctly read the input using the XML string iterator
- if ((httpResponse->GetResponseBody().tellp() > 0)
- && (httpResponse->GetResponseBody().tellg() > 0))
+ else
{
- httpResponse->GetResponseBody().seekg(0);
+ // A percent-encoded octet is encoded as a character triplet
+ xAmznTraceIdValEncodedStr << '%' // consisting of the percent character "%"
+ << std::hex << std::setfill('0') << std::setw(2) << std::uppercase
+ << (size_t) ch //followed by the two hexadecimal digits representing that octet's numeric value
+ << std::dec << std::setfill(' ') << std::setw(0) << std::nouppercase;
}
-
- error = GetErrorMarshaller()->Marshall(*httpResponse);
}
+ xAmznTraceIdVal = xAmznTraceIdValEncodedStr.str();
- error.SetResponseHeaders(httpResponse->GetHeaders());
- error.SetResponseCode(httpResponse->GetResponseCode());
- error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
- AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error);
- return error;
+ ioRequest->SetHeaderValue(Aws::Http::X_AMZN_TRACE_ID_HEADER, xAmznTraceIdVal);
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp
index f5fa676f986..a905dddb5cf 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp
@@ -23,6 +23,7 @@ AWS_CORE_API extern const char MESSAGE_LOWER_CASE[] = "message";
AWS_CORE_API extern const char MESSAGE_CAMEL_CASE[] = "Message";
AWS_CORE_API extern const char ERROR_TYPE_HEADER[] = "x-amzn-ErrorType";
AWS_CORE_API extern const char REQUEST_ID_HEADER[] = "x-amzn-RequestId";
+AWS_CORE_API extern const char QUERY_ERROR_HEADER[] = "x-amzn-query-error";
AWS_CORE_API extern const char TYPE[] = "__type";
AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const
@@ -50,6 +51,24 @@ AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse
error = FindErrorByHttpResponseCode(httpResponse.GetResponseCode());
error.SetMessage(message);
}
+
+ if (httpResponse.HasHeader(QUERY_ERROR_HEADER))
+ {
+ auto errorCodeString = httpResponse.GetHeader(QUERY_ERROR_HEADER);
+ auto locationOfSemicolon = errorCodeString.find_first_of(';');
+ Aws::String errorCode;
+
+ if (locationOfSemicolon != Aws::String::npos)
+ {
+ errorCode = errorCodeString.substr(0, locationOfSemicolon);
+ }
+ else
+ {
+ errorCode = errorCodeString;
+ }
+
+ error.SetExceptionName(errorCode);
+ }
}
else
{
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp
new file mode 100644
index 00000000000..b3e19d99778
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp
@@ -0,0 +1,212 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/AWSJsonClient.h>
+#include <aws/core/AmazonWebServiceRequest.h>
+#include <aws/core/auth/AWSAuthSignerProvider.h>
+#include <aws/core/client/AWSError.h>
+#include <aws/core/client/AWSErrorMarshaller.h>
+#include <aws/core/client/ClientConfiguration.h>
+#include <aws/core/client/CoreErrors.h>
+#include <aws/core/client/RetryStrategy.h>
+#include <aws/core/http/HttpClient.h>
+#include <aws/core/http/HttpResponse.h>
+#include <aws/core/http/URI.h>
+#include <aws/core/utils/json/JsonSerializer.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/xml/XmlSerializer.h>
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/event/EventStream.h>
+#include <aws/core/utils/UUID.h>
+#include <aws/core/monitoring/MonitoringManager.h>
+
+#include <cassert>
+
+
+using namespace Aws;
+using namespace Aws::Client;
+using namespace Aws::Http;
+using namespace Aws::Utils;
+using namespace Aws::Utils::Json;
+
+static const char AWS_JSON_CLIENT_LOG_TAG[] = "AWSJsonClient";
+
+AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
+ const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
+ const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
+ BASECLASS(configuration, signer, errorMarshaller)
+{
+}
+
+AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration,
+ const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
+ const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
+ BASECLASS(configuration, signerProvider, errorMarshaller)
+{
+}
+
+JsonOutcome AWSJsonClient::MakeRequest(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Endpoint::AWSEndpoint& endpoint,
+ Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const char* signerName /* = Aws::Auth::NULL_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+ return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
+}
+
+JsonOutcome AWSJsonClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint,
+ Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const char* signerName /* = Aws::Auth::NULL_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+ return MakeRequest(uri, method, signerName, signerRegionOverride, signerServiceNameOverride);
+}
+
+JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
+ const Aws::AmazonWebServiceRequest& request,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
+ if (!httpOutcome.IsSuccess())
+ {
+ return JsonOutcome(std::move(httpOutcome));
+ }
+
+ if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()),
+ httpOutcome.GetResult()->GetHeaders(),
+ httpOutcome.GetResult()->GetResponseCode()));
+
+ else
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+}
+
+JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* requestName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
+ if (!httpOutcome.IsSuccess())
+ {
+ return JsonOutcome(std::move(httpOutcome));
+ }
+
+ if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ {
+ JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
+ if (!jsonValue.WasParseSuccessful())
+ {
+ return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
+ }
+
+ //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
+ httpOutcome.GetResult()->GetHeaders(),
+ httpOutcome.GetResult()->GetResponseCode()));
+ }
+
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+}
+
+JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const
+{
+ // request is assumed to be signed
+ std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request);
+
+ if (DoesResponseGenerateError(httpResponse))
+ {
+ AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response");
+ auto error = BuildAWSError(httpResponse);
+ return JsonOutcome(std::move(error));
+ }
+
+ AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned successful response.");
+
+ HttpResponseOutcome httpOutcome(std::move(httpResponse));
+
+ if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ {
+ JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody());
+ if (!jsonValue.WasParseSuccessful())
+ {
+ return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false));
+ }
+
+ //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint.
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue),
+ httpOutcome.GetResult()->GetHeaders(),
+ httpOutcome.GetResult()->GetResponseCode()));
+ }
+
+ return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders()));
+}
+
+AWSError<CoreErrors> AWSJsonClient::BuildAWSError(
+ const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const
+{
+ AWSError<CoreErrors> error;
+ if (httpResponse->HasClientError())
+ {
+ bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
+ error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
+ }
+ else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
+ {
+ auto responseCode = httpResponse->GetResponseCode();
+ auto errorCode = AWSClient::GuessBodylessErrorType(responseCode);
+
+ Aws::StringStream ss;
+ ss << "No response body.";
+ error = AWSError<CoreErrors>(errorCode, "", ss.str(),
+ IsRetryableHttpResponseCode(responseCode));
+ }
+ else
+ {
+ assert(httpResponse->GetResponseCode() != HttpResponseCode::OK);
+ error = GetErrorMarshaller()->Marshall(*httpResponse);
+ }
+
+ error.SetResponseHeaders(httpResponse->GetHeaders());
+ error.SetResponseCode(httpResponse->GetResponseCode());
+ error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
+ AWS_LOGSTREAM_ERROR(AWS_JSON_CLIENT_LOG_TAG, error);
+ return error;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp
new file mode 100644
index 00000000000..a0bc8088384
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp
@@ -0,0 +1,236 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/AWSUrlPresigner.h>
+#include <aws/core/client/AWSClient.h>
+#include <aws/core/http/HttpClientFactory.h>
+
+namespace Aws
+{
+namespace Client
+{
+
+using HttpRequest = Http::HttpRequest;
+using HttpMethod = Http::HttpMethod;
+using URI = Http::URI;
+
+
+AWSUrlPresigner::AWSUrlPresigner(const AWSClient& client)
+ : m_awsClient(client)
+{}
+
+
+Aws::Client::AWSAuthSigner* AWSUrlPresigner::GetSignerByName(const char* name) const
+{
+ return m_awsClient.GetSignerByName(name);
+}
+
+std::shared_ptr<Aws::Http::HttpRequest>
+ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const Aws::Http::QueryStringParameterCollection& extraParams)
+{
+ Aws::Http::URI uriCopy = uri;
+ request.PutToPresignedUrl(uriCopy);
+ std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uriCopy, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
+
+ for (auto& param : extraParams)
+ {
+ httpRequest->AddQueryStringParameter(param.first.c_str(), param.second);
+ }
+
+ return httpRequest;
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri,
+ HttpMethod method,
+ long long expirationInSeconds) const
+{
+ const char* regionOverride = nullptr;
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri,
+ HttpMethod method,
+ const Aws::Http::HeaderValueCollection& customizedHeaders,
+ long long expirationInSeconds) const
+{
+ const char* regionOverride = nullptr;
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri,
+ HttpMethod method,
+ const char* regionOverride,
+ long long expirationInSeconds) const
+{
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri,
+ HttpMethod method,
+ const char* regionOverride,
+ const Aws::Http::HeaderValueCollection& customizedHeaders,
+ long long expirationInSeconds) const
+{
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const char* serviceNameOverride,
+ long long expirationInSeconds) const
+{
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const char* serviceNameOverride,
+ const Aws::Http::HeaderValueCollection& customizedHeaders,
+ long long expirationInSeconds) const
+{
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const char* serviceNameOverride,
+ const char* signerName,
+ long long expirationInSeconds) const
+{
+ const Aws::Http::HeaderValueCollection& customizedHeaders = {};
+ return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* region,
+ const char* serviceName,
+ const char* signerName,
+ const Aws::Http::HeaderValueCollection& customizedHeaders,
+ long long expirationInSeconds) const
+{
+ /* a real method implementation */
+ if (!signerName) {
+ signerName = Aws::Auth::SIGV4_SIGNER;
+ }
+ std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
+ for (const auto& it: customizedHeaders)
+ {
+ request->SetHeaderValue(it.first.c_str(), it.second);
+ }
+ auto signer = GetSignerByName(signerName);
+ if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds))
+ {
+ return request->GetURIString();
+ }
+
+ return {};
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Endpoint::AWSEndpoint& endpoint,
+ Aws::Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const Aws::Http::HeaderValueCollection& customizedHeaders /* = {} */,
+ uint64_t expirationInSeconds /* = 0 */,
+ const char* signerName /* = Aws::Auth::SIGV4_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+
+ return GeneratePresignedUrl(uri, method, signerRegionOverride, signerServiceNameOverride, signerName, customizedHeaders, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const Aws::Http::QueryStringParameterCollection& extraParams,
+ long long expirationInSeconds) const
+{
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+
+ return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const char* serviceNameOverride,
+ const char* signerName,
+ const Aws::Http::QueryStringParameterCollection& extraParams,
+ long long expirationInSeconds) const
+{
+ /* a real method implementation */
+ if (!signerName) {
+ signerName = Aws::Auth::SIGV4_SIGNER;
+ }
+ std::shared_ptr<HttpRequest> httpRequest =
+ ConvertToRequestForPresigning(request, uri, method, extraParams);
+ auto signer = GetSignerByName(signerName);
+ if (signer->PresignRequest(*httpRequest, regionOverride, serviceNameOverride, expirationInSeconds))
+ {
+ return httpRequest->GetURIString();
+ }
+
+ return {};
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const char* regionOverride,
+ const char* serviceNameOverride,
+ const Aws::Http::QueryStringParameterCollection& extraParams,
+ long long expirationInSeconds) const
+{
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+ return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds);
+}
+
+Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Http::URI& uri,
+ Aws::Http::HttpMethod method,
+ const Aws::Http::QueryStringParameterCollection& extraParams,
+ long long expirationInSeconds) const
+{
+ const char* regionOverride = nullptr;
+ const char* serviceNameOverride = nullptr;
+ const char* signerName = Aws::Auth::SIGV4_SIGNER;
+
+ return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds);
+}
+
+} // namespace Client
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp
new file mode 100644
index 00000000000..129595b9179
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp
@@ -0,0 +1,180 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/AWSXmlClient.h>
+#include <aws/core/AmazonWebServiceRequest.h>
+#include <aws/core/auth/AWSAuthSignerProvider.h>
+#include <aws/core/client/AWSError.h>
+#include <aws/core/client/AWSErrorMarshaller.h>
+#include <aws/core/client/ClientConfiguration.h>
+#include <aws/core/client/CoreErrors.h>
+#include <aws/core/client/RetryStrategy.h>
+#include <aws/core/http/HttpClient.h>
+#include <aws/core/http/HttpResponse.h>
+#include <aws/core/http/URI.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/xml/XmlSerializer.h>
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/event/EventStream.h>
+#include <aws/core/utils/UUID.h>
+
+using namespace Aws;
+using namespace Aws::Client;
+using namespace Aws::Http;
+using namespace Aws::Utils;
+using namespace Aws::Utils::Xml;
+
+static const char AWS_XML_CLIENT_LOG_TAG[] = "AWSXmlClient";
+
+AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration,
+ const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer,
+ const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
+ BASECLASS(configuration, signer, errorMarshaller)
+{
+}
+
+AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration,
+ const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider,
+ const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) :
+ BASECLASS(configuration, signerProvider, errorMarshaller)
+{
+}
+
+XmlOutcome AWSXMLClient::MakeRequest(const Aws::AmazonWebServiceRequest& request,
+ const Aws::Endpoint::AWSEndpoint& endpoint,
+ Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const char* signerName /* = Aws::Auth::NULL_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+ return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride);
+}
+
+XmlOutcome AWSXMLClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint,
+ const char* requestName /* = "" */,
+ Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */,
+ const char* signerName /* = Aws::Auth::NULL_SIGNER */,
+ const char* signerRegionOverride /* = nullptr */,
+ const char* signerServiceNameOverride /* = nullptr */) const
+{
+ const Aws::Http::URI& uri = endpoint.GetURI();
+ if (endpoint.GetAttributes()) {
+ signerName = endpoint.GetAttributes()->authScheme.GetName().c_str();
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) {
+ signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str();
+ }
+ if (endpoint.GetAttributes()->authScheme.GetSigningName()) {
+ signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str();
+ }
+ }
+ return MakeRequest(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride);
+}
+
+XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri,
+ const Aws::AmazonWebServiceRequest& request,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride));
+ if (!httpOutcome.IsSuccess())
+ {
+ return XmlOutcome(std::move(httpOutcome));
+ }
+
+ if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ {
+ XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody());
+
+ if (!xmlDoc.WasParseSuccessful())
+ {
+ AWS_LOGSTREAM_ERROR(AWS_XML_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str());
+ return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false);
+ }
+
+ return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc),
+ httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode()));
+ }
+
+ return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders()));
+}
+
+XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri,
+ Http::HttpMethod method,
+ const char* signerName,
+ const char* requestName,
+ const char* signerRegionOverride,
+ const char* signerServiceNameOverride) const
+{
+ HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride));
+ if (!httpOutcome.IsSuccess())
+ {
+ return XmlOutcome(std::move(httpOutcome));
+ }
+
+ if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0)
+ {
+ return XmlOutcome(AmazonWebServiceResult<XmlDocument>(
+ XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()),
+ httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode()));
+ }
+
+ return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders()));
+}
+
+AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const
+{
+ AWSError<CoreErrors> error;
+ if (httpResponse->HasClientError())
+ {
+ bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false;
+ error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable);
+ }
+ else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1)
+ {
+ auto responseCode = httpResponse->GetResponseCode();
+ auto errorCode = AWSClient::GuessBodylessErrorType(responseCode);
+
+ Aws::StringStream ss;
+ ss << "No response body.";
+ error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode));
+ }
+ else
+ {
+ // When trying to build an AWS Error from a response which is an FStream, we need to rewind the
+ // file pointer back to the beginning in order to correctly read the input using the XML string iterator
+ if ((httpResponse->GetResponseBody().tellp() > 0)
+ && (httpResponse->GetResponseBody().tellg() > 0))
+ {
+ httpResponse->GetResponseBody().seekg(0);
+ }
+
+ error = GetErrorMarshaller()->Marshall(*httpResponse);
+ }
+
+ error.SetResponseHeaders(httpResponse->GetHeaders());
+ error.SetResponseCode(httpResponse->GetResponseCode());
+ error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost());
+ AWS_LOGSTREAM_ERROR(AWS_XML_CLIENT_LOG_TAG, error);
+ return error;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp
new file mode 100644
index 00000000000..0907b81137e
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp
@@ -0,0 +1,228 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/AdaptiveRetryStrategy.h>
+
+#include <aws/core/client/AWSError.h>
+#include <aws/core/client/CoreErrors.h>
+#include <aws/core/utils/memory/stl/AWSSet.h>
+
+#include <cmath>
+#include <thread>
+
+using namespace Aws::Utils::Threading;
+
+namespace Aws
+{
+ namespace Client
+ {
+ static const double MIN_FILL_RATE = 0.5;
+ static const double MIN_CAPACITY = 1;
+
+ static const double SMOOTH = 0.8;
+ static const double BETA = 0.7;
+ static const double SCALE_CONSTANT = 0.4;
+
+ // A static list containing all service exception names classified as throttled.
+ static const char* THROTTLING_EXCEPTIONS[] {
+ "Throttling", "ThrottlingException", "ThrottledException", "RequestThrottledException",
+ "TooManyRequestsException", "ProvisionedThroughputExceededException", "TransactionInProgressException",
+ "RequestLimitExceeded", "BandwidthLimitExceeded", "LimitExceededException", "RequestThrottled",
+ "SlowDown", "PriorRequestNotComplete", "EC2ThrottledException"};
+ static const size_t THROTTLING_EXCEPTIONS_SZ = sizeof(THROTTLING_EXCEPTIONS) / sizeof(THROTTLING_EXCEPTIONS[0]);
+
+
+ // C-tor for unit testing
+ RetryTokenBucket::RetryTokenBucket(double fillRate, double maxCapacity, double currentCapacity,
+ const Aws::Utils::DateTime& lastTimestamp, double measuredTxRate, double lastTxRateBucket,
+ size_t requestCount, bool enabled, double lastMaxRate, const Aws::Utils::DateTime& lastThrottleTime)
+ :
+ m_fillRate(fillRate), m_maxCapacity(maxCapacity), m_currentCapacity(currentCapacity),
+ m_lastTimestamp(lastTimestamp), m_measuredTxRate(measuredTxRate),
+ m_lastTxRateBucket(lastTxRateBucket), m_requestCount(requestCount), m_enabled(enabled),
+ m_lastMaxRate(lastMaxRate), m_lastThrottleTime(lastThrottleTime)
+ {}
+
+ bool RetryTokenBucket::Acquire(size_t amount, bool fastFail)
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+ if (!m_enabled)
+ {
+ return true;
+ }
+ Refill();
+ bool notEnough = amount > m_currentCapacity;
+ if (notEnough && fastFail) {
+ return false;
+ }
+ // If all the tokens couldn't be acquired immediately, wait enough
+ // time to fill the remainder.
+ if (notEnough) {
+ std::chrono::duration<double> waitTime((amount - m_currentCapacity) / m_fillRate);
+ std::this_thread::sleep_for(waitTime);
+ Refill();
+ }
+ m_currentCapacity -= amount;
+ return true;
+ }
+
+ void RetryTokenBucket::Refill(const Aws::Utils::DateTime& now)
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+
+ if (0 == m_lastTimestamp.Millis()) {
+ m_lastTimestamp = now;
+ return;
+ }
+
+ double fillAmount = (std::abs(now.Millis() - m_lastTimestamp.Millis()))/1000.0 * m_fillRate;
+ m_currentCapacity = (std::min)(m_maxCapacity, m_currentCapacity + fillAmount);
+ m_lastTimestamp = now;
+ }
+
+ void RetryTokenBucket::UpdateRate(double newRps, const Aws::Utils::DateTime& now)
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+
+ Refill(now);
+ m_fillRate = (std::max)(newRps, MIN_FILL_RATE);
+ m_maxCapacity = (std::max)(newRps, MIN_CAPACITY);
+ m_currentCapacity = (std::min)(m_currentCapacity, m_maxCapacity);
+ }
+
+ void RetryTokenBucket::UpdateMeasuredRate(const Aws::Utils::DateTime& now)
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+
+ double t = now.Millis() / 1000.0;
+ double timeBucket = floor(t * 2.0) / 2.0;
+ m_requestCount += 1;
+ if (timeBucket > m_lastTxRateBucket) {
+ double currentRate = m_requestCount / (timeBucket - m_lastTxRateBucket);
+ m_measuredTxRate = (currentRate * SMOOTH) + (m_measuredTxRate * (1 - SMOOTH));
+ m_requestCount = 0;
+ m_lastTxRateBucket = timeBucket;
+ }
+ }
+
+ void RetryTokenBucket::UpdateClientSendingRate(bool isThrottlingResponse, const Aws::Utils::DateTime& now)
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+
+ UpdateMeasuredRate(now);
+
+ double calculatedRate = 0.0;
+ if (isThrottlingResponse)
+ {
+ double rateToUse = m_measuredTxRate;
+ if (m_enabled)
+ rateToUse = (std::min)(rateToUse, m_fillRate);
+
+ m_lastMaxRate = rateToUse;
+ m_lastThrottleTime = now;
+
+ calculatedRate = CUBICThrottle(rateToUse);
+ Enable();
+ }
+ else
+ {
+ double timeWindow = CalculateTimeWindow();
+ calculatedRate = CUBICSuccess(now, timeWindow);
+ }
+
+ double newRate = (std::min)(calculatedRate, 2.0 * m_measuredTxRate);
+ UpdateRate(newRate, now);
+ }
+
+ void RetryTokenBucket::Enable()
+ {
+ std::lock_guard<std::recursive_mutex> locker(m_mutex);
+ m_enabled = true;
+ }
+
+ double RetryTokenBucket::CalculateTimeWindow() const
+ {
+ return pow(((m_lastMaxRate * (1.0 - BETA)) / SCALE_CONSTANT), (1.0 / 3));
+ }
+
+ double RetryTokenBucket::CUBICSuccess(const Aws::Utils::DateTime& timestamp, const double timeWindow) const
+ {
+ double dt = (timestamp.Millis() - m_lastThrottleTime.Millis()) / 1000.0;
+ double calculatedRate = SCALE_CONSTANT * pow(dt - timeWindow, 3.0) + m_lastMaxRate;
+ return calculatedRate;
+ }
+
+ double RetryTokenBucket::CUBICThrottle(const double rateToUse) const
+ {
+ double calculatedRate = rateToUse * BETA;
+ return calculatedRate;
+ }
+
+
+ AdaptiveRetryStrategy::AdaptiveRetryStrategy(long maxAttempts) :
+ StandardRetryStrategy(maxAttempts)
+ {}
+
+ AdaptiveRetryStrategy::AdaptiveRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts) :
+ StandardRetryStrategy(retryQuotaContainer, maxAttempts)
+ {}
+
+ bool AdaptiveRetryStrategy::HasSendToken()
+ {
+ return m_retryTokenBucket.Acquire(1, m_fastFail);
+ }
+
+ void AdaptiveRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome)
+ {
+ if (httpResponseOutcome.IsSuccess())
+ {
+ m_retryQuotaContainer->ReleaseRetryQuota(Aws::Client::NO_RETRY_INCREMENT);
+ m_retryTokenBucket.UpdateClientSendingRate(false);
+ }
+ else
+ {
+ m_retryTokenBucket.UpdateClientSendingRate(IsThrottlingResponse(httpResponseOutcome));
+ }
+ }
+
+ void AdaptiveRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome, const AWSError<CoreErrors>& lastError)
+ {
+ if (httpResponseOutcome.IsSuccess())
+ {
+ m_retryQuotaContainer->ReleaseRetryQuota(lastError);
+ m_retryTokenBucket.UpdateClientSendingRate(false);
+ }
+ else
+ {
+ m_retryTokenBucket.UpdateClientSendingRate(IsThrottlingResponse(httpResponseOutcome));
+ }
+ }
+
+ bool AdaptiveRetryStrategy::IsThrottlingResponse(const HttpResponseOutcome& httpResponseOutcome)
+ {
+ if(httpResponseOutcome.IsSuccess())
+ return false;
+
+ const AWSError<CoreErrors>& error = httpResponseOutcome.GetError();
+ const Aws::Client::CoreErrors enumValue = error.GetErrorType();
+ switch(enumValue)
+ {
+ case Aws::Client::CoreErrors::THROTTLING:
+ case Aws::Client::CoreErrors::SLOW_DOWN:
+ return true;
+ default:
+ break;
+ }
+
+ if(std::find(THROTTLING_EXCEPTIONS,
+ THROTTLING_EXCEPTIONS + THROTTLING_EXCEPTIONS_SZ, error.GetExceptionName()) != THROTTLING_EXCEPTIONS + THROTTLING_EXCEPTIONS_SZ)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp
index e517379a779..647c6e3f49a 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp
@@ -4,8 +4,10 @@
*/
#include <aws/core/client/ClientConfiguration.h>
+#include <aws/core/config/defaults/ClientConfigurationDefaults.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/client/DefaultRetryStrategy.h>
+#include <aws/core/client/AdaptiveRetryStrategy.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/platform/OSVersionInfo.h>
#include <aws/core/utils/memory/AWSMemory.h>
@@ -26,43 +28,217 @@ namespace Client
{
static const char* CLIENT_CONFIG_TAG = "ClientConfiguration";
+static const char* USE_REQUEST_COMPRESSION_ENV_VAR = "USE_REQUEST_COMPRESSION";
+static const char* USE_REQUEST_COMPRESSION_CONFIG_VAR = "use_request_compression";
+static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR = "REQUEST_MIN_COMPRESSION_SIZE_BYTES";
+static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR = "request_min_compression_size_bytes";
-AWS_CORE_API Aws::String ComputeUserAgentString()
+Aws::String ComputeUserAgentString()
{
Aws::StringStream ss;
- ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString()
- << " " << Version::GetCompilerVersionString();
+ ss << "aws-sdk-cpp/" << Version::GetVersionString() << " "
+#if defined(AWS_USER_AGENT_CUSTOMIZATION)
+#define XSTR(V) STR(V)
+#define STR(V) #V
+ << XSTR(AWS_USER_AGENT_CUSTOMIZATION) << " "
+#undef STR
+#undef XSTR
+#endif
+ << Aws::OSVersionInfo::ComputeOSVersionString() << " "
+ << Version::GetCompilerVersionString();
return ss.str();
}
-ClientConfiguration::ClientConfiguration() :
- scheme(Aws::Http::Scheme::HTTPS),
- useDualStack(false),
- maxConnections(25),
- httpRequestTimeoutMs(0),
- requestTimeoutMs(3000),
- connectTimeoutMs(1000),
- enableTcpKeepAlive(true),
- tcpKeepAliveIntervalMs(30000),
- lowSpeedLimit(1),
- proxyScheme(Aws::Http::Scheme::HTTP),
- proxyPort(0),
- executor(Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG)),
- verifySSL(true),
- writeRateLimiter(nullptr),
- readRateLimiter(nullptr),
- httpLibOverride(Aws::Http::TransferLibType::DEFAULT_CLIENT),
- followRedirects(FollowRedirectsPolicy::DEFAULT),
- disableExpectHeader(false),
- enableClockSkewAdjustment(true),
- enableHostPrefixInjection(true),
- enableEndpointDiscovery(false),
- profileName(Aws::Auth::GetConfigProfileName())
+void setLegacyClientConfigurationParameters(ClientConfiguration& clientConfig)
{
- AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << profileName << "] if not specified by users.");
+ clientConfig.scheme = Aws::Http::Scheme::HTTPS;
+ clientConfig.useDualStack = false;
+ clientConfig.useFIPS = false;
+ clientConfig.maxConnections = 25;
+ clientConfig.httpRequestTimeoutMs = 0;
+ clientConfig.requestTimeoutMs = 3000;
+ clientConfig.connectTimeoutMs = 1000;
+ clientConfig.enableTcpKeepAlive = true;
+ clientConfig.tcpKeepAliveIntervalMs = 30000;
+ clientConfig.lowSpeedLimit = 1;
+ clientConfig.proxyScheme = Aws::Http::Scheme::HTTP;
+ clientConfig.proxyPort = 0;
+ clientConfig.executor = Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG);
+ clientConfig.verifySSL = true;
+ clientConfig.writeRateLimiter = nullptr;
+ clientConfig.readRateLimiter = nullptr;
+ clientConfig.httpLibOverride = Aws::Http::TransferLibType::DEFAULT_CLIENT;
+ clientConfig.followRedirects = FollowRedirectsPolicy::DEFAULT;
+ clientConfig.disableExpectHeader = false;
+ clientConfig.enableClockSkewAdjustment = true;
+ clientConfig.enableHostPrefixInjection = true;
+ clientConfig.profileName = Aws::Auth::GetConfigProfileName();
- // Initialize Retry Strategy
- int maxAttempts;
+ Aws::String useCompressionConfig = clientConfig.LoadConfigFromEnvOrProfile(
+ USE_REQUEST_COMPRESSION_ENV_VAR,
+ Aws::Auth::GetConfigProfileName(),
+ USE_REQUEST_COMPRESSION_CONFIG_VAR,
+ {"ENABLE", "DISABLE", "enable", "disable"},
+ "ENABLE"
+ );
+
+ if (Aws::Utils::StringUtils::ToLower(useCompressionConfig.c_str()) == "disable") {
+ clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::DISABLE;
+ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression disabled");
+ } else {
+ //Using default to true for forward compatibility in case new config is added but SDK is not updated.
+ clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::ENABLE;
+ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression enabled");
+ }
+
+ // Getting min request compression length
+ Aws::String minRequestCompressionString = Aws::Environment::GetEnv(REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR);
+ if (minRequestCompressionString.empty())
+ {
+ minRequestCompressionString = Aws::Config::GetCachedConfigValue(REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR);
+ }
+ if (!minRequestCompressionString.empty()) {
+ clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes = static_cast<int>(Aws::Utils::StringUtils::ConvertToInt32(minRequestCompressionString.c_str()));
+ if (clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes > 10485760) {
+ AWS_LOGSTREAM_ERROR(CLIENT_CONFIG_TAG, "ClientConfiguration for MinReqCompression is unsupported, received: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes);
+ }
+ }
+ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use MinReqCompression: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes);
+
+ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << clientConfig.profileName << "] if not specified by users.");
+
+ // Automatically determine the AWS region from environment variables, configuration file and EC2 metadata.
+ clientConfig.region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION");
+ if (!clientConfig.region.empty())
+ {
+ return;
+ }
+
+ clientConfig.region = Aws::Environment::GetEnv("AWS_REGION");
+ if (!clientConfig.region.empty())
+ {
+ return;
+ }
+
+ clientConfig.region = Aws::Config::GetCachedConfigValue("region");
+ if (!clientConfig.region.empty())
+ {
+ return;
+ }
+
+ // Set the endpoint to interact with EC2 instance's metadata service
+ Aws::String ec2MetadataServiceEndpoint = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT");
+ if (! ec2MetadataServiceEndpoint.empty())
+ {
+ //By default we use the IPv4 default metadata service address
+ auto client = Aws::Internal::GetEC2MetadataClient();
+ if (client != nullptr)
+ {
+ client->SetEndpoint(ec2MetadataServiceEndpoint);
+ }
+ }
+}
+
+ClientConfiguration::ClientConfiguration()
+{
+ this->disableIMDS = false;
+ setLegacyClientConfigurationParameters(*this);
+ retryStrategy = InitRetryStrategy();
+
+ if (!this->disableIMDS &&
+ region.empty() &&
+ Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
+ {
+ auto client = Aws::Internal::GetEC2MetadataClient();
+ if (client)
+ {
+ region = client->GetCurrentRegion();
+ }
+ }
+ if (!region.empty())
+ {
+ return;
+ }
+ region = Aws::String(Aws::Region::US_EAST_1);
+}
+
+ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisableIMDS)
+{
+ this->disableIMDS = shouldDisableIMDS;
+ setLegacyClientConfigurationParameters(*this);
+ // Call EC2 Instance Metadata service only once
+ Aws::String ec2MetadataRegion;
+ bool hasEc2MetadataRegion = false;
+ if (!this->disableIMDS &&
+ region.empty() &&
+ Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") {
+ auto client = Aws::Internal::GetEC2MetadataClient();
+ if (client)
+ {
+ ec2MetadataRegion = client->GetCurrentRegion();
+ hasEc2MetadataRegion = true;
+ region = ec2MetadataRegion;
+ }
+ }
+
+ if(region.empty())
+ {
+ region = Aws::String(Aws::Region::US_EAST_1);
+ }
+
+ if (profile && Aws::Config::HasCachedConfigProfile(profile)) {
+ this->profileName = Aws::String(profile);
+ AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG,
+ "Use user specified profile: [" << this->profileName << "] for ClientConfiguration.");
+ auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion();
+ if (!tmpRegion.empty()) {
+ region = tmpRegion;
+ }
+
+ Aws::String profileDefaultsMode = Aws::Config::GetCachedConfigProfile(this->profileName).GetDefaultsMode();
+ Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, profileDefaultsMode,
+ hasEc2MetadataRegion, ec2MetadataRegion);
+ return;
+ }
+ if (!retryStrategy)
+ {
+ retryStrategy = InitRetryStrategy();
+ }
+
+ AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one.");
+}
+
+ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char* defaultMode, bool shouldDisableIMDS)
+{
+ this->disableIMDS = shouldDisableIMDS;
+ setLegacyClientConfigurationParameters(*this);
+
+ // Call EC2 Instance Metadata service only once
+ Aws::String ec2MetadataRegion;
+ bool hasEc2MetadataRegion = false;
+ if (!this->disableIMDS &&
+ region.empty() &&
+ Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
+ {
+ auto client = Aws::Internal::GetEC2MetadataClient();
+ if (client)
+ {
+ ec2MetadataRegion = client->GetCurrentRegion();
+ hasEc2MetadataRegion = true;
+ region = ec2MetadataRegion;
+ }
+ }
+ if (region.empty())
+ {
+ region = Aws::String(Aws::Region::US_EAST_1);
+ }
+
+ Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion);
+}
+
+std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode)
+{
+ int maxAttempts = 0;
Aws::String maxAttemptsString = Aws::Environment::GetEnv("AWS_MAX_ATTEMPTS");
if (maxAttemptsString.empty())
{
@@ -83,15 +259,21 @@ ClientConfiguration::ClientConfiguration() :
}
}
- Aws::String retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE");
+ if (retryMode.empty())
+ {
+ retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE");
+ }
if (retryMode.empty())
{
retryMode = Aws::Config::GetCachedConfigValue("retry_mode");
}
+
+ std::shared_ptr<RetryStrategy> retryStrategy;
if (retryMode == "standard")
{
if (maxAttempts < 0)
{
+ // negative value set above force usage of default max attempts
retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG);
}
else
@@ -99,61 +281,55 @@ ClientConfiguration::ClientConfiguration() :
retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts);
}
}
- else
- {
- retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(CLIENT_CONFIG_TAG);
- }
-
- // Automatically determine the AWS region from environment variables, configuration file and EC2 metadata.
- region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION");
- if (!region.empty())
- {
- return;
- }
-
- region = Aws::Environment::GetEnv("AWS_REGION");
- if (!region.empty())
+ else if (retryMode == "adaptive")
{
- return;
- }
-
- region = Aws::Config::GetCachedConfigValue("region");
- if (!region.empty())
- {
- return;
- }
-
- if (Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
- {
- auto client = Aws::Internal::GetEC2MetadataClient();
- if (client)
+ if (maxAttempts < 0)
{
- region = client->GetCurrentRegion();
+ // negative value set above force usage of default max attempts
+ retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG);
+ }
+ else
+ {
+ retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts);
}
}
-
- if (!region.empty())
+ else
{
- return;
+ retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(CLIENT_CONFIG_TAG);
}
- region = Aws::String(Aws::Region::US_EAST_1);
+ return retryStrategy;
}
-ClientConfiguration::ClientConfiguration(const char* profile) : ClientConfiguration()
+Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey,
+ const Aws::String& profile,
+ const Aws::String& profileProperty,
+ const Aws::Vector<Aws::String>& allowedValues,
+ const Aws::String& defaultValue)
{
- if (profile && Aws::Config::HasCachedConfigProfile(profile))
- {
- this->profileName = Aws::String(profile);
- AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Use user specified profile: [" << this->profileName << "] for ClientConfiguration.");
- auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion();
- if (!tmpRegion.empty())
- {
- region = tmpRegion;
+ Aws::String option = Aws::Environment::GetEnv(envKey.c_str());
+ if (option.empty()) {
+ option = Aws::Config::GetCachedConfigValue(profile, profileProperty);
+ }
+ option = Aws::Utils::StringUtils::ToLower(option.c_str());
+ if (option.empty()) {
+ return defaultValue;
+ }
+
+ if (!allowedValues.empty() && std::find(allowedValues.cbegin(), allowedValues.cend(), option) == allowedValues.cend()) {
+ Aws::OStringStream expectedStr;
+ expectedStr << "[";
+ for(const auto& allowed : allowedValues) {
+ expectedStr << allowed << ";";
}
- return;
+ expectedStr << "]";
+
+ AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "Unrecognised value for " << envKey << ": " << option <<
+ ". Using default instead: " << defaultValue <<
+ ". Expected empty or one of: " << expectedStr.str());
+ option = defaultValue;
}
- AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one.");
+ return option;
}
} // namespace Client
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp
index 8c2c288dcd4..50a7f9308d8 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp
@@ -18,7 +18,8 @@ using namespace Aws::Http;
#pragma warning(disable : 4592)
#endif
-static Aws::UniquePtr<Aws::Map<Aws::String, AWSError<CoreErrors> > > s_CoreErrorsMapper(nullptr);
+using ErrorsMapperContainer = Aws::Map<Aws::String, AWSError<CoreErrors> >;
+static ErrorsMapperContainer* s_CoreErrorsMapper(nullptr);
#ifdef _MSC_VER
#pragma warning(pop)
@@ -30,7 +31,7 @@ void CoreErrorsMapper::InitCoreErrorsMapper()
{
return;
}
- s_CoreErrorsMapper = Aws::MakeUnique<Aws::Map<Aws::String, AWSError<CoreErrors> > >("InitCoreErrorsMapper");
+ s_CoreErrorsMapper = Aws::New<ErrorsMapperContainer>("InitCoreErrorsMapper");
s_CoreErrorsMapper->emplace("IncompleteSignature", AWSError<CoreErrors>(CoreErrors::INCOMPLETE_SIGNATURE, false));
s_CoreErrorsMapper->emplace("IncompleteSignatureException", AWSError<CoreErrors>(CoreErrors::INCOMPLETE_SIGNATURE, false));
@@ -92,10 +93,8 @@ void CoreErrorsMapper::InitCoreErrorsMapper()
void CoreErrorsMapper::CleanupCoreErrorsMapper()
{
- if (s_CoreErrorsMapper)
- {
- s_CoreErrorsMapper = nullptr;
- }
+ Aws::Delete(s_CoreErrorsMapper);
+ s_CoreErrorsMapper = nullptr;
}
AWSError<CoreErrors> CoreErrorsMapper::GetErrorForName(const char* errorName)
@@ -149,3 +148,12 @@ AWS_CORE_API AWSError<CoreErrors> CoreErrorsMapper::GetErrorForHttpResponseCode(
error.SetResponseCode(code);
return error;
}
+
+/**
+ * Overload ostream operator<< for CoreErrors enum class for a prettier output such as "103" and not "<67-00 00-00>"
+ */
+Aws::OStream& Aws::Client::operator<< (Aws::OStream& oStream, CoreErrors code)
+{
+ oStream << Aws::Utils::StringUtils::to_string(static_cast<typename std::underlying_type<HttpResponseCode>::type>(code));
+ return oStream;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp
index 7e57c79ffc4..405d7566cfb 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp
@@ -28,5 +28,5 @@ long DefaultRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErro
return 0;
}
- return (1 << attemptedRetries) * m_scaleFactor;
+ return (1UL << attemptedRetries) * m_scaleFactor;
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp
new file mode 100644
index 00000000000..f0a4e91d5ba
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp
@@ -0,0 +1,103 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/GenericClientConfiguration.h>
+#include <aws/core/platform/Environment.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+#include <aws/core/utils/threading/Executor.h>
+
+
+namespace Aws
+{
+namespace Client
+{
+template struct AWS_CORE_API GenericClientConfiguration<false>;
+
+bool IsEndpointDiscoveryEnabled(const Aws::String& endpointOverride, const Aws::String &profileName)
+{
+ bool enabled = true; // default value for AWS Services with enabled discovery trait
+ if (!endpointOverride.empty())
+ {
+ enabled = false;
+ }
+ else
+ {
+ static const char* AWS_ENABLE_ENDPOINT_DISCOVERY_ENV_KEY = "AWS_ENABLE_ENDPOINT_DISCOVERY";
+ static const char* AWS_ENABLE_ENDPOINT_DISCOVERY_PROFILE_KEY = "AWS_ENABLE_ENDPOINT_DISCOVERY";
+ static const char* AWS_ENABLE_ENDPOINT_ENABLED = "true";
+ static const char* AWS_ENABLE_ENDPOINT_DISABLED = "false";
+
+ Aws::String enableEndpointDiscovery = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_ENABLE_ENDPOINT_DISCOVERY_ENV_KEY,
+ profileName,
+ AWS_ENABLE_ENDPOINT_DISCOVERY_PROFILE_KEY,
+ {AWS_ENABLE_ENDPOINT_ENABLED, AWS_ENABLE_ENDPOINT_DISABLED},
+ AWS_ENABLE_ENDPOINT_ENABLED);
+
+ if (AWS_ENABLE_ENDPOINT_DISABLED == enableEndpointDiscovery)
+ {
+ // enabled by default unless explicitly disabled in ENV, profile config file, or programmatically later
+ enabled = false;
+ }
+ }
+ return enabled;
+}
+
+GenericClientConfiguration<true>::GenericClientConfiguration()
+ : ClientConfiguration(),
+ enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection),
+ enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery)
+{
+ enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName);
+ enableHostPrefixInjection = false; // disabled by default in the SDK
+}
+
+GenericClientConfiguration<true>::GenericClientConfiguration(const char* inputProfileName, bool shouldDisableIMDS)
+ : ClientConfiguration(inputProfileName, shouldDisableIMDS),
+ enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection),
+ enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery)
+{
+ enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName);
+ enableHostPrefixInjection = false; // disabled by default in the SDK
+}
+
+GenericClientConfiguration<true>::GenericClientConfiguration(bool useSmartDefaults, const char* inputDefaultMode, bool shouldDisableIMDS)
+ : ClientConfiguration(useSmartDefaults, inputDefaultMode, shouldDisableIMDS),
+ enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection),
+ enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery)
+{
+ enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName);
+ enableHostPrefixInjection = false; // disabled by default in the SDK
+}
+
+GenericClientConfiguration<true>::GenericClientConfiguration(const ClientConfiguration& config)
+ : ClientConfiguration(config),
+ enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection),
+ enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery)
+{
+ enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName);
+ enableHostPrefixInjection = false; // disabled by default in the SDK
+}
+
+GenericClientConfiguration<true>::GenericClientConfiguration(const GenericClientConfiguration<true>& other)
+ : ClientConfiguration(static_cast<ClientConfiguration>(other)),
+ enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection),
+ enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery)
+{
+ if (other.enableEndpointDiscovery) {
+ enableEndpointDiscovery = other.enableEndpointDiscovery.value();
+ }
+ enableHostPrefixInjection = other.enableHostPrefixInjection;
+}
+
+GenericClientConfiguration<true>& GenericClientConfiguration<true>::operator=(const GenericClientConfiguration<true>& other)
+{
+ if (this != &other) {
+ *static_cast<ClientConfiguration*>(this) = static_cast<ClientConfiguration>(other);
+ }
+ return *this;
+}
+
+} // namespace Client
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp
new file mode 100644
index 00000000000..e51a49049b7
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp
@@ -0,0 +1,336 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/client/RequestCompression.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+#include <algorithm>
+#include <aws/core/utils/memory/stl/AWSAllocator.h>
+
+#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION
+#include "zlib.h"
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#include <fcntl.h>
+#include <io.h>
+#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#define SET_BINARY_MODE(file)
+#endif // defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+// Defining zlib chunks to be 256k
+static const size_t ZLIB_CHUNK=263144;
+static const char AWS_REQUEST_COMPRESSION_ALLOCATION_TAG[] =
+ "RequestCompressionAlloc";
+#endif // ENABLED_ZLIB_REQUEST_COMPRESSION
+
+static const char AWS_REQUEST_COMPRESSION_LOG_TAG[] = "RequestCompression";
+
+Aws::String Aws::Client::GetCompressionAlgorithmId(const CompressionAlgorithm &algorithm)
+{
+ switch (algorithm)
+ {
+ case CompressionAlgorithm::GZIP:
+ return "gzip";
+ default:
+ return "";
+ }
+}
+
+#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION
+#ifdef USE_AWS_MEMORY_MANAGEMENT
+static const char* ZlibMemTag = "zlib";
+static const size_t offset = sizeof(size_t); // to make space for size of the array
+//Define custom memory allocation for zlib
+// if fail to allocate, return Z_NULL
+void* aws_zalloc(void * /* opaque */, unsigned items, unsigned size)
+{
+ unsigned sizeToAllocate = items*size;
+ size_t sizeToAllocateWithOffset = sizeToAllocate + offset;
+ if ((size != 0 && sizeToAllocate / size != items)
+ || (sizeToAllocateWithOffset <= sizeToAllocate ))
+ {
+ return Z_NULL;
+ }
+ char* newMem = reinterpret_cast<char*>(Aws::Malloc(ZlibMemTag, sizeToAllocateWithOffset));
+ if (newMem != nullptr) {
+ std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem);
+ *pointerToSize = size;
+ return reinterpret_cast<void*>(newMem + offset);
+ }
+ else
+ {
+ return Z_NULL;
+ }
+}
+
+void aws_zfree(void * /* opaque */, void * ptr)
+{
+ if(ptr)
+ {
+ char* shiftedMemory = reinterpret_cast<char*>(ptr);
+ Aws::Free(shiftedMemory - offset);
+ }
+}
+
+#endif // AWS_CUSTOM_MEMORY_MANAGEMENT
+#endif // ENABLED_ZLIB_REQUEST_COMPRESSION
+
+
+iostream_outcome Aws::Client::RequestCompression::compress(std::shared_ptr<Aws::IOStream> input,
+ const CompressionAlgorithm &algorithm) const
+{
+#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION
+ if (algorithm == CompressionAlgorithm::GZIP)
+ {
+ // calculating stream size
+ input->seekg(0, input->end);
+ size_t streamSize = input->tellg();
+ input->seekg(0, input->beg);
+
+ AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressing request of " << streamSize << " bytes.");
+
+ // Preparing output
+ std::shared_ptr<Aws::IOStream> output = Aws::MakeShared<Aws::StringStream>(AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!output)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate output while compressing")
+ return false;
+ }
+ // Prepare ZLIB to compress
+ int ret = Z_NULL;
+ int flush = Z_NO_FLUSH;
+ z_stream strm = {};
+ auto in = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!in)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate in buffer while compressing")
+ return false;
+ }
+
+ auto out = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!out)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate out buffer while compressing")
+ return false;
+ }
+
+ //Preparing allocators
+#ifdef USE_AWS_MEMORY_MANAGEMENT
+ strm.zalloc = (void *(*)(void *, unsigned, unsigned)) aws_zalloc;
+ strm.zfree = (void (*)(void *, void *)) aws_zfree;
+#else
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+#endif
+ strm.opaque = Z_NULL;
+
+ const int MAX_WINDOW_GZIP = 31;
+ const int DEFAULT_MEM_LEVEL_USAGE = 8;
+ ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WINDOW_GZIP, DEFAULT_MEM_LEVEL_USAGE, Z_DEFAULT_STRATEGY);
+ if(ret != Z_OK)
+ {
+ return false;
+ }
+
+ //Adding one to the stream size counter to account for the EOF marker.
+ streamSize++;
+ size_t toRead;
+ // Compress
+ do {
+ toRead = std::min(streamSize, ZLIB_CHUNK);
+ // Fill the buffer
+ if (! input->read(reinterpret_cast<char *>(in.get()), toRead))
+ {
+ if (input->eof())
+ {
+ //Last read need flush when exit loop
+ flush = Z_FINISH;
+ }
+ else {
+ AWS_LOGSTREAM_ERROR(
+ AWS_REQUEST_COMPRESSION_LOG_TAG,
+ "Uncompress request failed to read from stream");
+ return false;
+ }
+ }
+ streamSize -= toRead; //left to read
+ strm.avail_in = (flush == Z_FINISH)?toRead-1:toRead; //skip EOF if included
+ strm.next_in = in.get();
+ do
+ {
+ // Run deflate on buffers
+ strm.avail_out = ZLIB_CHUNK;
+ strm.next_out = out.get();
+
+ ret = deflate(&strm, flush);
+
+ // writing the output
+ assert(ZLIB_CHUNK >= strm.avail_out);
+ unsigned output_size = ZLIB_CHUNK - strm.avail_out;
+ if(! output->write(reinterpret_cast<char *>(out.get()), output_size))
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to write to output stream");
+ return false;
+ }
+ } while (strm.avail_out == 0);
+ assert(strm.avail_in == 0); // All data was read
+ } while (flush != Z_FINISH);
+ assert(ret == Z_STREAM_END); // Completed stream
+ AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request to: " << strm.total_out << " bytes");
+ deflateEnd(&strm);
+ return output;
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm));
+ return false;
+ }
+#else
+ // If there is no support to compress, always fail calls to this method.
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm));
+ AWS_UNREFERENCED_PARAM(input); // silencing warning;
+ return false;
+#endif
+}
+
+Aws::Utils::Outcome<std::shared_ptr<Aws::IOStream>, bool>
+Aws::Client::RequestCompression::uncompress(std::shared_ptr<Aws::IOStream> input, const CompressionAlgorithm &algorithm) const
+{
+#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION
+ if (algorithm == CompressionAlgorithm::GZIP)
+ {
+ // calculating stream size
+ input->seekg(0, input->end);
+ size_t streamSize = input->tellg();
+ input->seekg(0, input->beg);
+
+ AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompressing request of " << streamSize << " bytes.");
+
+ // Preparing output
+ std::shared_ptr<Aws::IOStream> output = Aws::MakeShared<Aws::StringStream>( AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!output)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate output while uncompressing")
+ return false;
+ }
+
+ // Prepare ZLIB to uncompress
+ int ret = Z_NULL;
+ z_stream strm = {};
+ auto in = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!in)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate in buffer while uncompressing")
+ return false;
+ }
+
+ auto out = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG);
+ if(!out)
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate out buffer while uncompressing")
+ return false;
+ }
+
+ //preparing allocation
+#ifdef USE_AWS_MEMORY_MANAGEMENT
+ strm.zalloc = (void *(*)(void *, unsigned, unsigned)) aws_zalloc;
+ strm.zfree = (void (*)(void *, void *)) aws_zfree;
+#else
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+#endif
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+
+ const int MAX_WINDOW_GZIP = 31;
+ ret = inflateInit2(&strm, MAX_WINDOW_GZIP);
+ if (ret != Z_OK)
+ {
+ return false;
+ }
+
+ //Adding one to the stream size counter to account for the EOF marker.
+ streamSize++;
+ size_t toRead;
+ // Decompress
+ do {
+ toRead = (streamSize < ZLIB_CHUNK)?streamSize:ZLIB_CHUNK;
+ if (toRead < 1) break; // Nothing left to read
+ // Fill the buffer
+ if(! input->read(reinterpret_cast<char *>(in.get()), toRead))
+ {
+ if (input->eof())
+ {
+ //skip passing the EOF to the buffer
+ toRead--;
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(
+ AWS_REQUEST_COMPRESSION_LOG_TAG,
+ "Compress request failed to read from stream");
+ return false;
+ }
+ }
+
+ // Filling input buffer to decompress
+ strm.avail_in = toRead;
+ strm.next_in = in.get();
+ do
+ {
+ // Run inflate on buffers
+ strm.avail_out = ZLIB_CHUNK;
+ strm.next_out = out.get();
+
+ ret = inflate(&strm, Z_NO_FLUSH);
+ // Catch errors
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_NEED_DICT");
+ return false;
+ case Z_DATA_ERROR:
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_DATA_ERROR");
+ return false;
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&strm);
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_MEM_ERROR");
+ return false;
+ }
+
+ // writing the output
+ unsigned output_size = ZLIB_CHUNK - strm.avail_out;
+ if(! output->write(reinterpret_cast<char *>(out.get()), output_size)) {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompressed request failed to write to output stream");
+ return false;
+ }
+ } while (strm.avail_out == 0);
+ } while (ret != Z_STREAM_END);
+ // clean up
+ (void)inflateEnd(&strm);
+ if (ret == Z_STREAM_END)
+ {
+ AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Decompressed request to: " << strm.total_out << " bytes");
+ return output;
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to decompress after read input completely");
+ return false;
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm));
+ return false;
+ }
+#else
+ // If there is no support to compress, always fail calls to this method.
+ AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm));
+ AWS_UNREFERENCED_PARAM(input); // silencing warning;
+ return false;
+#endif
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp
index b439b7ca995..77b6f5abbbd 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp
@@ -17,18 +17,21 @@ namespace Aws
{
static const int INITIAL_RETRY_TOKENS = 500;
static const int RETRY_COST = 5;
- static const int NO_RETRY_INCREMENT = 1;
static const int TIMEOUT_RETRY_COST = 10;
StandardRetryStrategy::StandardRetryStrategy(long maxAttempts) :
m_retryQuotaContainer(Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy")),
m_maxAttempts(maxAttempts)
- {}
+ {
+ srand((unsigned int)time(NULL));
+ }
StandardRetryStrategy::StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts) :
m_retryQuotaContainer(retryQuotaContainer),
m_maxAttempts(maxAttempts)
- {}
+ {
+ srand((unsigned int)time(NULL));
+ }
void StandardRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome)
{
@@ -60,7 +63,8 @@ namespace Aws
long StandardRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const
{
AWS_UNREFERENCED_PARAM(error);
- return (std::min)(rand() % 1000 * (1 << attemptedRetries), 20000);
+ // Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values:
+ return (std::min)(rand() % 1000 * (1 << (std::min)(attemptedRetries, 15L)), 20000);
}
DefaultRetryQuotaContainer::DefaultRetryQuotaContainer() : m_retryQuota(INITIAL_RETRY_TOKENS)
@@ -99,4 +103,4 @@ namespace Aws
ReleaseRetryQuota(capacityAmount);
}
}
-} \ No newline at end of file
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSConfigFileProfileConfigLoader.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSConfigFileProfileConfigLoader.cpp
new file mode 100644
index 00000000000..ba0079bb5e8
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSConfigFileProfileConfigLoader.cpp
@@ -0,0 +1,629 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/config/AWSProfileConfigLoader.h>
+#include <aws/core/utils/memory/stl/AWSSet.h>
+#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <fstream>
+
+namespace Aws
+{
+ namespace Config
+ {
+ using namespace Aws::Utils;
+ using namespace Aws::Auth;
+
+ static const char REGION_KEY[] = "region";
+ static const char ACCESS_KEY_ID_KEY[] = "aws_access_key_id";
+ static const char SECRET_KEY_KEY[] = "aws_secret_access_key";
+ static const char SESSION_TOKEN_KEY[] = "aws_session_token";
+ static const char SSO_START_URL_KEY[] = "sso_start_url";
+ static const char SSO_REGION_KEY[] = "sso_region";
+ static const char SSO_ACCOUNT_ID_KEY[] = "sso_account_id";
+ static const char SSO_ROLE_NAME_KEY[] = "sso_role_name";
+ static const char SSO_SESSION_KEY[] = "sso_session";
+ static const char ROLE_ARN_KEY[] = "role_arn";
+ static const char EXTERNAL_ID_KEY[] = "external_id";
+ static const char CREDENTIAL_PROCESS_COMMAND[] = "credential_process";
+ static const char SOURCE_PROFILE_KEY[] = "source_profile";
+ static const char PROFILE_SECTION[] = "profile";
+ static const char DEFAULT[] = "default";
+ static const char SSO_SESSION_SECTION[] = "sso-session";
+ static const char DEFAULTS_MODE_KEY[] = "defaults_mode";
+ static const char EQ = '=';
+ static const char LEFT_BRACKET = '[';
+ static const char RIGHT_BRACKET = ']';
+ static const char PARSER_TAG[] = "Aws::Config::ConfigFileProfileFSM";
+
+ // generated by python from identifier regex pattern from the spec: R"([A-Za-z0-9_\-/.%@:\+]+)":
+ // #py: ''.join(chr(i) for i in range(128) if re.match("[A-Za-z0-9_\-\/.%@:\+]", chr(i)))
+ const char IDENTIFIER_ALLOWED_CHARACTERS[] = R"(%+-./0123456789:@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz)";
+ static const size_t IDENTIFIER_ALLOWED_CHARACTERS_SZ = sizeof(IDENTIFIER_ALLOWED_CHARACTERS) - 1;
+ const char WHITESPACE_CHARACTERS[] = "\t ";
+ static const size_t WHITESPACE_CHARACTERS_SZ = sizeof(WHITESPACE_CHARACTERS) - 1;
+ const char COMMENT_START[] = "#;";
+ static const size_t COMMENT_START_SZ = sizeof(COMMENT_START) - 1;
+
+ struct ProfilePropertyAccessFunctions
+ {
+ const char* PropertyKey;
+ std::function<void(Profile&, const Aws::String&)> Setter;
+ std::function<const Aws::String&(const Profile&)> Getter;
+ };
+
+ static const ProfilePropertyAccessFunctions PROFILE_PROPERTY_FUNCS[] =
+ {{REGION_KEY, &Profile::SetRegion, &Profile::GetRegion},
+ //ACCESS_KEY_ID_KEY, - AwsCredentials require special handling
+ //SECRET_KEY_KEY,
+ //SESSION_TOKEN_KEY,
+ {SSO_START_URL_KEY, &Profile::SetSsoStartUrl, &Profile::GetSsoStartUrl},
+ {SSO_REGION_KEY, &Profile::SetSsoRegion, &Profile::GetSsoRegion},
+ {SSO_ACCOUNT_ID_KEY, &Profile::SetSsoAccountId, &Profile::GetSsoAccountId},
+ {SSO_ROLE_NAME_KEY, &Profile::SetSsoRoleName, &Profile::GetSsoRoleName},
+ //SSO_SESSION_KEY - SsoSession requires special handling
+ {ROLE_ARN_KEY, &Profile::SetRoleArn, &Profile::GetRoleArn},
+ {EXTERNAL_ID_KEY, &Profile::SetExternalId, &Profile::GetExternalId},
+ {CREDENTIAL_PROCESS_COMMAND, &Profile::SetCredentialProcess, &Profile::GetCredentialProcess},
+ {SOURCE_PROFILE_KEY, &Profile::SetSourceProfile, &Profile::GetSourceProfile},
+ {DEFAULTS_MODE_KEY, &Profile::SetDefaultsMode, &Profile::GetDefaultsMode}};
+
+ template<typename EntryT, size_t N>
+ const EntryT* FindInStaticArray(const EntryT (&array)[N], const Aws::String& searchKey)
+ {
+ const EntryT* found = std::find_if(array, array + N,
+ [&searchKey](const EntryT& entry)
+ {
+ return searchKey == entry.PropertyKey;
+ });
+
+ if(!!found && found != array + N)
+ return found;
+
+ return nullptr;
+ }
+
+ static const char* PROFILE_KEY_SPECIAL_HANDLING[] =
+ {ACCESS_KEY_ID_KEY, SECRET_KEY_KEY, SESSION_TOKEN_KEY, SSO_SESSION_KEY};
+ static const size_t PROFILE_KEY_SPECIAL_HANDLING_SZ = sizeof(PROFILE_KEY_SPECIAL_HANDLING) / sizeof(PROFILE_KEY_SPECIAL_HANDLING[0]);
+
+ struct SsoSessionPropertyAccessFunctions
+ {
+ const char* PropertyKey;
+ std::function<void(Profile::SsoSession&, const Aws::String&)> Setter;
+ std::function<const Aws::String&(const Profile::SsoSession&)> Getter;
+ };
+ static const SsoSessionPropertyAccessFunctions SSO_SESSION_PROPERTY_FUNCS[] =
+ {{SSO_REGION_KEY, &Profile::SsoSession::SetSsoRegion, &Profile::SsoSession::GetSsoRegion},
+ {SSO_START_URL_KEY, &Profile::SsoSession::SetSsoStartUrl, &Profile::SsoSession::GetSsoStartUrl}};
+
+ class ConfigFileProfileFSM
+ {
+ public:
+ ConfigFileProfileFSM(bool useProfilePrefix)
+ : m_useProfilePrefix(useProfilePrefix)
+ {}
+
+ const Aws::Map<String, Profile>& GetProfiles() const { return m_foundProfiles; }
+
+ void ParseStream(Aws::IStream& stream)
+ {
+ static const size_t ASSUME_EMPTY_LEN = 3;
+ State currentState = START;
+ Aws::String currentSectionName;
+ Aws::Map<Aws::String, Aws::String> currentKeyValues;
+
+ Aws::String rawLine;
+ while(std::getline(stream, rawLine) && currentState != FAILURE)
+ {
+ Aws::String line = rawLine.substr(0, rawLine.find_first_of(COMMENT_START)); // ignore comments
+ if (line.empty() || line.length() < ASSUME_EMPTY_LEN || line.find_first_not_of(WHITESPACE_CHARACTERS) == Aws::String::npos)
+ {
+ continue;
+ }
+
+ auto openPos = line.find(LEFT_BRACKET);
+ auto closePos = line.find(RIGHT_BRACKET);
+
+ if(openPos != std::string::npos && closePos != std::string::npos)
+ {
+ FlushSection(currentState, currentSectionName, currentKeyValues);
+ currentKeyValues.clear();
+ ParseSectionDeclaration(line, currentSectionName, currentState);
+ continue;
+ }
+
+ if(PROFILE_FOUND == currentState || SSO_SESSION_FOUND == currentState)
+ {
+ auto equalsPos = line.find(EQ);
+ if (equalsPos != std::string::npos)
+ {
+ auto key = StringUtils::Trim(line.substr(0, equalsPos).c_str());
+ auto value = StringUtils::Trim(line.substr(equalsPos + 1).c_str());
+ currentKeyValues[key] = value;
+ continue;
+ }
+ }
+
+ if(UNKNOWN_SECTION_FOUND == currentState)
+ {
+ // skip any unknown sections
+ continue;
+ }
+
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Unexpected line in the aws shared profile: " << rawLine);
+ currentState = FAILURE;
+ break;
+ }
+
+ FlushSection(currentState, currentSectionName, currentKeyValues);
+
+ // Put sso-sessions into profiles
+ for(auto& profile : m_foundProfiles)
+ {
+ const Aws::String& profileSsoSessionName = profile.second.GetValue(SSO_SESSION_KEY);
+ if(!profileSsoSessionName.empty())
+ {
+ auto ssoSessionIt = m_foundSsoSessions.find(profileSsoSessionName);
+ if(ssoSessionIt == m_foundSsoSessions.end())
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "AWS profile has reference to a missing sso_session: " << profileSsoSessionName);
+ currentState = FAILURE;
+ continue;
+ }
+ auto ssoSession = ssoSessionIt->second;
+ auto prof = profile.second;
+ // If sso session and profile have conflicting start url or region, fail to parse
+ // the session/sso specific profile properties
+ auto hasConflictingStartUrls = !ssoSession.GetSsoStartUrl().empty()
+ && !prof.GetSsoStartUrl().empty()
+ && ssoSession.GetSsoStartUrl() != prof.GetSsoStartUrl();
+ auto hasConflictingRegions = !ssoSession.GetSsoRegion().empty()
+ && !prof.GetSsoRegion().empty()
+ && ssoSession.GetSsoRegion() != prof.GetSsoRegion();
+ if (hasConflictingStartUrls || hasConflictingRegions) {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG,
+ "SSO profile has a start url or region conflict with sso session");
+ prof.SetSsoStartUrl("");
+ prof.SetSsoRegion("");
+ prof.SetSsoAccountId("");
+ prof.SetSsoRoleName("");
+ continue;
+ }
+ profile.second.SetSsoSession(ssoSessionIt->second);
+ }
+ }
+
+ if(FAILURE == currentState)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "AWS shared profile config parsing failed");
+ }
+ }
+
+ private:
+ // true means Shared Config parsing, false means Shared Credentials parsing
+ bool m_useProfilePrefix = false;
+
+ enum State
+ {
+ START = 0,
+ PROFILE_FOUND,
+ SSO_SESSION_FOUND,
+ UNKNOWN_SECTION_FOUND,
+ FAILURE
+ };
+
+ /**
+ * Helper function to parse a single word (aka section identifier) containing allowed characters from a line and a pos
+ * i.e. line="[ profile default ]";identifierBegin=10 will return "default"
+ * @param line, a section definition line being parsed
+ * @param identifierBegin, an Aws::String position to start parsing
+ * @param oErrorMsg, a reference to Aws::String to store error message in case of a parsing error.
+ * @return Aws::String, e.g. "default"
+ */
+ Aws::String ParseIdentifier(const Aws::String& line, Aws::String::size_type identifierBegin, Aws::String& oErrorMsg)
+ {
+ // pos at the beginning of section Identifier (or sso_session section keyword)
+ Aws::String::size_type identifierLength = 0;
+ Aws::String::size_type pos = identifierBegin;
+ while(pos < line.length())
+ {
+ if(std::find(IDENTIFIER_ALLOWED_CHARACTERS,
+ IDENTIFIER_ALLOWED_CHARACTERS + IDENTIFIER_ALLOWED_CHARACTERS_SZ,
+ line[pos]) != IDENTIFIER_ALLOWED_CHARACTERS + IDENTIFIER_ALLOWED_CHARACTERS_SZ)
+ {
+ identifierLength++;
+ pos++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ const Aws::String SECTION_END_CHARS_TO_SKIP = Aws::String(WHITESPACE_CHARACTERS) + RIGHT_BRACKET;
+
+ if(identifierLength == 0)
+ {
+ oErrorMsg = "identifier is missing";
+ return "";
+ }
+ if(pos >= line.size() || SECTION_END_CHARS_TO_SKIP.find(line[pos]) == Aws::String::npos) {
+ oErrorMsg = "a blank space character or closing bracket is expected after Identifier";
+ return "";
+ }
+ Aws::String sectionIdentifier = line.substr(identifierBegin, identifierLength);
+
+ return sectionIdentifier;
+ }
+
+ /**
+ * A helper function to parse config section declaration line
+ * @param line, an input line, e.g. "[profile default]"
+ * @param ioSectionName, a return argument representing parsed section Identifier, e.g. "default"
+ * @param ioState, a return argument representing parser state, e.g. PROFILE_FOUND
+ */
+ void ParseSectionDeclaration(const Aws::String& line,
+ Aws::String& ioSectionName,
+ State& ioState)
+ {
+ do { // goto in a form of "do { break; } while(0);"
+ Aws::String::size_type pos = 0;
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ if(pos != Aws::String::npos && LEFT_BRACKET != line[pos])
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "First non-blank space character of a section definition must be [, line:" << line);
+ break;
+ }
+ pos++;
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ if(pos == Aws::String::npos || pos >= line.size())
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Unknown section found in the aws config file: " << line);
+ break;
+ }
+ bool defaultProfileOrSsoSectionRequired = false;
+ if (m_useProfilePrefix)
+ {
+ // in configuration files, the profile name must start with profile. (eg. [profile profile-name]),
+ // except where the profile name is default. When the profile name is default it may start with profile
+ static const size_t PROFILE_KEYWORD_LENGTH = 7;
+ if(line.rfind(PROFILE_SECTION, pos + PROFILE_KEYWORD_LENGTH) != Aws::String::npos)
+ {
+ // skipping required (optional for default) profile keyword
+ pos += PROFILE_KEYWORD_LENGTH;
+ if(pos >= line.size() ||
+ std::find(WHITESPACE_CHARACTERS,
+ WHITESPACE_CHARACTERS + WHITESPACE_CHARACTERS_SZ,
+ line[pos]) == WHITESPACE_CHARACTERS + WHITESPACE_CHARACTERS_SZ)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Expected a blank space after \"profile\" keyword: " << line);
+ break;
+ }
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ }
+ else
+ {
+ defaultProfileOrSsoSectionRequired = true;
+ }
+ }
+
+ Aws::String errorMsg;
+ Aws::String sectionIdentifier = ParseIdentifier(line, pos, errorMsg);
+ if (!errorMsg.empty())
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Failed to parse section identifier: " << errorMsg << " " << line);
+ break;
+ }
+ pos += sectionIdentifier.length();
+
+ if(defaultProfileOrSsoSectionRequired)
+ {
+ if (sectionIdentifier != DEFAULT && sectionIdentifier != SSO_SESSION_SECTION)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "In configuration files, the profile name must start with "
+ "profile keyword (except default profile): " << line);
+ break;
+ }
+ if (sectionIdentifier != SSO_SESSION_SECTION)
+ {
+ // profile found, still pending check for closing bracket
+ ioState = PROFILE_FOUND;
+ ioSectionName = sectionIdentifier;
+ }
+ }
+
+ if(!m_useProfilePrefix || sectionIdentifier != SSO_SESSION_SECTION)
+ {
+ // profile found, still pending check for closing bracket
+ ioState = PROFILE_FOUND;
+ ioSectionName = sectionIdentifier;
+ }
+
+ if(m_useProfilePrefix && sectionIdentifier == SSO_SESSION_SECTION)
+ {
+ // "[sso_session..." found, continue parsing for sso_session identifier
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ if(pos == Aws::String::npos)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Expected a blank space after \"sso_session\" keyword: " << line);
+ break;
+ }
+
+ sectionIdentifier = ParseIdentifier(line, pos, errorMsg);
+ if (!errorMsg.empty())
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Failed to parse section identifier: " << errorMsg << " " << line);
+ break;
+ }
+ pos += sectionIdentifier.length();
+ // sso_session found, still pending check for closing bracket
+ ioState = SSO_SESSION_FOUND;
+ ioSectionName = sectionIdentifier;
+ }
+
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ if(pos == Aws::String::npos)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Expected a non-blank space after section identifier (i.e. missing \"]\"): " << line);
+ break;
+ }
+ if(line[pos] != RIGHT_BRACKET)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Missing closing bracket after Section Identifier "
+ "(i.e. missing \"]\" or extra non-blank characters before \"]\"): " << line);
+ break;
+ }
+ pos++;
+ pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
+ if(pos != Aws::String::npos &&
+ std::find(COMMENT_START, COMMENT_START + COMMENT_START_SZ, line[pos]) == COMMENT_START + COMMENT_START_SZ)
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "Found unexpected characters after closing bracket of Section Identifier " << line);
+ break;
+ }
+ // the rest is a comment, and we don't care about it.
+ if ((ioState != SSO_SESSION_FOUND && ioState != PROFILE_FOUND) || ioSectionName.empty())
+ {
+ AWS_LOGSTREAM_FATAL(PARSER_TAG, "Unexpected parser state after attempting to parse section " << line);
+ break;
+ }
+ return;
+ } while(0); // end of goto in a form of "do { break; } while(0);"
+
+ ioSectionName.erase();
+ ioState = UNKNOWN_SECTION_FOUND;
+ return;
+ }
+
+ /**
+ * A helper function to store currently being parsed section along with its properties
+ * (i.e. [profile default] and its key1=val1 under).
+ * @param currentState, a current parser State, e.g. PROFILE_FOUND
+ * @param currentSectionName, a current section identifier, e.g. "default"
+ * @param currentKeyValues, a map of parsed key-value properties of a section definition being recorded
+ */
+ void FlushSection(const State currentState, const Aws::String& currentSectionName, Aws::Map<Aws::String, Aws::String>& currentKeyValues)
+ {
+ if(START == currentState || currentSectionName.empty())
+ {
+ return; //nothing to flush
+ }
+
+ if(PROFILE_FOUND == currentState)
+ {
+ Profile& profile = m_foundProfiles[currentSectionName];
+
+ for(const auto& keyVal : currentKeyValues)
+ {
+ auto setterFuncPtr = FindInStaticArray(PROFILE_PROPERTY_FUNCS, keyVal.first);
+ if(setterFuncPtr)
+ {
+ AWS_LOGSTREAM_DEBUG(PARSER_TAG, "Found " << setterFuncPtr->PropertyKey << " " << keyVal.second);
+ setterFuncPtr->Setter(profile, keyVal.second);
+ }
+ else
+ {
+ auto specialPropertyKey = std::find_if(PROFILE_KEY_SPECIAL_HANDLING, PROFILE_KEY_SPECIAL_HANDLING + PROFILE_KEY_SPECIAL_HANDLING_SZ,
+ [&keyVal](const char* entry)
+ {
+ return !!entry && keyVal.first == entry;
+ });
+
+ if (specialPropertyKey && specialPropertyKey != PROFILE_KEY_SPECIAL_HANDLING + PROFILE_KEY_SPECIAL_HANDLING_SZ)
+ {
+ AWS_LOGSTREAM_INFO(PARSER_TAG, "Unknown property: " << keyVal.first << " in the profile: " << currentSectionName);
+ }
+ }
+ }
+
+ auto accessKeyIdIter = currentKeyValues.find(ACCESS_KEY_ID_KEY);
+ Aws::String accessKey, secretKey, sessionToken;
+ if (accessKeyIdIter != currentKeyValues.end())
+ {
+ accessKey = accessKeyIdIter->second;
+ AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found access key " << accessKey);
+
+ auto secretAccessKeyIter = currentKeyValues.find(SECRET_KEY_KEY);
+ auto sessionTokenIter = currentKeyValues.find(SESSION_TOKEN_KEY);
+ if (secretAccessKeyIter != currentKeyValues.end())
+ {
+ secretKey = secretAccessKeyIter->second;
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "No secret access key found even though an access key was specified. This will cause all signed AWS calls to fail.");
+ }
+
+ if (sessionTokenIter != currentKeyValues.end())
+ {
+ sessionToken = sessionTokenIter->second;
+ }
+
+ profile.SetCredentials(Aws::Auth::AWSCredentials(accessKey, secretKey, sessionToken));
+ }
+
+ if (!profile.GetSsoStartUrl().empty() || !profile.GetSsoRegion().empty()
+ || !profile.GetSsoAccountId().empty() || !profile.GetSsoRoleName().empty())
+ {
+ // If there is no sso session, all fields are required. If an SSO session is present,
+ // then only account id and sso role name are required.
+ auto hasSession = currentKeyValues.find(SSO_SESSION_KEY) != currentKeyValues.end();
+ auto hasInvalidProfileWithoutSession = !hasSession &&
+ (profile.GetSsoStartUrl().empty()
+ || profile.GetSsoRegion().empty()
+ || profile.GetSsoAccountId().empty()
+ || profile.GetSsoRoleName().empty());
+ auto hasInvalidProfileWithSession = hasSession &&
+ (profile.GetSsoAccountId().empty()
+ || profile.GetSsoRoleName().empty());
+ if (hasInvalidProfileWithoutSession || hasInvalidProfileWithSession) {
+ profile.SetSsoStartUrl("");
+ profile.SetSsoRegion("");
+ profile.SetSsoAccountId("");
+ profile.SetSsoRoleName("");
+ AWS_LOGSTREAM_ERROR(PARSER_TAG, "invalid SSO configuration for aws profile " << currentSectionName);
+ }
+ }
+
+ profile.SetName(currentSectionName);
+ profile.SetAllKeyValPairs(std::move(currentKeyValues));
+ }
+ else if (SSO_SESSION_FOUND == currentState) {
+ Profile::SsoSession& ssoSession = m_foundSsoSessions[currentSectionName];
+ for(const auto& keyVal : currentKeyValues)
+ {
+ auto setterFuncPtr = FindInStaticArray(SSO_SESSION_PROPERTY_FUNCS, keyVal.first);
+ if(setterFuncPtr)
+ {
+ AWS_LOGSTREAM_DEBUG(PARSER_TAG, "Found sso-session property " << setterFuncPtr->PropertyKey << " " << keyVal.second);
+ setterFuncPtr->Setter(ssoSession, keyVal.second);
+ }
+ else
+ {
+ AWS_LOGSTREAM_INFO(PARSER_TAG, "Unknown property: " << keyVal.first << " in the sso-session: " << currentSectionName);
+ }
+ }
+ ssoSession.SetName(currentSectionName);
+ ssoSession.SetAllKeyValPairs(std::move(currentKeyValues));
+ }
+ else
+ {
+ AWS_LOGSTREAM_FATAL(PARSER_TAG, "Unknown parser error: unexpected state " << currentState);
+ }
+ }
+
+ Aws::Map<String, Profile> m_foundProfiles;
+ Aws::Map<String, Profile::SsoSession> m_foundSsoSessions;
+ };
+
+ static const char* const CONFIG_FILE_LOADER = "Aws::Config::AWSConfigFileProfileConfigLoader";
+
+ AWSConfigFileProfileConfigLoader::AWSConfigFileProfileConfigLoader(const Aws::String& fileName, bool useProfilePrefix) :
+ m_fileName(fileName), m_useProfilePrefix(useProfilePrefix)
+ {
+ AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Initializing config loader against fileName "
+ << fileName << " and using profilePrefix = " << useProfilePrefix);
+ }
+
+ bool AWSConfigFileProfileConfigLoader::LoadInternal()
+ {
+ m_profiles.clear();
+
+ Aws::IFStream inputFile(m_fileName.c_str());
+ if(inputFile)
+ {
+ ConfigFileProfileFSM parser(m_useProfilePrefix);
+ parser.ParseStream(inputFile);
+ m_profiles = parser.GetProfiles();
+ return m_profiles.size() > 0;
+ }
+
+ AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for reading.");
+
+ return false;
+ }
+
+ bool AWSConfigFileProfileConfigLoader::PersistInternal(const Aws::Map<Aws::String, Profile>& profiles)
+ {
+ Aws::OFStream outputFile(m_fileName.c_str(), std::ios_base::out | std::ios_base::trunc);
+ if(outputFile)
+ {
+ Aws::UnorderedMap<Aws::String, std::reference_wrapper<const Profile::SsoSession>> ssoSessionsToDump;
+
+ for(const auto& profile : profiles)
+ {
+ Aws::String prefix = m_useProfilePrefix ? PROFILE_SECTION : "";
+
+ AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing profile " << profile.first << " to disk.");
+
+ outputFile << LEFT_BRACKET << prefix << " " << profile.second.GetName() << RIGHT_BRACKET << std::endl;
+ const Aws::Auth::AWSCredentials& credentials = profile.second.GetCredentials();
+ if (!credentials.GetAWSAccessKeyId().empty()) {
+ outputFile << ACCESS_KEY_ID_KEY << EQ << credentials.GetAWSAccessKeyId() << std::endl;
+ }
+ if (!credentials.GetAWSSecretKey().empty()) {
+ outputFile << SECRET_KEY_KEY << EQ << credentials.GetAWSSecretKey() << std::endl;
+ }
+ if(!credentials.GetSessionToken().empty()) {
+ outputFile << SESSION_TOKEN_KEY << EQ << credentials.GetSessionToken() << std::endl;
+ }
+ // credentials.GetExpiration().Millis() <- is not present in a config.
+
+ for(const auto& profilePropertyPair : PROFILE_PROPERTY_FUNCS)
+ {
+ const auto& profilePropertyValue = profilePropertyPair.Getter(profile.second);
+ if(!profilePropertyValue.empty())
+ {
+ outputFile << profilePropertyPair.PropertyKey << EQ << profilePropertyValue << std::endl;
+ }
+ }
+
+ if(profile.second.IsSsoSessionSet())
+ {
+ const auto& ssoSession = profile.second.GetSsoSession();
+ const auto alreadyScheduledForDumpIt = ssoSessionsToDump.find(ssoSession.GetName());
+ if (alreadyScheduledForDumpIt != ssoSessionsToDump.end() &&
+ alreadyScheduledForDumpIt->second.get() != ssoSession)
+ {
+ AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "2 or more profiles reference 'sso-session' section "
+ "with the same name but different properties: " << ssoSession.GetName());
+ }
+ else
+ {
+ ssoSessionsToDump.insert({ssoSession.GetName(), std::cref(ssoSession)});
+ }
+ outputFile << SSO_SESSION_KEY << EQ << ssoSession.GetName() << std::endl;
+ }
+ outputFile << std::endl;
+ }
+
+ for(const auto& ssoSessionPair : ssoSessionsToDump)
+ {
+ AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing sso-session " << ssoSessionPair.first << " to disk.");
+ const Profile::SsoSession& ssoSession = ssoSessionPair.second.get();
+ outputFile << LEFT_BRACKET << SSO_SESSION_SECTION << " " << ssoSession.GetName() << RIGHT_BRACKET << std::endl;
+ for(const auto& ssoSessionPropertyPair : SSO_SESSION_PROPERTY_FUNCS)
+ {
+ const auto& profilePropertyValue = ssoSessionPropertyPair.Getter(ssoSession);
+ if(!profilePropertyValue.empty())
+ {
+ outputFile << ssoSessionPropertyPair.PropertyKey << EQ << profilePropertyValue << std::endl;
+ }
+ }
+ outputFile << std::endl;
+ }
+
+ AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Profiles written to config file " << m_fileName);
+
+ return true;
+ }
+
+ AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for writing.");
+
+ return false;
+ }
+ } // Config namespace
+} // Aws namespace
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp
deleted file mode 100644
index bb6acd0b3a0..00000000000
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoader.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-/**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
-
-#include <aws/core/config/AWSProfileConfigLoader.h>
-#include <aws/core/internal/AWSHttpResourceClient.h>
-#include <aws/core/auth/AWSCredentialsProvider.h>
-#include <aws/core/utils/memory/stl/AWSList.h>
-#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
-#include <aws/core/utils/StringUtils.h>
-#include <aws/core/utils/logging/LogMacros.h>
-#include <aws/core/utils/json/JsonSerializer.h>
-#include <fstream>
-
-namespace Aws
-{
- namespace Config
- {
- using namespace Aws::Utils;
- using namespace Aws::Auth;
-
- static const char* const CONFIG_LOADER_TAG = "Aws::Config::AWSProfileConfigLoader";
- #ifdef _MSC_VER
- // VS2015 compiler's bug, warning s_CoreErrorsMapper: symbol will be dynamically initialized (implementation limitation)
- AWS_SUPPRESS_WARNING(4592,
- static Aws::UniquePtr<ConfigAndCredentialsCacheManager> s_configManager(nullptr);
- )
- #else
- static Aws::UniquePtr<ConfigAndCredentialsCacheManager> s_configManager(nullptr);
- #endif
-
- static const char CONFIG_CREDENTIALS_CACHE_MANAGER_TAG[] = "ConfigAndCredentialsCacheManager";
-
- bool AWSProfileConfigLoader::Load()
- {
- if(LoadInternal())
- {
- AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully reloaded configuration.");
- m_lastLoadTime = DateTime::Now();
- AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "reloaded config at "
- << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601));
- return true;
- }
-
- AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Failed to reload configuration.");
- return false;
- }
-
- bool AWSProfileConfigLoader::PersistProfiles(const Aws::Map<Aws::String, Profile>& profiles)
- {
- if(PersistInternal(profiles))
- {
- AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully persisted configuration.");
- m_profiles = profiles;
- m_lastLoadTime = DateTime::Now();
- AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "persisted config at "
- << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601));
- return true;
- }
-
- AWS_LOGSTREAM_WARN(CONFIG_LOADER_TAG, "Failed to persist configuration.");
- return false;
- }
-
- static const char REGION_KEY[] = "region";
- static const char ACCESS_KEY_ID_KEY[] = "aws_access_key_id";
- static const char SECRET_KEY_KEY[] = "aws_secret_access_key";
- static const char SESSION_TOKEN_KEY[] = "aws_session_token";
- static const char SSO_START_URL_KEY[] = "sso_start_url";
- static const char SSO_REGION_KEY[] = "sso_region";
- static const char SSO_ACCOUNT_ID_KEY[] = "sso_account_id";
- static const char SSO_ROLE_NAME_KEY[] = "sso_role_name";
- static const char ROLE_ARN_KEY[] = "role_arn";
- static const char EXTERNAL_ID_KEY[] = "external_id";
- static const char CREDENTIAL_PROCESS_COMMAND[] = "credential_process";
- static const char SOURCE_PROFILE_KEY[] = "source_profile";
- static const char PROFILE_PREFIX[] = "profile ";
- static const char EQ = '=';
- static const char LEFT_BRACKET = '[';
- static const char RIGHT_BRACKET = ']';
- static const char PARSER_TAG[] = "Aws::Config::ConfigFileProfileFSM";
-
- class ConfigFileProfileFSM
- {
- public:
- ConfigFileProfileFSM() : m_parserState(START) {}
-
- const Aws::Map<String, Profile>& GetProfiles() const { return m_foundProfiles; }
-
- void ParseStream(Aws::IStream& stream)
- {
- static const size_t ASSUME_EMPTY_LEN = 3;
-
- Aws::String line;
- while(std::getline(stream, line) && m_parserState != FAILURE)
- {
- if (line.empty() || line.length() < ASSUME_EMPTY_LEN)
- {
- continue;
- }
-
- auto openPos = line.find(LEFT_BRACKET);
- auto closePos = line.find(RIGHT_BRACKET);
-
- switch(m_parserState)
- {
-
- case START:
- if(openPos != std::string::npos && closePos != std::string::npos)
- {
- FlushProfileAndReset(line, openPos, closePos);
- m_parserState = PROFILE_FOUND;
- }
- break;
-
- //fallthrough here is intentional to reduce duplicate logic
- case PROFILE_KEY_VALUE_FOUND:
- if(openPos != std::string::npos && closePos != std::string::npos)
- {
- m_parserState = PROFILE_FOUND;
- FlushProfileAndReset(line, openPos, closePos);
- break;
- }
- // fall through
- case PROFILE_FOUND:
- {
- auto equalsPos = line.find(EQ);
- if (equalsPos != std::string::npos)
- {
- auto key = line.substr(0, equalsPos);
- auto value = line.substr(equalsPos + 1);
- m_profileKeyValuePairs[StringUtils::Trim(key.c_str())] =
- StringUtils::Trim(value.c_str());
- m_parserState = PROFILE_KEY_VALUE_FOUND;
- }
-
- break;
- }
- default:
- m_parserState = FAILURE;
- break;
- }
- }
-
- FlushProfileAndReset(line, std::string::npos, std::string::npos);
- }
-
- private:
-
- void FlushProfileAndReset(Aws::String& line, size_t openPos, size_t closePos)
- {
- if(!m_currentWorkingProfile.empty() && !m_profileKeyValuePairs.empty())
- {
- Profile profile;
- profile.SetName(m_currentWorkingProfile);
-
- auto regionIter = m_profileKeyValuePairs.find(REGION_KEY);
- if (regionIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found region " << regionIter->second);
- profile.SetRegion(regionIter->second);
- }
-
- auto accessKeyIdIter = m_profileKeyValuePairs.find(ACCESS_KEY_ID_KEY);
- Aws::String accessKey, secretKey, sessionToken;
- if (accessKeyIdIter != m_profileKeyValuePairs.end())
- {
- accessKey = accessKeyIdIter->second;
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found access key " << accessKey);
-
- auto secretAccessKeyIter = m_profileKeyValuePairs.find(SECRET_KEY_KEY);
- auto sessionTokenIter = m_profileKeyValuePairs.find(SESSION_TOKEN_KEY);
- if (secretAccessKeyIter != m_profileKeyValuePairs.end())
- {
- secretKey = secretAccessKeyIter->second;
- }
- else
- {
- AWS_LOGSTREAM_ERROR(PARSER_TAG, "No secret access key found even though an access key was specified. This will cause all signed AWS calls to fail.");
- }
-
- if (sessionTokenIter != m_profileKeyValuePairs.end())
- {
- sessionToken = sessionTokenIter->second;
- }
-
- profile.SetCredentials(Aws::Auth::AWSCredentials(accessKey, secretKey, sessionToken));
- }
-
- auto ssoStartUrlIter = m_profileKeyValuePairs.find(SSO_START_URL_KEY);
- auto ssoRegionIter = m_profileKeyValuePairs.find(SSO_REGION_KEY);
- auto ssoRoleNameIter = m_profileKeyValuePairs.find(SSO_ROLE_NAME_KEY);
- auto ssoAccountIdIter = m_profileKeyValuePairs.find(SSO_ACCOUNT_ID_KEY);
- if (ssoStartUrlIter != m_profileKeyValuePairs.end()
- || ssoRegionIter != m_profileKeyValuePairs.end()
- || ssoRoleNameIter != m_profileKeyValuePairs.end()
- || ssoAccountIdIter != m_profileKeyValuePairs.end())
- {
- if (ssoStartUrlIter != m_profileKeyValuePairs.end()
- && ssoRegionIter != m_profileKeyValuePairs.end()
- && ssoRoleNameIter != m_profileKeyValuePairs.end()
- && ssoAccountIdIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found sso_start_url " << ssoStartUrlIter->second);
- profile.SetSsoStartUrl(ssoStartUrlIter->second);
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found sso_region " << ssoRegionIter->second);
- profile.SetSsoRegion(ssoRegionIter->second);
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found sso_account_id " << ssoAccountIdIter->second);
- profile.SetSsoAccountId(ssoAccountIdIter->second);
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found sso_role_name " << ssoRoleNameIter->second);
- profile.SetSsoRoleName(ssoRoleNameIter->second);
- } else {
- AWS_LOGSTREAM_ERROR(PARSER_TAG, "invalid configuration for sso profile " << profile.GetName());
- }
- }
-
- auto assumeRoleArnIter = m_profileKeyValuePairs.find(ROLE_ARN_KEY);
- if (assumeRoleArnIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found role arn " << assumeRoleArnIter->second);
- profile.SetRoleArn(assumeRoleArnIter->second);
- }
-
- auto externalIdIter = m_profileKeyValuePairs.find(EXTERNAL_ID_KEY);
- if (externalIdIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found external id " << externalIdIter->second);
- profile.SetExternalId(externalIdIter->second);
- }
-
- auto sourceProfileIter = m_profileKeyValuePairs.find(SOURCE_PROFILE_KEY);
- if (sourceProfileIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found source profile " << sourceProfileIter->second);
- profile.SetSourceProfile(sourceProfileIter->second);
- }
-
- auto credentialProcessIter = m_profileKeyValuePairs.find(CREDENTIAL_PROCESS_COMMAND);
- if (credentialProcessIter != m_profileKeyValuePairs.end())
- {
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found credential process " << credentialProcessIter->second);
- profile.SetCredentialProcess(credentialProcessIter->second);
- }
- profile.SetAllKeyValPairs(m_profileKeyValuePairs);
-
- m_foundProfiles[profile.GetName()] = std::move(profile);
- m_currentWorkingProfile.clear();
- m_profileKeyValuePairs.clear();
- }
-
- if(!line.empty() && openPos != std::string::npos && closePos != std::string::npos)
- {
- m_currentWorkingProfile = StringUtils::Trim(line.substr(openPos + 1, closePos - openPos - 1).c_str());
- StringUtils::Replace(m_currentWorkingProfile, PROFILE_PREFIX, "");
- AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found profile " << m_currentWorkingProfile);
- }
- }
-
- enum State
- {
- START = 0,
- PROFILE_FOUND,
- PROFILE_KEY_VALUE_FOUND,
- FAILURE
- };
-
- Aws::String m_currentWorkingProfile;
- Aws::Map<String, String> m_profileKeyValuePairs;
- State m_parserState;
- Aws::Map<String, Profile> m_foundProfiles;
- };
-
- static const char* const CONFIG_FILE_LOADER = "Aws::Config::AWSConfigFileProfileConfigLoader";
-
- AWSConfigFileProfileConfigLoader::AWSConfigFileProfileConfigLoader(const Aws::String& fileName, bool useProfilePrefix) :
- m_fileName(fileName), m_useProfilePrefix(useProfilePrefix)
- {
- AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Initializing config loader against fileName "
- << fileName << " and using profilePrefix = " << useProfilePrefix);
- }
-
- bool AWSConfigFileProfileConfigLoader::LoadInternal()
- {
- m_profiles.clear();
-
- Aws::IFStream inputFile(m_fileName.c_str());
- if(inputFile)
- {
- ConfigFileProfileFSM parser;
- parser.ParseStream(inputFile);
- m_profiles = parser.GetProfiles();
- return m_profiles.size() > 0;
- }
-
- AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for reading.");
-
- return false;
- }
-
- bool AWSConfigFileProfileConfigLoader::PersistInternal(const Aws::Map<Aws::String, Profile>& profiles)
- {
- Aws::OFStream outputFile(m_fileName.c_str(), std::ios_base::out | std::ios_base::trunc);
- if(outputFile)
- {
- for(auto& profile : profiles)
- {
- Aws::String prefix = m_useProfilePrefix ? PROFILE_PREFIX : "";
-
- AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing profile " << profile.first << " to disk.");
-
- outputFile << LEFT_BRACKET << prefix << profile.second.GetName() << RIGHT_BRACKET << std::endl;
- const Aws::Auth::AWSCredentials& credentials = profile.second.GetCredentials();
- outputFile << ACCESS_KEY_ID_KEY << EQ << credentials.GetAWSAccessKeyId() << std::endl;
- outputFile << SECRET_KEY_KEY << EQ << credentials.GetAWSSecretKey() << std::endl;
-
- if(!credentials.GetSessionToken().empty())
- {
- outputFile << SESSION_TOKEN_KEY << EQ << credentials.GetSessionToken() << std::endl;
- }
-
- if(!profile.second.GetRegion().empty())
- {
- outputFile << REGION_KEY << EQ << profile.second.GetRegion() << std::endl;
- }
-
- if(!profile.second.GetRoleArn().empty())
- {
- outputFile << ROLE_ARN_KEY << EQ << profile.second.GetRoleArn() << std::endl;
- }
-
- if(!profile.second.GetSourceProfile().empty())
- {
- outputFile << SOURCE_PROFILE_KEY << EQ << profile.second.GetSourceProfile() << std::endl;
- }
-
- outputFile << std::endl;
- }
-
- AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Profiles written to config file " << m_fileName);
-
- return true;
- }
-
- AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for writing.");
-
- return false;
- }
-
- static const char* const EC2_INSTANCE_PROFILE_LOG_TAG = "Aws::Config::EC2InstanceProfileConfigLoader";
-
- EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const std::shared_ptr<Aws::Internal::EC2MetadataClient>& client)
- : m_ec2metadataClient(client == nullptr ? Aws::MakeShared<Aws::Internal::EC2MetadataClient>(EC2_INSTANCE_PROFILE_LOG_TAG) : client)
- {
- }
-
- bool EC2InstanceProfileConfigLoader::LoadInternal()
- {
- auto credentialsStr = m_ec2metadataClient->GetDefaultCredentialsSecurely();
- if(credentialsStr.empty()) return false;
-
- Json::JsonValue credentialsDoc(credentialsStr);
- if (!credentialsDoc.WasParseSuccessful())
- {
- AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG,
- "Failed to parse output from EC2MetadataService.");
- return false;
- }
- const char* accessKeyId = "AccessKeyId";
- const char* secretAccessKey = "SecretAccessKey";
- Aws::String accessKey, secretKey, token;
-
- auto credentialsView = credentialsDoc.View();
- accessKey = credentialsView.GetString(accessKeyId);
- AWS_LOGSTREAM_INFO(EC2_INSTANCE_PROFILE_LOG_TAG,
- "Successfully pulled credentials from metadata service with access key " << accessKey);
-
- secretKey = credentialsView.GetString(secretAccessKey);
- token = credentialsView.GetString("Token");
-
- auto region = m_ec2metadataClient->GetCurrentRegion();
-
- Profile profile;
- profile.SetCredentials(AWSCredentials(accessKey, secretKey, token));
- profile.SetRegion(region);
- profile.SetName(INSTANCE_PROFILE_KEY);
-
- m_profiles[INSTANCE_PROFILE_KEY] = profile;
-
- return true;
- }
-
- ConfigAndCredentialsCacheManager::ConfigAndCredentialsCacheManager() :
- m_credentialsFileLoader(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()),
- m_configFileLoader(Aws::Auth::GetConfigProfileFilename(), true/*use profile prefix*/)
- {
- ReloadCredentialsFile();
- ReloadConfigFile();
- }
-
- void ConfigAndCredentialsCacheManager::ReloadConfigFile()
- {
- Aws::Utils::Threading::WriterLockGuard guard(m_configLock);
- m_configFileLoader.SetFileName(Aws::Auth::GetConfigProfileFilename());
- m_configFileLoader.Load();
- }
-
- void ConfigAndCredentialsCacheManager::ReloadCredentialsFile()
- {
- Aws::Utils::Threading::WriterLockGuard guard(m_credentialsLock);
- m_credentialsFileLoader.SetFileName(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename());
- m_credentialsFileLoader.Load();
- }
-
- bool ConfigAndCredentialsCacheManager::HasConfigProfile(const Aws::String& profileName) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
- return (m_configFileLoader.GetProfiles().count(profileName) == 1);
- }
-
- Aws::Config::Profile ConfigAndCredentialsCacheManager::GetConfigProfile(const Aws::String& profileName) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
- const auto& profiles = m_configFileLoader.GetProfiles();
- const auto &iter = profiles.find(profileName);
- if (iter == profiles.end())
- {
- return {};
- }
- return iter->second;
- }
-
- Aws::Map<Aws::String, Aws::Config::Profile> ConfigAndCredentialsCacheManager::GetConfigProfiles() const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
- return m_configFileLoader.GetProfiles();
- }
-
- Aws::String ConfigAndCredentialsCacheManager::GetConfig(const Aws::String& profileName, const Aws::String& key) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
- const auto& profiles = m_configFileLoader.GetProfiles();
- const auto &iter = profiles.find(profileName);
- if (iter == profiles.end())
- {
- return {};
- }
- return iter->second.GetValue(key);
- }
-
- bool ConfigAndCredentialsCacheManager::HasCredentialsProfile(const Aws::String& profileName) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
- return (m_credentialsFileLoader.GetProfiles().count(profileName) == 1);
- }
-
- Aws::Config::Profile ConfigAndCredentialsCacheManager::GetCredentialsProfile(const Aws::String& profileName) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
- const auto &profiles = m_credentialsFileLoader.GetProfiles();
- const auto &iter = profiles.find(profileName);
- if (iter == profiles.end())
- {
- return {};
- }
- return iter->second;
- }
-
- Aws::Map<Aws::String, Aws::Config::Profile> ConfigAndCredentialsCacheManager::GetCredentialsProfiles() const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
- return m_credentialsFileLoader.GetProfiles();
- }
-
- Aws::Auth::AWSCredentials ConfigAndCredentialsCacheManager::GetCredentials(const Aws::String& profileName) const
- {
- Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
- const auto& profiles = m_credentialsFileLoader.GetProfiles();
- const auto &iter = profiles.find(profileName);
- if (iter == profiles.end())
- {
- return {};
- }
- return iter->second.GetCredentials();
- }
-
- void InitConfigAndCredentialsCacheManager()
- {
- if (s_configManager)
- {
- return;
- }
- s_configManager = Aws::MakeUnique<ConfigAndCredentialsCacheManager>(CONFIG_CREDENTIALS_CACHE_MANAGER_TAG);
- }
-
- void CleanupConfigAndCredentialsCacheManager()
- {
- if (!s_configManager)
- {
- return;
- }
- s_configManager = nullptr;
- }
-
- void ReloadCachedConfigFile()
- {
- assert(s_configManager);
- s_configManager->ReloadConfigFile();
- }
-
- void ReloadCachedCredentialsFile()
- {
- assert(s_configManager);
- s_configManager->ReloadCredentialsFile();
- }
-
- bool HasCachedConfigProfile(const Aws::String& profileName)
- {
- assert(s_configManager);
- return s_configManager->HasConfigProfile(profileName);
- }
-
- Aws::Config::Profile GetCachedConfigProfile(const Aws::String& profileName)
- {
- assert(s_configManager);
- return s_configManager->GetConfigProfile(profileName);
- }
-
- Aws::Map<Aws::String, Aws::Config::Profile> GetCachedConfigProfiles()
- {
- assert(s_configManager);
- return s_configManager->GetConfigProfiles();
- }
-
- Aws::String GetCachedConfigValue(const Aws::String &profileName, const Aws::String &key)
- {
- assert(s_configManager);
- return s_configManager->GetConfig(profileName, key);
- }
-
- Aws::String GetCachedConfigValue(const Aws::String &key)
- {
- assert(s_configManager);
- return s_configManager->GetConfig(Aws::Auth::GetConfigProfileName(), key);
- }
-
- bool HasCachedCredentialsProfile(const Aws::String& profileName)
- {
- assert(s_configManager);
- return s_configManager->HasCredentialsProfile(profileName);
- }
-
- Aws::Config::Profile GetCachedCredentialsProfile(const Aws::String &profileName)
- {
- assert(s_configManager);
- return s_configManager->GetCredentialsProfile(profileName);
- }
-
- Aws::Map<Aws::String, Aws::Config::Profile> GetCachedCredentialsProfiles()
- {
- assert(s_configManager);
- return s_configManager->GetCredentialsProfiles();
- }
-
- Aws::Auth::AWSCredentials GetCachedCredentials(const Aws::String &profileName)
- {
- assert(s_configManager);
- return s_configManager->GetCredentials(profileName);
- }
- } // Config namespace
-} // Aws namespace
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoaderBase.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoaderBase.cpp
new file mode 100644
index 00000000000..cb7b19d0ceb
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/AWSProfileConfigLoaderBase.cpp
@@ -0,0 +1,50 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/config/AWSProfileConfigLoaderBase.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <fstream>
+
+namespace Aws
+{
+ namespace Config
+ {
+ using namespace Aws::Utils;
+ using namespace Aws::Auth;
+
+ static const char* const CONFIG_LOADER_BASE_TAG = "Aws::Config::AWSProfileConfigLoaderBase";
+
+ bool AWSProfileConfigLoader::Load()
+ {
+ if(LoadInternal())
+ {
+ AWS_LOGSTREAM_INFO(CONFIG_LOADER_BASE_TAG, "Successfully reloaded configuration.");
+ m_lastLoadTime = DateTime::Now();
+ AWS_LOGSTREAM_TRACE(CONFIG_LOADER_BASE_TAG, "reloaded config at "
+ << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601));
+ return true;
+ }
+
+ AWS_LOGSTREAM_INFO(CONFIG_LOADER_BASE_TAG, "Failed to reload configuration.");
+ return false;
+ }
+
+ bool AWSProfileConfigLoader::PersistProfiles(const Aws::Map<Aws::String, Profile>& profiles)
+ {
+ if(PersistInternal(profiles))
+ {
+ AWS_LOGSTREAM_INFO(CONFIG_LOADER_BASE_TAG, "Successfully persisted configuration.");
+ m_profiles = profiles;
+ m_lastLoadTime = DateTime::Now();
+ AWS_LOGSTREAM_TRACE(CONFIG_LOADER_BASE_TAG, "persisted config at "
+ << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601));
+ return true;
+ }
+
+ AWS_LOGSTREAM_WARN(CONFIG_LOADER_BASE_TAG, "Failed to persist configuration.");
+ return false;
+ }
+ } // Config namespace
+} // Aws namespace
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/ConfigAndCredentialsCacheManager.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/ConfigAndCredentialsCacheManager.cpp
new file mode 100644
index 00000000000..b47fe72a0a2
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/ConfigAndCredentialsCacheManager.cpp
@@ -0,0 +1,206 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/config/ConfigAndCredentialsCacheManager.h>
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/utils/memory/stl/AWSList.h>
+#include <aws/core/utils/json/JsonSerializer.h>
+#include <fstream>
+
+namespace Aws
+{
+ namespace Config
+ {
+ using namespace Aws::Utils;
+ using namespace Aws::Auth;
+
+ #ifdef _MSC_VER
+ // VS2015 compiler's bug, warning s_CoreErrorsMapper: symbol will be dynamically initialized (implementation limitation)
+ AWS_SUPPRESS_WARNING(4592,
+ static ConfigAndCredentialsCacheManager* s_configManager(nullptr);
+ )
+ #else
+ static ConfigAndCredentialsCacheManager* s_configManager(nullptr);
+ #endif
+
+ static const char CONFIG_CREDENTIALS_CACHE_MANAGER_TAG[] = "ConfigAndCredentialsCacheManager";
+
+
+ ConfigAndCredentialsCacheManager::ConfigAndCredentialsCacheManager() :
+ m_credentialsFileLoader(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()),
+ m_configFileLoader(Aws::Auth::GetConfigProfileFilename(), true/*use profile prefix*/)
+ {
+ ReloadCredentialsFile();
+ ReloadConfigFile();
+ }
+
+ void ConfigAndCredentialsCacheManager::ReloadConfigFile()
+ {
+ Aws::Utils::Threading::WriterLockGuard guard(m_configLock);
+ m_configFileLoader.SetFileName(Aws::Auth::GetConfigProfileFilename());
+ m_configFileLoader.Load();
+ }
+
+ void ConfigAndCredentialsCacheManager::ReloadCredentialsFile()
+ {
+ Aws::Utils::Threading::WriterLockGuard guard(m_credentialsLock);
+ m_credentialsFileLoader.SetFileName(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename());
+ m_credentialsFileLoader.Load();
+ }
+
+ bool ConfigAndCredentialsCacheManager::HasConfigProfile(const Aws::String& profileName) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
+ return (m_configFileLoader.GetProfiles().count(profileName) == 1);
+ }
+
+ Aws::Config::Profile ConfigAndCredentialsCacheManager::GetConfigProfile(const Aws::String& profileName) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
+ const auto& profiles = m_configFileLoader.GetProfiles();
+ const auto &iter = profiles.find(profileName);
+ if (iter == profiles.end())
+ {
+ return {};
+ }
+ return iter->second;
+ }
+
+ Aws::Map<Aws::String, Aws::Config::Profile> ConfigAndCredentialsCacheManager::GetConfigProfiles() const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
+ return m_configFileLoader.GetProfiles();
+ }
+
+ Aws::String ConfigAndCredentialsCacheManager::GetConfig(const Aws::String& profileName, const Aws::String& key) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_configLock);
+ const auto& profiles = m_configFileLoader.GetProfiles();
+ const auto &iter = profiles.find(profileName);
+ if (iter == profiles.end())
+ {
+ return {};
+ }
+ return iter->second.GetValue(key);
+ }
+
+ bool ConfigAndCredentialsCacheManager::HasCredentialsProfile(const Aws::String& profileName) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
+ return (m_credentialsFileLoader.GetProfiles().count(profileName) == 1);
+ }
+
+ Aws::Config::Profile ConfigAndCredentialsCacheManager::GetCredentialsProfile(const Aws::String& profileName) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
+ const auto &profiles = m_credentialsFileLoader.GetProfiles();
+ const auto &iter = profiles.find(profileName);
+ if (iter == profiles.end())
+ {
+ return {};
+ }
+ return iter->second;
+ }
+
+ Aws::Map<Aws::String, Aws::Config::Profile> ConfigAndCredentialsCacheManager::GetCredentialsProfiles() const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
+ return m_credentialsFileLoader.GetProfiles();
+ }
+
+ Aws::Auth::AWSCredentials ConfigAndCredentialsCacheManager::GetCredentials(const Aws::String& profileName) const
+ {
+ Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock);
+ const auto& profiles = m_credentialsFileLoader.GetProfiles();
+ const auto &iter = profiles.find(profileName);
+ if (iter == profiles.end())
+ {
+ return {};
+ }
+ return iter->second.GetCredentials();
+ }
+
+ void InitConfigAndCredentialsCacheManager()
+ {
+ if (s_configManager)
+ {
+ return;
+ }
+ s_configManager = Aws::New<ConfigAndCredentialsCacheManager>(CONFIG_CREDENTIALS_CACHE_MANAGER_TAG);
+ }
+
+ void CleanupConfigAndCredentialsCacheManager()
+ {
+ Aws::Delete(s_configManager);
+ s_configManager = nullptr;
+ }
+
+ void ReloadCachedConfigFile()
+ {
+ assert(s_configManager);
+ s_configManager->ReloadConfigFile();
+ }
+
+ void ReloadCachedCredentialsFile()
+ {
+ assert(s_configManager);
+ s_configManager->ReloadCredentialsFile();
+ }
+
+ bool HasCachedConfigProfile(const Aws::String& profileName)
+ {
+ assert(s_configManager);
+ return s_configManager->HasConfigProfile(profileName);
+ }
+
+ Aws::Config::Profile GetCachedConfigProfile(const Aws::String& profileName)
+ {
+ assert(s_configManager);
+ return s_configManager->GetConfigProfile(profileName);
+ }
+
+ Aws::Map<Aws::String, Aws::Config::Profile> GetCachedConfigProfiles()
+ {
+ assert(s_configManager);
+ return s_configManager->GetConfigProfiles();
+ }
+
+ Aws::String GetCachedConfigValue(const Aws::String &profileName, const Aws::String &key)
+ {
+ assert(s_configManager);
+ return s_configManager->GetConfig(profileName, key);
+ }
+
+ Aws::String GetCachedConfigValue(const Aws::String &key)
+ {
+ assert(s_configManager);
+ return s_configManager->GetConfig(Aws::Auth::GetConfigProfileName(), key);
+ }
+
+ bool HasCachedCredentialsProfile(const Aws::String& profileName)
+ {
+ assert(s_configManager);
+ return s_configManager->HasCredentialsProfile(profileName);
+ }
+
+ Aws::Config::Profile GetCachedCredentialsProfile(const Aws::String &profileName)
+ {
+ assert(s_configManager);
+ return s_configManager->GetCredentialsProfile(profileName);
+ }
+
+ Aws::Map<Aws::String, Aws::Config::Profile> GetCachedCredentialsProfiles()
+ {
+ assert(s_configManager);
+ return s_configManager->GetCredentialsProfiles();
+ }
+
+ Aws::Auth::AWSCredentials GetCachedCredentials(const Aws::String &profileName)
+ {
+ assert(s_configManager);
+ return s_configManager->GetCredentials(profileName);
+ }
+ } // Config namespace
+} // Aws namespace
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp
new file mode 100644
index 00000000000..0b505b2c003
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp
@@ -0,0 +1,112 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/config/AWSProfileConfigLoader.h>
+#include <aws/core/internal/AWSHttpResourceClient.h>
+#include <aws/core/auth/AWSCredentialsProvider.h>
+#include <aws/core/utils/memory/stl/AWSList.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/json/JsonSerializer.h>
+#include <fstream>
+#include <random>
+
+namespace Aws
+{
+ namespace Config
+ {
+ using namespace Aws::Utils;
+ using namespace Aws::Auth;
+
+ static const char* const INTERNAL_EXCEPTION_PHRASE = "InternalServiceException";
+ static const int64_t FIVE_MINUTE_MILLIS = 60000 * 5;
+ static const int64_t TEN_MINUTE_MILLIS = 60000 * 10;
+
+ static const char* const EC2_INSTANCE_PROFILE_LOG_TAG = "Aws::Config::EC2InstanceProfileConfigLoader";
+
+ EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const std::shared_ptr<Aws::Internal::EC2MetadataClient>& client)
+ {
+ if(client == nullptr)
+ {
+ Aws::Internal::InitEC2MetadataClient();
+ m_ec2metadataClient = Aws::Internal::GetEC2MetadataClient();
+ }
+ else
+ {
+ m_ec2metadataClient = client;
+ }
+ }
+
+ bool EC2InstanceProfileConfigLoader::LoadInternal()
+ {
+ // re-use old credentials until we need to call IMDS again.
+ if (DateTime::Now().Millis() < this->credentialsValidUntilMillis) {
+ AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG,
+ "Skipping IMDS call until " << this->credentialsValidUntilMillis);
+ return true;
+ }
+ this->credentialsValidUntilMillis = DateTime::Now().Millis();
+
+ if (!m_ec2metadataClient) {
+ AWS_LOGSTREAM_FATAL(EC2_INSTANCE_PROFILE_LOG_TAG, "EC2MetadataClient is a nullptr!")
+ return false;
+ }
+ auto credentialsStr = m_ec2metadataClient->GetDefaultCredentialsSecurely();
+ if(credentialsStr.empty()) return false;
+
+ Json::JsonValue credentialsDoc(credentialsStr);
+ if (!credentialsDoc.WasParseSuccessful())
+ {
+ AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG,
+ "Failed to parse output from EC2MetadataService.");
+ return false;
+ }
+
+ const char* accessKeyId = "AccessKeyId";
+ const char* secretAccessKey = "SecretAccessKey";
+ const char* expiration = "Expiration";
+ const char* code = "Code";
+ Aws::String accessKey, secretKey, token;
+
+ auto credentialsView = credentialsDoc.View();
+ DateTime expirationTime(credentialsView.GetString(expiration), Aws::Utils::DateFormat::ISO_8601);
+ // re-use old credentials and not block if the IMDS call failed or if the latest credential is in the past
+ if (expirationTime.WasParseSuccessful() && DateTime::Now() > expirationTime) {
+ AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG,
+ "Expiration Time of Credentials in the past, refusing to update credentials");
+ this->credentialsValidUntilMillis = DateTime::Now().Millis() + calculateRetryTime();
+ return true;
+ } else if (credentialsView.GetString(code) == INTERNAL_EXCEPTION_PHRASE) {
+ AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG,
+ "IMDS call failed, refusing to update credentials");
+ this->credentialsValidUntilMillis = DateTime::Now().Millis() + calculateRetryTime();
+ return true;
+ }
+ accessKey = credentialsView.GetString(accessKeyId);
+ AWS_LOGSTREAM_INFO(EC2_INSTANCE_PROFILE_LOG_TAG,
+ "Successfully pulled credentials from metadata service with access key " << accessKey);
+
+ secretKey = credentialsView.GetString(secretAccessKey);
+ token = credentialsView.GetString("Token");
+
+ auto region = m_ec2metadataClient->GetCurrentRegion();
+
+ Profile profile;
+ profile.SetCredentials(AWSCredentials(accessKey, secretKey, token));
+ profile.SetRegion(region);
+ profile.SetName(INSTANCE_PROFILE_KEY);
+
+ m_profiles[INSTANCE_PROFILE_KEY] = profile;
+
+ return true;
+ }
+
+ int64_t EC2InstanceProfileConfigLoader::calculateRetryTime() const {
+ std::random_device rd;
+ std::mt19937_64 gen(rd());
+ std::uniform_int_distribution<int64_t> dist(FIVE_MINUTE_MILLIS, TEN_MINUTE_MILLIS);
+ return dist(gen);
+ }
+ } // Config namespace
+} // Aws namespace
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/defaults/ClientConfigurationDefaults.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/defaults/ClientConfigurationDefaults.cpp
new file mode 100644
index 00000000000..7b54066fb3f
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/config/defaults/ClientConfigurationDefaults.cpp
@@ -0,0 +1,197 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+/**
+ * Please note that this file is autogenerated.
+ * The backwards compatibility of the default values provided by new client configuration defaults is not guaranteed;
+ * the values might change over time.
+ */
+
+#include <aws/common/platform.h> // for AWS_OS_IOS macro
+#include <aws/core/config/defaults/ClientConfigurationDefaults.h>
+#include <aws/core/config/AWSProfileConfigLoader.h>
+#include <aws/core/client/ClientConfiguration.h>
+#include <aws/core/internal/AWSHttpResourceClient.h>
+#include <aws/core/platform/Environment.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
+
+namespace Aws
+{
+ namespace Config
+ {
+ namespace Defaults
+ {
+ static const char* CLIENT_CONFIG_DEFAULTS_TAG = "ClientConfigurationDefaults";
+
+ void SetSmartDefaultsConfigurationParameters(Aws::Client::ClientConfiguration& clientConfig,
+ const Aws::String& defaultMode,
+ bool hasEc2MetadataRegion,
+ const Aws::String& ec2MetadataRegion)
+ {
+ const Aws::String caseInsensitiveMode = ResolveDefaultModeName(clientConfig,
+ defaultMode,
+ Aws::Config::GetCachedConfigValue("defaults_mode"),
+ hasEc2MetadataRegion,
+ ec2MetadataRegion);
+
+ if(caseInsensitiveMode == "legacy")
+ {
+ return SetLegacyClientConfiguration(clientConfig);
+ }
+
+ if(caseInsensitiveMode == "standard")
+ {
+ return SetStandardClientConfiguration(clientConfig);
+ }
+
+ if(caseInsensitiveMode == "in-region")
+ {
+ return SetInRegionClientConfiguration(clientConfig);
+ }
+
+ if(caseInsensitiveMode == "cross-region")
+ {
+ return SetCrossRegionClientConfiguration(clientConfig);
+ }
+
+ if(caseInsensitiveMode == "mobile")
+ {
+ return SetMobileClientConfiguration(clientConfig);
+ }
+ return SetLegacyClientConfiguration(clientConfig);
+ }
+
+ bool isMobile()
+ {
+#if defined(AWS_OS_IOS) || defined (__ANDROID__)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ const char* ResolveAutoClientConfiguration(const Aws::Client::ClientConfiguration& clientConfig,
+ const Aws::String& ec2MetadataRegion)
+ {
+ // Check if we're on mobile, CPP SDK is statically built, so we can check how we were built
+ if(isMobile())
+ {
+ return "mobile";
+ }
+ // We're not on mobile (best we can tell). See if we can determine whether we're an in-region or
+ // cross-region client.
+ Aws::String current_region;
+ Aws::String env_region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION");
+ if(!Aws::Environment::GetEnv("AWS_EXECUTION_ENV").empty())
+ {
+ // We're running in an AWS service environment, so we can trust the region environment variables
+ // to be the current region, if they're set
+ current_region = Aws::Environment::GetEnv("AWS_REGION");
+ if(current_region.empty())
+ {
+ current_region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION");
+ }
+ }
+ if(current_region.empty())
+ {
+ current_region = ec2MetadataRegion;
+ }
+ if(!current_region.empty() && !clientConfig.region.empty())
+ {
+ if(current_region == clientConfig.region)
+ {
+ return "in-region";
+ }
+ else
+ {
+ return "cross-region";
+ }
+ }
+ // We don't seem to be mobile, and we couldn't determine whether we're running within an AWS region.
+ // Fall back to standard.
+ return "standard";
+ }
+
+ void SetLegacyClientConfiguration(Aws::Client::ClientConfiguration& clientConfig)
+ {
+ clientConfig.retryStrategy = Aws::Client::InitRetryStrategy("default");
+ }
+
+ void SetStandardClientConfiguration(Aws::Client::ClientConfiguration& clientConfig)
+ {
+ clientConfig.connectTimeoutMs = 3100;
+ clientConfig.retryStrategy = Aws::Client::InitRetryStrategy("standard");
+ }
+
+ void SetInRegionClientConfiguration(Aws::Client::ClientConfiguration& clientConfig)
+ {
+ clientConfig.connectTimeoutMs = 1100;
+ clientConfig.retryStrategy = Aws::Client::InitRetryStrategy("standard");
+ }
+
+ void SetCrossRegionClientConfiguration(Aws::Client::ClientConfiguration& clientConfig)
+ {
+ clientConfig.connectTimeoutMs = 3100;
+ clientConfig.retryStrategy = Aws::Client::InitRetryStrategy("standard");
+ }
+
+ void SetMobileClientConfiguration(Aws::Client::ClientConfiguration& clientConfig)
+ {
+ clientConfig.connectTimeoutMs = 30000;
+ clientConfig.retryStrategy = Aws::Client::InitRetryStrategy("standard");
+ }
+
+ Aws::String ResolveDefaultModeName(const Aws::Client::ClientConfiguration& clientConfig,
+ Aws::String requestedDefaultMode,
+ const Aws::String& configFileDefaultMode,
+ bool hasEc2MetadataRegion,
+ Aws::String ec2MetadataRegion)
+ {
+ if (requestedDefaultMode.empty())
+ {
+ requestedDefaultMode = Aws::Environment::GetEnv("AWS_DEFAULTS_MODE");
+ }
+ if (requestedDefaultMode.empty())
+ {
+ requestedDefaultMode = configFileDefaultMode;
+ }
+ if (Aws::Utils::StringUtils::ToLower(requestedDefaultMode.c_str()) == "auto")
+ {
+ if (!hasEc2MetadataRegion &&
+ Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
+ {
+ auto client = Aws::Internal::GetEC2MetadataClient();
+ if (client)
+ {
+ ec2MetadataRegion = client->GetCurrentRegion();
+ }
+ }
+ requestedDefaultMode = ResolveAutoClientConfiguration(clientConfig, ec2MetadataRegion);
+ return requestedDefaultMode;
+ }
+ if (requestedDefaultMode.empty())
+ {
+ requestedDefaultMode = "legacy";
+ return requestedDefaultMode;
+ }
+
+ requestedDefaultMode = Aws::Utils::StringUtils::ToLower(requestedDefaultMode.c_str());
+ if (requestedDefaultMode != "legacy" &&
+ requestedDefaultMode != "standard" &&
+ requestedDefaultMode != "in-region" &&
+ requestedDefaultMode != "cross-region" &&
+ requestedDefaultMode != "mobile")
+ {
+ AWS_LOGSTREAM_WARN(CLIENT_CONFIG_DEFAULTS_TAG, "User specified client configuration: ["
+ << requestedDefaultMode
+ << "] is not found, will use the SDK default legacy one.");
+ requestedDefaultMode = "legacy";
+ }
+ return requestedDefaultMode;
+ }
+ } //namespace Defaults
+ } //namespace Config
+} //namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSEndpoint.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSEndpoint.cpp
new file mode 100644
index 00000000000..4990faff243
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSEndpoint.cpp
@@ -0,0 +1,86 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/AWSEndpoint.h>
+#include <aws/core/utils/DNS.h>
+
+namespace Aws
+{
+namespace Endpoint
+{
+
+Aws::String AWSEndpoint::GetURL() const
+{
+ return m_uri.GetURIString();
+}
+
+void AWSEndpoint::SetURL(Aws::String url)
+{
+ m_uri = std::move(url);
+}
+
+const Aws::Http::URI& AWSEndpoint::GetURI() const
+{
+ return m_uri;
+}
+
+void AWSEndpoint::SetURI(Aws::Http::URI uri)
+{
+ m_uri = std::move(uri);
+}
+
+AWSEndpoint::OptionalError AWSEndpoint::AddPrefixIfMissing(const Aws::String& prefix)
+{
+ if (m_uri.GetAuthority().rfind(prefix, 0) == 0)
+ {
+ // uri already starts with a prefix
+ return OptionalError();
+ }
+
+ if (Aws::Utils::IsValidHost(prefix + m_uri.GetAuthority()))
+ {
+ m_uri.SetAuthority(prefix + m_uri.GetAuthority());
+ return OptionalError();
+ }
+
+ return OptionalError(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::ENDPOINT_RESOLUTION_FAILURE, "",
+ Aws::String("Failed to add host prefix, resulting uri is an invalid hostname: ") + prefix + m_uri.GetAuthority(),
+ false/*retryable*/));
+}
+
+void AWSEndpoint::SetQueryString(const Aws::String& queryString)
+{
+ m_uri.SetQueryString(queryString);
+}
+
+const Crt::Optional<AWSEndpoint::EndpointAttributes>& AWSEndpoint::GetAttributes() const
+{
+ return m_attributes;
+}
+
+Crt::Optional<AWSEndpoint::EndpointAttributes>& AWSEndpoint::AccessAttributes()
+{
+ return m_attributes;
+}
+
+void AWSEndpoint::SetAttributes(AWSEndpoint::EndpointAttributes&& attributes)
+{
+ m_attributes = std::move(attributes);
+}
+
+const Aws::UnorderedMap<Aws::String, Aws::String>& AWSEndpoint::GetHeaders() const
+{
+ return m_headers;
+}
+
+void AWSEndpoint::SetHeaders(Aws::UnorderedMap<Aws::String, Aws::String> headers)
+{
+ m_headers = std::move(headers);
+}
+
+} // namespace Endpoint
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSPartitions.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSPartitions.cpp
new file mode 100644
index 00000000000..bfe3cf6147b
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/AWSPartitions.cpp
@@ -0,0 +1,153 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/AWSPartitions.h>
+#include <aws/core/utils/memory/stl/AWSArray.h>
+
+namespace Aws
+{
+namespace Endpoint
+{
+const size_t AWSPartitions::PartitionsBlobStrLen = 3166;
+const size_t AWSPartitions::PartitionsBlobSize = 3167;
+
+using PartitionsBlobT = Aws::Array<const char, AWSPartitions::PartitionsBlobSize>;
+static constexpr PartitionsBlobT PartitionsBlob = {{
+'{','"','p','a','r','t','i','t','i','o','n','s','"',':','[','{','"','i','d','"',':','"','a','w','s',
+'"',',','"','o','u','t','p','u','t','s','"',':','{','"','d','n','s','S','u','f','f','i','x','"',':',
+'"','a','m','a','z','o','n','a','w','s','.','c','o','m','"',',','"','d','u','a','l','S','t','a','c',
+'k','D','n','s','S','u','f','f','i','x','"',':','"','a','p','i','.','a','w','s','"',',','"','n','a',
+'m','e','"',':','"','a','w','s','"',',','"','s','u','p','p','o','r','t','s','D','u','a','l','S','t',
+'a','c','k','"',':','t','r','u','e',',','"','s','u','p','p','o','r','t','s','F','I','P','S','"',':',
+'t','r','u','e','}',',','"','r','e','g','i','o','n','R','e','g','e','x','"',':','"','^','(','u','s',
+'|','e','u','|','a','p','|','s','a','|','c','a','|','m','e','|','a','f',')','\\','\\','-','\\','\\','w',
+'+','\\','\\','-','\\','\\','d','+','$','"',',','"','r','e','g','i','o','n','s','"',':','{','"','a','f',
+'-','s','o','u','t','h','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':',
+'"','A','f','r','i','c','a',' ','(','C','a','p','e',' ','T','o','w','n',')','"','}',',','"','a','p',
+'-','e','a','s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"',
+'A','s','i','a',' ','P','a','c','i','f','i','c',' ','(','H','o','n','g',' ','K','o','n','g',')','"',
+'}',',','"','a','p','-','n','o','r','t','h','e','a','s','t','-','1','"',':','{','"','d','e','s','c',
+'r','i','p','t','i','o','n','"',':','"','A','s','i','a',' ','P','a','c','i','f','i','c',' ','(','T',
+'o','k','y','o',')','"','}',',','"','a','p','-','n','o','r','t','h','e','a','s','t','-','2','"',':',
+'{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','s','i','a',' ','P','a','c','i',
+'f','i','c',' ','(','S','e','o','u','l',')','"','}',',','"','a','p','-','n','o','r','t','h','e','a',
+'s','t','-','3','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','s','i',
+'a',' ','P','a','c','i','f','i','c',' ','(','O','s','a','k','a',')','"','}',',','"','a','p','-','s',
+'o','u','t','h','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A',
+'s','i','a',' ','P','a','c','i','f','i','c',' ','(','M','u','m','b','a','i',')','"','}',',','"','a',
+'p','-','s','o','u','t','h','-','2','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',
+':','"','A','s','i','a',' ','P','a','c','i','f','i','c',' ','(','H','y','d','e','r','a','b','a','d',
+')','"','}',',','"','a','p','-','s','o','u','t','h','e','a','s','t','-','1','"',':','{','"','d','e',
+'s','c','r','i','p','t','i','o','n','"',':','"','A','s','i','a',' ','P','a','c','i','f','i','c',' ',
+'(','S','i','n','g','a','p','o','r','e',')','"','}',',','"','a','p','-','s','o','u','t','h','e','a',
+'s','t','-','2','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','s','i',
+'a',' ','P','a','c','i','f','i','c',' ','(','S','y','d','n','e','y',')','"','}',',','"','a','p','-',
+'s','o','u','t','h','e','a','s','t','-','3','"',':','{','"','d','e','s','c','r','i','p','t','i','o',
+'n','"',':','"','A','s','i','a',' ','P','a','c','i','f','i','c',' ','(','J','a','k','a','r','t','a',
+')','"','}',',','"','a','p','-','s','o','u','t','h','e','a','s','t','-','4','"',':','{','"','d','e',
+'s','c','r','i','p','t','i','o','n','"',':','"','A','s','i','a',' ','P','a','c','i','f','i','c',' ',
+'(','M','e','l','b','o','u','r','n','e',')','"','}',',','"','a','w','s','-','g','l','o','b','a','l',
+'"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','W','S',' ','S','t','a',
+'n','d','a','r','d',' ','g','l','o','b','a','l',' ','r','e','g','i','o','n','"','}',',','"','c','a',
+'-','c','e','n','t','r','a','l','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n',
+'"',':','"','C','a','n','a','d','a',' ','(','C','e','n','t','r','a','l',')','"','}',',','"','e','u',
+'-','c','e','n','t','r','a','l','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n',
+'"',':','"','E','u','r','o','p','e',' ','(','F','r','a','n','k','f','u','r','t',')','"','}',',','"',
+'e','u','-','c','e','n','t','r','a','l','-','2','"',':','{','"','d','e','s','c','r','i','p','t','i',
+'o','n','"',':','"','E','u','r','o','p','e',' ','(','Z','u','r','i','c','h',')','"','}',',','"','e',
+'u','-','n','o','r','t','h','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',
+':','"','E','u','r','o','p','e',' ','(','S','t','o','c','k','h','o','l','m',')','"','}',',','"','e',
+'u','-','s','o','u','t','h','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',
+':','"','E','u','r','o','p','e',' ','(','M','i','l','a','n',')','"','}',',','"','e','u','-','s','o',
+'u','t','h','-','2','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','E','u',
+'r','o','p','e',' ','(','S','p','a','i','n',')','"','}',',','"','e','u','-','w','e','s','t','-','1',
+'"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','E','u','r','o','p','e',' ',
+'(','I','r','e','l','a','n','d',')','"','}',',','"','e','u','-','w','e','s','t','-','2','"',':','{',
+'"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','E','u','r','o','p','e',' ','(','L','o',
+'n','d','o','n',')','"','}',',','"','e','u','-','w','e','s','t','-','3','"',':','{','"','d','e','s',
+'c','r','i','p','t','i','o','n','"',':','"','E','u','r','o','p','e',' ','(','P','a','r','i','s',')',
+'"','}',',','"','m','e','-','c','e','n','t','r','a','l','-','1','"',':','{','"','d','e','s','c','r',
+'i','p','t','i','o','n','"',':','"','M','i','d','d','l','e',' ','E','a','s','t',' ','(','U','A','E',
+')','"','}',',','"','m','e','-','s','o','u','t','h','-','1','"',':','{','"','d','e','s','c','r','i',
+'p','t','i','o','n','"',':','"','M','i','d','d','l','e',' ','E','a','s','t',' ','(','B','a','h','r',
+'a','i','n',')','"','}',',','"','s','a','-','e','a','s','t','-','1','"',':','{','"','d','e','s','c',
+'r','i','p','t','i','o','n','"',':','"','S','o','u','t','h',' ','A','m','e','r','i','c','a',' ','(',
+'S','a','o',' ','P','a','u','l','o',')','"','}',',','"','u','s','-','e','a','s','t','-','1','"',':',
+'{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','U','S',' ','E','a','s','t',' ','(',
+'N','.',' ','V','i','r','g','i','n','i','a',')','"','}',',','"','u','s','-','e','a','s','t','-','2',
+'"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','U','S',' ','E','a','s','t',
+' ','(','O','h','i','o',')','"','}',',','"','u','s','-','w','e','s','t','-','1','"',':','{','"','d',
+'e','s','c','r','i','p','t','i','o','n','"',':','"','U','S',' ','W','e','s','t',' ','(','N','.',' ',
+'C','a','l','i','f','o','r','n','i','a',')','"','}',',','"','u','s','-','w','e','s','t','-','2','"',
+':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','U','S',' ','W','e','s','t',' ',
+'(','O','r','e','g','o','n',')','"','}','}','}',',','{','"','i','d','"',':','"','a','w','s','-','c',
+'n','"',',','"','o','u','t','p','u','t','s','"',':','{','"','d','n','s','S','u','f','f','i','x','"',
+':','"','a','m','a','z','o','n','a','w','s','.','c','o','m','.','c','n','"',',','"','d','u','a','l',
+'S','t','a','c','k','D','n','s','S','u','f','f','i','x','"',':','"','a','p','i','.','a','m','a','z',
+'o','n','w','e','b','s','e','r','v','i','c','e','s','.','c','o','m','.','c','n','"',',','"','n','a',
+'m','e','"',':','"','a','w','s','-','c','n','"',',','"','s','u','p','p','o','r','t','s','D','u','a',
+'l','S','t','a','c','k','"',':','t','r','u','e',',','"','s','u','p','p','o','r','t','s','F','I','P',
+'S','"',':','t','r','u','e','}',',','"','r','e','g','i','o','n','R','e','g','e','x','"',':','"','^',
+'c','n','\\','\\','-','\\','\\','w','+','\\','\\','-','\\','\\','d','+','$','"',',','"','r','e','g','i','o',
+'n','s','"',':','{','"','a','w','s','-','c','n','-','g','l','o','b','a','l','"',':','{','"','d','e',
+'s','c','r','i','p','t','i','o','n','"',':','"','A','W','S',' ','C','h','i','n','a',' ','g','l','o',
+'b','a','l',' ','r','e','g','i','o','n','"','}',',','"','c','n','-','n','o','r','t','h','-','1','"',
+':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','C','h','i','n','a',' ','(','B',
+'e','i','j','i','n','g',')','"','}',',','"','c','n','-','n','o','r','t','h','w','e','s','t','-','1',
+'"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','C','h','i','n','a',' ','(',
+'N','i','n','g','x','i','a',')','"','}','}','}',',','{','"','i','d','"',':','"','a','w','s','-','u',
+'s','-','g','o','v','"',',','"','o','u','t','p','u','t','s','"',':','{','"','d','n','s','S','u','f',
+'f','i','x','"',':','"','a','m','a','z','o','n','a','w','s','.','c','o','m','"',',','"','d','u','a',
+'l','S','t','a','c','k','D','n','s','S','u','f','f','i','x','"',':','"','a','p','i','.','a','w','s',
+'"',',','"','n','a','m','e','"',':','"','a','w','s','-','u','s','-','g','o','v','"',',','"','s','u',
+'p','p','o','r','t','s','D','u','a','l','S','t','a','c','k','"',':','t','r','u','e',',','"','s','u',
+'p','p','o','r','t','s','F','I','P','S','"',':','t','r','u','e','}',',','"','r','e','g','i','o','n',
+'R','e','g','e','x','"',':','"','^','u','s','\\','\\','-','g','o','v','\\','\\','-','\\','\\','w','+','\\',
+'\\','-','\\','\\','d','+','$','"',',','"','r','e','g','i','o','n','s','"',':','{','"','a','w','s','-',
+'u','s','-','g','o','v','-','g','l','o','b','a','l','"',':','{','"','d','e','s','c','r','i','p','t',
+'i','o','n','"',':','"','A','W','S',' ','G','o','v','C','l','o','u','d',' ','(','U','S',')',' ','g',
+'l','o','b','a','l',' ','r','e','g','i','o','n','"','}',',','"','u','s','-','g','o','v','-','e','a',
+'s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','W','S',
+' ','G','o','v','C','l','o','u','d',' ','(','U','S','-','E','a','s','t',')','"','}',',','"','u','s',
+'-','g','o','v','-','w','e','s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o',
+'n','"',':','"','A','W','S',' ','G','o','v','C','l','o','u','d',' ','(','U','S','-','W','e','s','t',
+')','"','}','}','}',',','{','"','i','d','"',':','"','a','w','s','-','i','s','o','"',',','"','o','u',
+'t','p','u','t','s','"',':','{','"','d','n','s','S','u','f','f','i','x','"',':','"','c','2','s','.',
+'i','c','.','g','o','v','"',',','"','d','u','a','l','S','t','a','c','k','D','n','s','S','u','f','f',
+'i','x','"',':','"','c','2','s','.','i','c','.','g','o','v','"',',','"','n','a','m','e','"',':','"',
+'a','w','s','-','i','s','o','"',',','"','s','u','p','p','o','r','t','s','D','u','a','l','S','t','a',
+'c','k','"',':','f','a','l','s','e',',','"','s','u','p','p','o','r','t','s','F','I','P','S','"',':',
+'t','r','u','e','}',',','"','r','e','g','i','o','n','R','e','g','e','x','"',':','"','^','u','s','\\',
+'\\','-','i','s','o','\\','\\','-','\\','\\','w','+','\\','\\','-','\\','\\','d','+','$','"',',','"','r','e',
+'g','i','o','n','s','"',':','{','"','a','w','s','-','i','s','o','-','g','l','o','b','a','l','"',':',
+'{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','A','W','S',' ','I','S','O',' ','(',
+'U','S',')',' ','g','l','o','b','a','l',' ','r','e','g','i','o','n','"','}',',','"','u','s','-','i',
+'s','o','-','e','a','s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',
+':','"','U','S',' ','I','S','O',' ','E','a','s','t','"','}',',','"','u','s','-','i','s','o','-','w',
+'e','s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"','U','S',
+' ','I','S','O',' ','W','E','S','T','"','}','}','}',',','{','"','i','d','"',':','"','a','w','s','-',
+'i','s','o','-','b','"',',','"','o','u','t','p','u','t','s','"',':','{','"','d','n','s','S','u','f',
+'f','i','x','"',':','"','s','c','2','s','.','s','g','o','v','.','g','o','v','"',',','"','d','u','a',
+'l','S','t','a','c','k','D','n','s','S','u','f','f','i','x','"',':','"','s','c','2','s','.','s','g',
+'o','v','.','g','o','v','"',',','"','n','a','m','e','"',':','"','a','w','s','-','i','s','o','-','b',
+'"',',','"','s','u','p','p','o','r','t','s','D','u','a','l','S','t','a','c','k','"',':','f','a','l',
+'s','e',',','"','s','u','p','p','o','r','t','s','F','I','P','S','"',':','t','r','u','e','}',',','"',
+'r','e','g','i','o','n','R','e','g','e','x','"',':','"','^','u','s','\\','\\','-','i','s','o','b','\\',
+'\\','-','\\','\\','w','+','\\','\\','-','\\','\\','d','+','$','"',',','"','r','e','g','i','o','n','s','"',
+':','{','"','a','w','s','-','i','s','o','-','b','-','g','l','o','b','a','l','"',':','{','"','d','e',
+'s','c','r','i','p','t','i','o','n','"',':','"','A','W','S',' ','I','S','O','B',' ','(','U','S',')',
+' ','g','l','o','b','a','l',' ','r','e','g','i','o','n','"','}',',','"','u','s','-','i','s','o','b',
+'-','e','a','s','t','-','1','"',':','{','"','d','e','s','c','r','i','p','t','i','o','n','"',':','"',
+'U','S',' ','I','S','O','B',' ','E','a','s','t',' ','(','O','h','i','o',')','"','}','}','}',']',',',
+'"','v','e','r','s','i','o','n','"',':','"','1','.','1','"','}','\0'
+}};
+
+const char* AWSPartitions::GetPartitionsBlob()
+{
+ return PartitionsBlob.data();
+}
+
+} // namespace Endpoint
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/BuiltInParameters.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/BuiltInParameters.cpp
new file mode 100644
index 00000000000..43c3e2f0f94
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/BuiltInParameters.cpp
@@ -0,0 +1,135 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/BuiltInParameters.h>
+#include <aws/core/utils/logging/LogMacros.h>
+
+static const char ENDPOINT_BUILTIN_LOG_TAG[] = "EndpointBuiltInParameters";
+
+namespace Aws
+{
+namespace Endpoint
+{
+ void BuiltInParameters::OverrideEndpoint(const Aws::String& endpoint, const Aws::Http::Scheme& scheme)
+ {
+ static const char* SDK_ENDPOINT = "Endpoint";
+
+ if (endpoint.compare(0, 7, "http://") == 0 || endpoint.compare(0, 8, "https://") == 0)
+ {
+ SetStringParameter(SDK_ENDPOINT, endpoint);
+ }
+ else
+ {
+ SetStringParameter(SDK_ENDPOINT, Aws::String(Aws::Http::SchemeMapper::ToString(scheme)) + "://" + endpoint);
+ }
+ }
+
+ bool StringEndsWith(const Aws::String& str, const Aws::String& suffix)
+ {
+ if (suffix.size() > str.size())
+ return false;
+ return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
+ }
+
+ void BuiltInParameters::SetFromClientConfiguration(const Client::ClientConfiguration& config)
+ {
+ bool forceFIPS = false;
+ static const char* AWS_REGION = "Region";
+ if (!config.region.empty()) {
+ static const char* FIPS_PREFIX = "fips-";
+ static const char* FIPS_SUFFIX = "-fips";
+ if (config.region.rfind(FIPS_PREFIX, 0) == 0) {
+ // Backward compatibility layer for code hacking previous SDK version
+ Aws::String regionOverride = config.region.substr(sizeof(FIPS_PREFIX) - 1);
+ forceFIPS = true;
+ SetStringParameter(AWS_REGION, regionOverride);
+ } else if (StringEndsWith(config.region, FIPS_SUFFIX)) {
+ Aws::String regionOverride = config.region.substr(0, config.region.size() - sizeof(FIPS_SUFFIX) - 1);
+ forceFIPS = true;
+ SetStringParameter(AWS_REGION, regionOverride);
+ } else {
+ SetStringParameter(AWS_REGION, config.region);
+ }
+ }
+
+ static const char* AWS_USE_FIPS = "UseFIPS";
+ SetBooleanParameter(AWS_USE_FIPS, config.useFIPS || forceFIPS);
+
+ static const char* AWS_USE_DUAL_STACK = "UseDualStack";
+ SetBooleanParameter(AWS_USE_DUAL_STACK, config.useDualStack);
+
+ if (!config.endpointOverride.empty()) {
+ OverrideEndpoint(config.endpointOverride, config.scheme);
+
+ if (config.region.empty()) {
+ AWS_LOGSTREAM_WARN(ENDPOINT_BUILTIN_LOG_TAG,
+ "Endpoint is overridden but region is not set. "
+ "Region is required my many endpoint rule sets to resolve the endpoint. "
+ "And it is required to compute an aws signature.");
+ SetStringParameter(AWS_REGION, "region-not-set"); // dummy endpoint resolution parameter
+ }
+ }
+ }
+
+ void BuiltInParameters::SetFromClientConfiguration(const Client::GenericClientConfiguration<false>& config)
+ {
+ return SetFromClientConfiguration(static_cast<const Client::ClientConfiguration&>(config));
+ }
+
+ void BuiltInParameters::SetFromClientConfiguration(const Client::GenericClientConfiguration<true>& config)
+ {
+ SetFromClientConfiguration(static_cast<const Client::ClientConfiguration&>(config));
+ }
+
+ const BuiltInParameters::EndpointParameter& BuiltInParameters::GetParameter(const Aws::String& name) const
+ {
+ const auto foundIt = std::find_if(m_params.begin(), m_params.end(),
+ [name](const BuiltInParameters::EndpointParameter& item)
+ {
+ return item.GetName() == name;
+ });
+
+ if (foundIt != m_params.end())
+ {
+ return *foundIt;
+ }
+ else
+ {
+ static const BuiltInParameters::EndpointParameter BUILTIN_NOT_FOUND_PARAMETER("PARAMETER_NOT_SET", false, EndpointParameter::ParameterOrigin::CLIENT_CONTEXT);
+ return BUILTIN_NOT_FOUND_PARAMETER;
+ }
+ }
+
+ void BuiltInParameters::SetParameter(EndpointParameter param)
+ {
+ const auto foundIt = std::find_if(m_params.begin(), m_params.end(),
+ [param](const BuiltInParameters::EndpointParameter& item)
+ {
+ return item.GetName() == param.GetName();
+ });
+
+ if (foundIt != m_params.end())
+ {
+ m_params.erase(foundIt);
+ }
+ m_params.emplace_back(std::move(param));
+ }
+
+ void BuiltInParameters::SetStringParameter(Aws::String name, Aws::String value)
+ {
+ return SetParameter(EndpointParameter(std::move(name), std::move(value), EndpointParameter::ParameterOrigin::BUILT_IN));
+ }
+
+ void BuiltInParameters::SetBooleanParameter(Aws::String name, bool value)
+ {
+ return SetParameter(EndpointParameter(std::move(name), value, EndpointParameter::ParameterOrigin::BUILT_IN));
+ }
+
+ const Aws::Vector<BuiltInParameters::EndpointParameter>& BuiltInParameters::GetAllParameters() const
+ {
+ return m_params;
+ }
+} // namespace Endpoint
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/ClientContextParameters.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/ClientContextParameters.cpp
new file mode 100644
index 00000000000..cdff71f6698
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/ClientContextParameters.cpp
@@ -0,0 +1,61 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/ClientContextParameters.h>
+
+namespace Aws
+{
+namespace Endpoint
+{
+ const ClientContextParameters::EndpointParameter& ClientContextParameters::GetParameter(const Aws::String& name) const
+ {
+ const auto foundIt = std::find_if(m_params.begin(), m_params.end(),
+ [name](const ClientContextParameters::EndpointParameter& item)
+ {
+ return item.GetName() == name;
+ });
+
+ if (foundIt != m_params.end())
+ {
+ return *foundIt;
+ }
+ else
+ {
+ static const ClientContextParameters::EndpointParameter CTX_NOT_FOUND_PARAMETER("PARAMETER_NOT_SET", false, EndpointParameter::ParameterOrigin::CLIENT_CONTEXT);
+ return CTX_NOT_FOUND_PARAMETER;
+ }
+ }
+
+ void ClientContextParameters::SetParameter(EndpointParameter param)
+ {
+ const auto foundIt = std::find_if(m_params.begin(), m_params.end(),
+ [param](const ClientContextParameters::EndpointParameter& item)
+ {
+ return item.GetName() == param.GetName();
+ });
+
+ if (foundIt != m_params.end())
+ {
+ m_params.erase(foundIt);
+ }
+ m_params.emplace_back(std::move(param));
+ }
+
+ void ClientContextParameters::SetStringParameter(Aws::String name, Aws::String value)
+ {
+ return SetParameter(EndpointParameter(std::move(name), std::move(value), EndpointParameter::ParameterOrigin::CLIENT_CONTEXT));
+ }
+
+ void ClientContextParameters::SetBooleanParameter(Aws::String name, bool value)
+ {
+ return SetParameter(EndpointParameter(std::move(name), value, EndpointParameter::ParameterOrigin::CLIENT_CONTEXT));
+ }
+
+ const Aws::Vector<ClientContextParameters::EndpointParameter>& ClientContextParameters::GetAllParameters() const
+ {
+ return m_params;
+ }
+} // namespace Endpoint
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp
new file mode 100644
index 00000000000..58370cd4256
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/DefaultEndpointProvider.cpp
@@ -0,0 +1,236 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/DefaultEndpointProvider.h>
+#include <aws/core/utils/memory/stl/AWSMap.h>
+#include <aws/crt/Api.h>
+
+namespace Aws
+{
+namespace Endpoint
+{
+
+/**
+ * Export endpoint provider symbols from DLL
+ */
+template class AWS_CORE_API DefaultEndpointProvider<Aws::Client::GenericClientConfiguration<false>,
+ Aws::Endpoint::BuiltInParameters,
+ Aws::Endpoint::ClientContextParameters>;
+
+char CharToDec(const char c)
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ if(c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0;
+}
+
+Aws::String PercentDecode(Aws::String inputString)
+{
+ if (inputString.find_first_of("%") == Aws::String::npos)
+ {
+ return inputString;
+ }
+ Aws::String result;
+ result.reserve(inputString.size());
+
+ bool percentFound = false;
+ char firstOctet = 0;
+ char secondOctet = 0;
+ for(size_t i = 0; i < inputString.size(); ++i)
+ {
+ const char currentChar = inputString[i];
+ if ('%' == currentChar)
+ {
+ if (percentFound)
+ {
+ // not percent-encoded string
+ result += currentChar;
+ }
+ percentFound = true;
+ continue;
+ }
+
+ if (percentFound)
+ {
+ if ((currentChar >= '0' && currentChar <= '9') ||
+ (currentChar >= 'A' && currentChar <= 'F') ||
+ (currentChar >= 'a' && currentChar <= 'f'))
+ {
+ if(!firstOctet)
+ {
+ firstOctet = currentChar;
+ continue;
+ }
+ if(!secondOctet)
+ {
+ secondOctet = currentChar;
+ char encodedChar = CharToDec(firstOctet) * 16 + CharToDec(secondOctet);
+ result += encodedChar;
+
+ percentFound = false;
+ firstOctet = 0;
+ secondOctet = 0;
+ continue;
+ }
+ } else {
+ // Non-percent encoded sequence
+ result += '%';
+ if(!firstOctet)
+ result += firstOctet;
+ result += currentChar;
+ percentFound = false;
+ firstOctet = 0;
+ secondOctet = 0;
+ continue;
+ }
+ }
+
+ if ('+' == currentChar)
+ {
+ result += ' ';
+ continue;
+ }
+ result += currentChar;
+ }
+ return result;
+}
+
+AWS_CORE_API ResolveEndpointOutcome
+ResolveEndpointDefaultImpl(const Aws::Crt::Endpoints::RuleEngine& ruleEngine,
+ const EndpointParameters& builtInParameters,
+ const EndpointParameters& clientContextParameters,
+ const EndpointParameters& endpointParameters)
+{
+ if(!ruleEngine) {
+ AWS_LOGSTREAM_FATAL(DEFAULT_ENDPOINT_PROVIDER_TAG, "Invalid CRT Rule Engine state");
+ return ResolveEndpointOutcome(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::INTERNAL_FAILURE,
+ "",
+ "CRT Endpoint rule engine is not initialized",
+ false/*retryable*/));
+ }
+
+ Aws::Crt::Endpoints::RequestContext crtRequestCtx;
+
+ const Aws::Vector<std::reference_wrapper<const EndpointParameters>> allParameters
+ = {std::cref(builtInParameters), std::cref(clientContextParameters), std::cref(endpointParameters)};
+
+ for (const auto& parameterClass : allParameters)
+ {
+ for(const auto& parameter : parameterClass.get())
+ {
+ if(EndpointParameter::ParameterType::BOOLEAN == parameter.GetStoredType())
+ {
+ AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint bool eval parameter: " << parameter.GetName() << " = " << parameter.GetBoolValueNoCheck());
+ crtRequestCtx.AddBoolean(Aws::Crt::ByteCursorFromCString(parameter.GetName().c_str()), parameter.GetBoolValueNoCheck());
+ }
+ else if(EndpointParameter::ParameterType::STRING == parameter.GetStoredType())
+ {
+ AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint str eval parameter: " << parameter.GetName() << " = " << parameter.GetStrValueNoCheck());
+ crtRequestCtx.AddString(Aws::Crt::ByteCursorFromCString(parameter.GetName().c_str()), Aws::Crt::ByteCursorFromCString(parameter.GetStrValueNoCheck().c_str()));
+ }
+ else
+ {
+ return ResolveEndpointOutcome(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
+ "",
+ "Invalid endpoint parameter type for parameter " + parameter.GetName(),
+ false/*retryable*/));
+ }
+ }
+ }
+
+ auto resolved = ruleEngine.Resolve(crtRequestCtx);
+
+ if(resolved.has_value())
+ {
+ if(resolved->IsError())
+ {
+ auto crtError = resolved->GetError();
+ Aws::String sdkCrtError = crtError ? Aws::String(crtError->begin(), crtError->end()) :
+ "CRT Rule engine resolution resulted in an unknown error";
+ return ResolveEndpointOutcome(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::INVALID_PARAMETER_COMBINATION,
+ "",
+ sdkCrtError,
+ false/*retryable*/));
+ }
+ else if(resolved->IsEndpoint() && resolved->GetUrl())
+ {
+ Aws::Endpoint::AWSEndpoint endpoint;
+ const auto crtUrl = resolved->GetUrl();
+ Aws::String sdkCrtUrl = Aws::String(crtUrl->begin(), crtUrl->end());
+ AWS_LOGSTREAM_DEBUG(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint rules engine evaluated the endpoint: " << sdkCrtUrl);
+ endpoint.SetURL(PercentDecode(std::move(sdkCrtUrl)));
+
+ // Transform attributes
+ // Each attribute consist of properties, hence converting CRT properties to SDK attributes
+ const auto crtProps = resolved->GetProperties();
+ if (crtProps && crtProps->size() > 2) {
+ Aws::String sdkCrtProps = crtProps ? Aws::String(crtProps->begin(), crtProps->end()) : "";
+ AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG, "Endpoint rules evaluated props: " << sdkCrtProps);
+
+ Internal::Endpoint::EndpointAttributes epAttributes = Internal::Endpoint::EndpointAttributes::BuildEndpointAttributesFromJson(
+ sdkCrtProps);
+
+ endpoint.SetAttributes(std::move(epAttributes));
+ }
+
+ // transform headers
+ const auto crtHeaders = resolved->GetHeaders();
+ if (crtHeaders)
+ {
+ Aws::UnorderedMap<Aws::String, Aws::String> sdkHeaders;
+ for (const auto& header: *crtHeaders)
+ {
+ Aws::String key(header.first.begin(), header.first.end());
+ Aws::String value;
+ for (const auto& crtHeaderValue : header.second)
+ {
+ if(!value.empty()) {
+ value.insert(value.end(), ';');
+ }
+ value.insert(value.end(), crtHeaderValue.begin(), crtHeaderValue.end());
+ }
+ sdkHeaders.emplace(std::move(key), std::move(value));
+ }
+
+ endpoint.SetHeaders(std::move(sdkHeaders));
+ }
+
+ return ResolveEndpointOutcome(std::move(endpoint));
+ }
+ else
+ {
+ return ResolveEndpointOutcome(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
+ "",
+ "Invalid AWS CRT RuleEngine state",
+ false/*retryable*/));
+ }
+ }
+
+ auto errCode = Aws::Crt::LastError();
+ AWS_LOGSTREAM_DEBUG(DEFAULT_ENDPOINT_PROVIDER_TAG, "ERROR: Rule engine has failed to evaluate the endpoint: " << errCode << " " << Aws::Crt::ErrorDebugString(errCode));
+
+ return ResolveEndpointOutcome(
+ Aws::Client::AWSError<Aws::Client::CoreErrors>(
+ Aws::Client::CoreErrors::INVALID_QUERY_PARAMETER,
+ "",
+ "Failed to evaluate the endpoint: null output from AWS CRT RuleEngine",
+ false/*retryable*/));
+
+}
+
+} // namespace Endpoint
+} // namespace Aws \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp
new file mode 100644
index 00000000000..0928186839a
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/EndpointProviderBase.cpp
@@ -0,0 +1,20 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/EndpointProviderBase.h>
+
+namespace Aws
+{
+namespace Endpoint
+{
+/**
+ * Export endpoint provider symbols from DLL
+ */
+template class AWS_CORE_API EndpointProviderBase<Aws::Client::GenericClientConfiguration<false>,
+ Aws::Endpoint::BuiltInParameters,
+ Aws::Endpoint::ClientContextParameters>;
+
+} // namespace Endpoint
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/internal/AWSEndpointAttribute.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/internal/AWSEndpointAttribute.cpp
new file mode 100644
index 00000000000..5c295bb1325
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/endpoint/internal/AWSEndpointAttribute.cpp
@@ -0,0 +1,82 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/endpoint/internal/AWSEndpointAttribute.h>
+#include <aws/core/utils/logging/LogMacros.h>
+
+static const char ENDPOINT_AUTH_SCHEME_TAG[] = "EndpointAuthScheme::BuildEndpointAuthSchemeFromJson";
+
+Aws::String CrtToSdkSignerName(const Aws::String& crtSignerName)
+{
+ Aws::String sdkSigner = "NullSigner";
+ if (crtSignerName == "sigv4") {
+ sdkSigner = "SignatureV4";
+ } else if (crtSignerName == "sigv4a") {
+ sdkSigner = "AsymmetricSignatureV4";
+ } else if (crtSignerName == "none") {
+ sdkSigner = "NullSigner";
+ } else if (crtSignerName == "bearer") {
+ sdkSigner = "Bearer";
+ } else {
+ AWS_LOG_WARN(ENDPOINT_AUTH_SCHEME_TAG, (Aws::String("Unknown Endpoint authSchemes signer: ") + crtSignerName).c_str());
+ }
+
+ return sdkSigner;
+}
+
+Aws::Internal::Endpoint::EndpointAttributes
+Aws::Internal::Endpoint::EndpointAttributes::BuildEndpointAttributesFromJson(const Aws::String& iJsonStr)
+{
+ Aws::Internal::Endpoint::EndpointAttributes attributes;
+ Aws::Internal::Endpoint::EndpointAuthScheme& authScheme = attributes.authScheme;
+
+ Utils::Json::JsonValue jsonObject(iJsonStr);
+ if (jsonObject.WasParseSuccessful())
+ {
+ Aws::Map<Aws::String, Utils::Json::JsonView> jsonMap = jsonObject.View().GetAllObjects();
+ for (const auto& mapItemAttribute : jsonMap)
+ {
+ if (mapItemAttribute.first == "authSchemes" && mapItemAttribute.second.IsListType()) {
+ Aws::Utils::Array<Utils::Json::JsonView> jsonAuthSchemeArray = mapItemAttribute.second.AsArray();
+
+ for (size_t arrayIdx = 0; arrayIdx < jsonAuthSchemeArray.GetLength(); ++arrayIdx)
+ {
+ const Utils::Json::JsonView& property = jsonAuthSchemeArray.GetItem(arrayIdx);
+ for (const auto& mapItemProperty : property.GetAllObjects())
+ {
+ if (mapItemProperty.first == "name") {
+ authScheme.SetName(CrtToSdkSignerName(mapItemProperty.second.AsString()));
+ } else if (mapItemProperty.first == "signingName") {
+ authScheme.SetSigningName(mapItemProperty.second.AsString());
+ } else if (mapItemProperty.first == "signingRegion") {
+ authScheme.SetSigningRegion(mapItemProperty.second.AsString());
+ } else if (mapItemProperty.first == "signingRegionSet") {
+ Aws::Utils::Array<Utils::Json::JsonView> signingRegionArray = mapItemProperty.second.AsArray();
+ if (signingRegionArray.GetLength() != 1) {
+ AWS_LOG_WARN(ENDPOINT_AUTH_SCHEME_TAG,
+ "Signing region set size is not equal to 1");
+ }
+ if (signingRegionArray.GetLength() > 0) {
+ authScheme.SetSigningRegionSet(signingRegionArray.GetItem(0).AsString());
+ }
+ } else if (mapItemProperty.first == "disableDoubleEncoding") {
+ authScheme.SetDisableDoubleEncoding(mapItemProperty.second.AsBool());
+ } else {
+ AWS_LOG_WARN(ENDPOINT_AUTH_SCHEME_TAG, Aws::String("Unknown Endpoint authSchemes attribute property: " + mapItemProperty.first).c_str());
+ }
+ }
+ }
+ } else {
+ AWS_LOG_WARN(ENDPOINT_AUTH_SCHEME_TAG, Aws::String("Unknown Endpoint Attribute: " + mapItemAttribute.first).c_str());
+ }
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(ENDPOINT_AUTH_SCHEME_TAG, "Json Parse failed with message: " << jsonObject.GetErrorMessage());
+ }
+
+ return attributes;
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp
index d21a2e7d86b..cdcbf103e7c 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/cjson/cJSON.cpp
@@ -85,12 +85,19 @@ typedef struct {
const unsigned char *json;
size_t position;
} error;
+/*
+ * NOTE: the use of this static global variable is not thread-safe,
+ * hence writing to / reading from it is disabled in this code.
+ *
+ * See https://cjson.docsforge.com/#thread-safety (concurrent reads)
+ * See https://github.com/aws/aws-sdk-cpp/pull/2231 (concurrent writes)
static error global_error = { NULL, 0 };
CJSON_AS4CPP_PUBLIC(const char *) cJSON_AS4CPP_GetErrorPtr(void)
{
return (const char*) (global_error.json + global_error.position);
}
+ */
CJSON_AS4CPP_PUBLIC(char *) cJSON_AS4CPP_GetStringValue(const cJSON * const item)
{
@@ -120,7 +127,7 @@ CJSON_AS4CPP_PUBLIC(double) cJSON_AS4CPP_GetNumberValue(const cJSON * const item
CJSON_AS4CPP_PUBLIC(const char*) cJSON_AS4CPP_Version(void)
{
static char version[15];
- sprintf(version, "%i.%i.%i", CJSON_AS4CPP_VERSION_MAJOR, CJSON_AS4CPP_VERSION_MINOR, CJSON_AS4CPP_VERSION_PATCH);
+ snprintf(version, sizeof(version), "%i.%i.%i", CJSON_AS4CPP_VERSION_MAJOR, CJSON_AS4CPP_VERSION_MINOR, CJSON_AS4CPP_VERSION_PATCH);
return version;
}
@@ -569,27 +576,27 @@ static cJSON_AS4CPP_bool print_number(const cJSON * const item, printbuffer * co
/* For integer which is out of the range of [INT_MIN, INT_MAX], valuestring is an integer literal. */
if (item->valuestring)
{
- length = sprintf((char*)number_buffer, "%s", item->valuestring);
+ length = snprintf((char*)number_buffer, sizeof(number_buffer), "%s", item->valuestring);
}
/* This checks for NaN and Infinity */
else if (isnan(d) || isinf(d))
{
- length = sprintf((char*)number_buffer, "null");
+ length = snprintf((char*)number_buffer, sizeof(number_buffer), "null");
}
else
{
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
- length = sprintf((char*)number_buffer, "%1.15g", d);
+ length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
- length = sprintf((char*)number_buffer, "%1.17g", d);
+ length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.17g", d);
}
}
- /* sprintf failed or buffer overrun occurred */
+ /* snprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
{
return false;
@@ -1018,7 +1025,7 @@ static cJSON_AS4CPP_bool print_string_ptr(const unsigned char * const input, pri
break;
default:
/* escape and print as unicode codepoint */
- sprintf((char*)output_pointer, "u%04x", *input_pointer);
+ snprintf((char*)output_pointer, output_buffer->length - (output_pointer - output_buffer->buffer), "u%04x", *input_pointer);
output_pointer += 4;
break;
}
@@ -1107,9 +1114,13 @@ CJSON_AS4CPP_PUBLIC(cJSON *) cJSON_AS4CPP_ParseWithLengthOpts(const char *value,
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL;
- /* reset error position */
+ /* reset error position
+ *
+ * NOTE: disabled due to thread safety (see note at the top of this file).
+ *
global_error.json = NULL;
global_error.position = 0;
+ */
if (value == NULL || 0 == buffer_length)
{
@@ -1175,7 +1186,9 @@ fail:
*return_parse_end = (const char*)local_error.json + local_error.position;
}
+ /* NOTE: disabled due to thread safety (see note at the top of this file).
global_error = local_error;
+ */
}
return NULL;
@@ -2470,7 +2483,7 @@ CJSON_AS4CPP_PUBLIC(cJSON *) cJSON_AS4CPP_CreateInt64(long long num)
if (num > INT_MAX || num < INT_MIN)
{
char buf[21];
- sprintf(buf, "%lld", num);
+ snprintf(buf, sizeof(buf), "%lld", num);
item->valuestring = (char*)cJSON_AS4CPP_strdup((const unsigned char*)buf, &global_hooks);
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp
index ebe0fd9eec0..151a3686765 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/external/tinyxml2/tinyxml2.cpp
@@ -135,13 +135,15 @@ struct Entity {
char value;
};
-static const int NUM_ENTITIES = 5;
+static const int NUM_ENTITIES = 7;
static const Entity entities[NUM_ENTITIES] = {
- { "quot", 4, DOUBLE_QUOTE },
- { "amp", 3, '&' },
- { "apos", 4, SINGLE_QUOTE },
- { "lt", 2, '<' },
- { "gt", 2, '>' }
+ { "quot", 4, DOUBLE_QUOTE },
+ { "amp", 3, '&' },
+ { "apos", 4, SINGLE_QUOTE },
+ { "lt", 2, '<' },
+ { "gt", 2, '>' },
+ { "#xA", 3, LF },
+ { "#xD", 3, CR }
};
@@ -2396,6 +2398,8 @@ XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
_restrictedEntityFlag[(unsigned char)'&'] = true;
_restrictedEntityFlag[(unsigned char)'<'] = true;
_restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
+ _restrictedEntityFlag[(unsigned char)LF] = true;
+ _restrictedEntityFlag[(unsigned char)CR] = true;
_buffer.Push( 0 );
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp
index a556e39a5d8..a08b21f9b58 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp
@@ -121,9 +121,11 @@ namespace Aws
void InitStaticState() override
{
+ AWS_LOGSTREAM_DEBUG(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Initializing Http Static State");
#if ENABLE_CURL_CLIENT
if(s_InitCleanupCurlFlag)
{
+ AWS_LOGSTREAM_DEBUG(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Initializing Curl Http Client");
CurlHttpClient::InitGlobalState();
}
#if !defined (_WIN32)
@@ -139,9 +141,11 @@ namespace Aws
virtual void CleanupStaticState() override
{
+ AWS_LOGSTREAM_DEBUG(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Cleanup Http Static State");
#if ENABLE_CURL_CLIENT
if(s_InitCleanupCurlFlag)
{
+ AWS_LOGSTREAM_DEBUG(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Cleanup Curl Http Client");
CurlHttpClient::CleanupGlobalState();
}
#endif
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp
index 95cb626c22e..1f109c86a92 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp
@@ -4,37 +4,88 @@
*/
#include <aws/core/http/HttpRequest.h>
-
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/http/request_response.h>
+#include <aws/crt/Types.h>
+#include <aws/crt/http/HttpRequestResponse.h>
namespace Aws
{
-namespace Http
-{
+ namespace Http
+ {
-const char DATE_HEADER[] = "date";
-const char AWS_DATE_HEADER[] = "X-Amz-Date";
-const char AWS_SECURITY_TOKEN[] = "X-Amz-Security-Token";
-const char ACCEPT_HEADER[] = "accept";
-const char ACCEPT_CHAR_SET_HEADER[] = "accept-charset";
-const char ACCEPT_ENCODING_HEADER[] = "accept-encoding";
-const char AUTHORIZATION_HEADER[] = "authorization";
-const char AWS_AUTHORIZATION_HEADER[] = "authorization";
-const char COOKIE_HEADER[] = "cookie";
-const char CONTENT_LENGTH_HEADER[] = "content-length";
-const char CONTENT_TYPE_HEADER[] = "content-type";
-const char TRANSFER_ENCODING_HEADER[] = "transfer-encoding";
-const char USER_AGENT_HEADER[] = "user-agent";
-const char VIA_HEADER[] = "via";
-const char HOST_HEADER[] = "host";
-const char AMZ_TARGET_HEADER[] = "x-amz-target";
-const char X_AMZ_EXPIRES_HEADER[] = "X-Amz-Expires";
-const char CONTENT_MD5_HEADER[] = "content-md5";
-const char API_VERSION_HEADER[] = "x-amz-api-version";
-const char SDK_INVOCATION_ID_HEADER[] = "amz-sdk-invocation-id";
-const char SDK_REQUEST_HEADER[] = "amz-sdk-request";
-const char CHUNKED_VALUE[] = "chunked";
+ const char DATE_HEADER[] = "date";
+ const char AWS_DATE_HEADER[] = "X-Amz-Date";
+ const char AWS_SECURITY_TOKEN[] = "X-Amz-Security-Token";
+ const char ACCEPT_HEADER[] = "accept";
+ const char ACCEPT_CHAR_SET_HEADER[] = "accept-charset";
+ const char ACCEPT_ENCODING_HEADER[] = "accept-encoding";
+ const char AUTHORIZATION_HEADER[] = "authorization";
+ const char AWS_AUTHORIZATION_HEADER[] = "authorization";
+ const char COOKIE_HEADER[] = "cookie";
+ const char DECODED_CONTENT_LENGTH_HEADER[] = "x-amz-decoded-content-length";
+ const char CONTENT_LENGTH_HEADER[] = "content-length";
+ const char CONTENT_TYPE_HEADER[] = "content-type";
+ const char CONTENT_ENCODING_HEADER[] = "content-encoding";
+ const char TRANSFER_ENCODING_HEADER[] = "transfer-encoding";
+ const char USER_AGENT_HEADER[] = "user-agent";
+ const char VIA_HEADER[] = "via";
+ const char HOST_HEADER[] = "host";
+ const char AMZ_TARGET_HEADER[] = "x-amz-target";
+ const char X_AMZ_EXPIRES_HEADER[] = "X-Amz-Expires";
+ const char CONTENT_MD5_HEADER[] = "content-md5";
+ const char API_VERSION_HEADER[] = "x-amz-api-version";
+ const char AWS_TRAILER_HEADER[] = "x-amz-trailer";
+ const char SDK_INVOCATION_ID_HEADER[] = "amz-sdk-invocation-id";
+ const char SDK_REQUEST_HEADER[] = "amz-sdk-request";
+ const char CHUNKED_VALUE[] = "chunked";
+ const char AWS_CHUNKED_VALUE[] = "aws-chunked";
+ const char X_AMZN_TRACE_ID_HEADER[] = "X-Amzn-Trace-Id";
+ const char ALLOCATION_TAG[] = "HttpRequestConversion";
+ const char X_AMZN_ERROR_TYPE[] = "x-amzn-errortype";
-} // Http
-} // Aws
+ std::shared_ptr<Aws::Crt::Http::HttpRequest> HttpRequest::ToCrtHttpRequest()
+ {
+ auto request = Aws::MakeShared<Aws::Crt::Http::HttpRequest>(ALLOCATION_TAG);
+ request->SetBody([&]() -> std::shared_ptr<IOStream> {
+ const std::shared_ptr<Aws::IOStream>& body = GetContentBody();
+ if (body) {
+ return body;
+ }
+ // Return an empty string stream for no body
+ return Aws::MakeShared<Aws::StringStream>(ALLOCATION_TAG, "");
+ }());
+ auto headers = GetHeaders();
+ for (const auto& it: headers)
+ {
+ Aws::Crt::Http::HttpHeader header;
+ header.name = Aws::Crt::ByteCursorFromCString(it.first.c_str());
+ header.value = Aws::Crt::ByteCursorFromCString(it.second.c_str());
+ request->AddHeader(header);
+ }
+ // Need a different URL encoding here.
+ // CRT sigv4 don't any encoding if double encoding is off, need to encode the path before passing to CRT.
+ const URI& uri = m_uri;
+ Aws::StringStream ss;
+ Aws::StringStream port;
+ if (uri.GetScheme() == Scheme::HTTP && uri.GetPort() != HTTP_DEFAULT_PORT)
+ {
+ port << ":" << uri.GetPort();
+ }
+ else if (uri.GetScheme() == Scheme::HTTPS && uri.GetPort() != HTTPS_DEFAULT_PORT)
+ {
+ port << ":" << uri.GetPort();
+ }
+ ss << SchemeMapper::ToString(uri.GetScheme()) << SEPARATOR << uri.GetAuthority() << port.str()
+ << ((uri.GetPath() == "/") ? "" : URI::URLEncodePath(uri.GetPath()))
+ << uri.GetQueryString();
+ request->SetPath(Aws::Crt::ByteCursorFromCString(ss.str().c_str()));
+ const char *method = HttpMethodMapper::GetNameForHttpMethod(m_method);
+ request->SetMethod(Aws::Crt::ByteCursorFromCString(method));
+ return request;
+ }
+
+ } // Http
+} // Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpResponse.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpResponse.cpp
new file mode 100644
index 00000000000..d4e08336531
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpResponse.cpp
@@ -0,0 +1,24 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/HttpResponse.h>
+
+#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
+#include <aws/core/utils/StringUtils.h>
+
+namespace Aws
+{
+ namespace Http
+ {
+ /**
+ * Overload ostream operator<< for HttpResponseCode enum class for a prettier output such as "200" and not "<C8-00 00-00>"
+ */
+ Aws::OStream& operator<< (Aws::OStream& oStream, HttpResponseCode code)
+ {
+ oStream << Aws::Utils::StringUtils::to_string(static_cast<typename std::underlying_type<HttpResponseCode>::type>(code));
+ return oStream;
+ }
+ } // Http
+} // Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp
index a2239df54b1..0bc3c092458 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp
@@ -5,9 +5,8 @@
#include <aws/core/http/URI.h>
-#include <aws/core/utils/StringUtils.h>
-#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <aws/core/utils/memory/stl/AWSSet.h>
+#include <aws/core/utils/logging/LogMacros.h>
#include <cstdlib>
#include <cctype>
@@ -25,10 +24,52 @@ namespace Http
const char* SEPARATOR = "://";
+bool s_compliantRfc3986Encoding = false;
+void SetCompliantRfc3986Encoding(bool compliant) { s_compliantRfc3986Encoding = compliant; }
+
+Aws::String urlEncodeSegment(const Aws::String& segment)
+{
+ // consolidates legacy escaping logic into one local method
+ if (s_compliantRfc3986Encoding)
+ {
+ return StringUtils::URLEncode(segment.c_str());
+ }
+ else
+ {
+ Aws::StringStream ss;
+ ss << std::hex << std::uppercase;
+ for(unsigned char c : segment) // alnum results in UB if the value of c is not unsigned char & is not EOF
+ {
+ // RFC 3986 §2.3 unreserved characters
+ if (StringUtils::IsAlnum(c))
+ {
+ ss << c;
+ continue;
+ }
+ switch(c)
+ {
+ // §2.3 unreserved characters
+ // The path section of the URL allows unreserved characters to appear unescaped
+ case '-': case '_': case '.': case '~':
+ // RFC 3986 §2.2 Reserved characters
+ // NOTE: this implementation does not accurately implement the RFC on purpose to accommodate for
+ // discrepancies in the implementations of URL encoding between AWS services for legacy reasons.
+ case '$': case '&': case ',':
+ case ':': case '=': case '@':
+ ss << c;
+ break;
+ default:
+ ss << '%' << std::setfill('0') << std::setw(2) << (int)c << std::setw(0);
+ }
+ }
+ return ss.str();
+ }
+}
+
} // namespace Http
} // namespace Aws
-URI::URI() : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT)
+URI::URI() : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT), m_pathHasTrailingSlash(false)
{
}
@@ -102,7 +143,7 @@ void URI::SetScheme(Scheme value)
Aws::String URI::URLEncodePathRFC3986(const Aws::String& path)
{
- if(path.empty())
+ if (path.empty())
{
return path;
}
@@ -114,34 +155,10 @@ Aws::String URI::URLEncodePathRFC3986(const Aws::String& path)
// escape characters appearing in a URL path according to RFC 3986
for (const auto& segment : pathParts)
{
- ss << '/';
- for(unsigned char c : segment) // alnum results in UB if the value of c is not unsigned char & is not EOF
- {
- // §2.3 unreserved characters
- if (StringUtils::IsAlnum(c))
- {
- ss << c;
- continue;
- }
- switch(c)
- {
- // §2.3 unreserved characters
- case '-': case '_': case '.': case '~':
- // The path section of the URL allow reserved characters to appear unescaped
- // RFC 3986 §2.2 Reserved characters
- // NOTE: this implementation does not accurately implement the RFC on purpose to accommodate for
- // discrepancies in the implementations of URL encoding between AWS services for legacy reasons.
- case '$': case '&': case ',':
- case ':': case '=': case '@':
- ss << c;
- break;
- default:
- ss << '%' << std::setfill('0') << std::setw(2) << (int)((unsigned char)c) << std::setw(0);
- }
- }
+ ss << '/' << urlEncodeSegment(segment);
}
- //if the last character was also a slash, then add that back here.
+ // if the last character was also a slash, then add that back here.
if (path.back() == '/')
{
ss << '/';
@@ -176,23 +193,65 @@ Aws::String URI::URLEncodePath(const Aws::String& path)
}
}
-void URI::SetPath(const Aws::String& value)
+Aws::String URI::GetPath() const
{
- const Aws::Vector<Aws::String> pathParts = StringUtils::Split(value, '/');
- Aws::String path;
- path.reserve(value.length() + 1/* in case we have to append slash before the path. */);
+ Aws::String path = "";
- for (const auto& segment : pathParts)
+ for (auto const& segment : m_pathSegments)
{
path.push_back('/');
path.append(segment);
}
- if (value.back() == '/')
+ if (m_pathSegments.empty() || m_pathHasTrailingSlash)
{
path.push_back('/');
}
- m_path = std::move(path);
+
+ return path;
+}
+
+Aws::String URI::GetURLEncodedPath() const
+{
+ Aws::StringStream ss;
+
+ for (auto const& segment : m_pathSegments)
+ {
+ ss << '/' << StringUtils::URLEncode(segment.c_str());
+ }
+
+ if (m_pathSegments.empty() || m_pathHasTrailingSlash)
+ {
+ ss << '/';
+ }
+
+ return ss.str();
+}
+
+Aws::String URI::GetURLEncodedPathRFC3986() const
+{
+ Aws::StringStream ss;
+ ss << std::hex << std::uppercase;
+
+ // escape characters appearing in a URL path according to RFC 3986
+ // (mostly; there is some non-standards legacy support that can be disabled)
+ for (const auto& segment : m_pathSegments)
+ {
+ ss << '/' << urlEncodeSegment(segment);
+ }
+
+ if (m_pathSegments.empty() || m_pathHasTrailingSlash)
+ {
+ ss << '/';
+ }
+
+ return ss.str();
+}
+
+void URI::SetPath(const Aws::String& value)
+{
+ m_pathSegments.clear();
+ AddPathSegments(value);
}
//ugh, this isn't even part of the canonicalization spec. It is part of how our services have implemented their signers though....
@@ -347,9 +406,9 @@ Aws::String URI::GetURIString(bool includeQueryString) const
ss << ":" << m_port;
}
- if(m_path != "/")
+ if (!m_pathSegments.empty())
{
- ss << URLEncodePathRFC3986(m_path);
+ ss << GetURLEncodedPathRFC3986();
}
if(includeQueryString)
@@ -397,10 +456,26 @@ void URI::ExtractAndSetAuthority(const Aws::String& uri)
authorityStart += 3;
}
- size_t posOfEndOfAuthorityPort = uri.find(':', authorityStart);
- size_t posOfEndOfAuthoritySlash = uri.find('/', authorityStart);
- size_t posOfEndOfAuthorityQuery = uri.find('?', authorityStart);
- size_t posEndOfAuthority = (std::min)({posOfEndOfAuthorityPort, posOfEndOfAuthoritySlash, posOfEndOfAuthorityQuery});
+ size_t posEndOfAuthority=0;
+ // are we extracting an ipv6 address?
+ if (uri.length() > authorityStart && uri.at(authorityStart) == '[')
+ {
+ posEndOfAuthority = uri.find(']', authorityStart);
+ if (posEndOfAuthority == Aws::String::npos) {
+ AWS_LOGSTREAM_ERROR("Uri", "Malformed uri: " << uri.c_str());
+ }
+ else
+ {
+ ++posEndOfAuthority;
+ }
+ }
+ else
+ {
+ size_t posOfEndOfAuthorityPort = uri.find(':', authorityStart);
+ size_t posOfEndOfAuthoritySlash = uri.find('/', authorityStart);
+ size_t posOfEndOfAuthorityQuery = uri.find('?', authorityStart);
+ posEndOfAuthority = (std::min)({posOfEndOfAuthorityPort, posOfEndOfAuthoritySlash, posOfEndOfAuthorityQuery});
+ }
if (posEndOfAuthority == Aws::String::npos)
{
posEndOfAuthority = uri.length();
@@ -422,11 +497,25 @@ void URI::ExtractAndSetPort(const Aws::String& uri)
authorityStart += 3;
}
- size_t positionOfPortDelimiter = uri.find(':', authorityStart);
+ size_t portSearchStart = authorityStart;
+ // are we extracting an ipv6 address?
+ if (uri.length() > portSearchStart && uri.at(portSearchStart) == '[')
+ {
+ size_t posEndOfAuthority = uri.find(']', portSearchStart);
+ if (posEndOfAuthority == Aws::String::npos) {
+ AWS_LOGSTREAM_ERROR("Uri", "Malformed uri: " << uri.c_str());
+ }
+ else
+ {
+ portSearchStart = posEndOfAuthority;
+ }
+ }
+
+ size_t positionOfPortDelimiter = uri.find(':', portSearchStart);
bool hasPort = positionOfPortDelimiter != Aws::String::npos;
- if ((uri.find('/', authorityStart) < positionOfPortDelimiter) || (uri.find('?', authorityStart) < positionOfPortDelimiter))
+ if ((uri.find('/', portSearchStart) < positionOfPortDelimiter) || (uri.find('?', portSearchStart) < positionOfPortDelimiter))
{
hasPort = false;
}
@@ -506,5 +595,5 @@ Aws::String URI::GetFormParameters() const
bool URI::CompareURIParts(const URI& other) const
{
- return m_scheme == other.m_scheme && m_authority == other.m_authority && m_path == other.m_path && m_queryString == other.m_queryString;
+ return m_scheme == other.m_scheme && m_authority == other.m_authority && GetPath() == other.GetPath() && m_queryString == other.m_queryString;
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp
index 1a965cd7950..a6684c640a8 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp
@@ -43,7 +43,7 @@ CURL* CurlHandleContainer::AcquireCurlHandle()
}
CURL* handle = m_handleContainer.Acquire();
- AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing.");
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing.");
AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Returning connection handle " << handle);
return handle;
}
@@ -52,6 +52,9 @@ void CurlHandleContainer::ReleaseCurlHandle(CURL* handle)
{
if (handle)
{
+#if LIBCURL_VERSION_NUM >= 0x074D00 // 7.77.0
+ curl_easy_setopt(handle, CURLOPT_COOKIEFILE, NULL); // workaround a mem leak on curl
+#endif
curl_easy_reset(handle);
SetDefaultOptionsOnHandle(handle);
AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Releasing curl handle " << handle);
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp
index 95132f5df0e..0f64b150629 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp
@@ -7,9 +7,12 @@
#include <aws/core/http/HttpRequest.h>
#include <aws/core/http/standard/StandardHttpResponse.h>
#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/HashingUtils.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/ratelimiter/RateLimiterInterface.h>
#include <aws/core/utils/DateTime.h>
+#include <aws/core/utils/crypto/Hash.h>
+#include <aws/core/utils/Outcome.h>
#include <aws/core/monitoring/HttpClientMetrics.h>
#include <cassert>
#include <algorithm>
@@ -146,17 +149,34 @@ struct CurlReadCallbackContext
m_client(client),
m_curlHandle(curlHandle),
m_rateLimiter(limiter),
- m_request(request)
+ m_request(request),
+ m_chunkEnd(false)
{}
const CurlHttpClient* m_client;
CURL* m_curlHandle;
Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter;
HttpRequest* m_request;
+ bool m_chunkEnd;
};
static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient";
+static int64_t GetContentLengthFromHeader(CURL* connectionHandle,
+ bool& hasContentLength) {
+#if LIBCURL_VERSION_NUM >= 0x073700 // 7.55.0
+ curl_off_t contentLength = {};
+ CURLcode res = curl_easy_getinfo(
+ connectionHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &contentLength);
+#else
+ double contentLength = {};
+ CURLcode res = curl_easy_getinfo(
+ connectionHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
+#endif
+ hasContentLength = (res == CURLE_OK) && (contentLength != -1);
+ return hasContentLength ? static_cast<int64_t>(contentLength) : -1;
+}
+
static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata)
{
if (ptr)
@@ -176,8 +196,13 @@ static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata)
context->m_rateLimiter->ApplyAndPayForCost(static_cast<int64_t>(sizeToWrite));
}
+ for (const auto& hashIterator : context->m_request->GetResponseValidationHashes())
+ {
+ hashIterator.second->Update(reinterpret_cast<unsigned char*>(ptr), sizeToWrite);
+ }
+
response->GetResponseBody().write(ptr, static_cast<std::streamsize>(sizeToWrite));
- if (context->m_request->IsEventStreamRequest())
+ if (context->m_request->IsEventStreamRequest() && !response->HasHeader(Aws::Http::X_AMZN_ERROR_TYPE))
{
response->GetResponseBody().flush();
}
@@ -214,8 +239,7 @@ static size_t WriteHeader(char* ptr, size_t size, size_t nmemb, void* userdata)
return 0;
}
-
-static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata)
+static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata, bool isStreaming)
{
CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata);
if(context == nullptr)
@@ -232,10 +256,20 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata)
HttpRequest* request = context->m_request;
const std::shared_ptr<Aws::IOStream>& ioStream = request->GetContentBody();
- const size_t amountToRead = size * nmemb;
+ size_t amountToRead = size * nmemb;
+ bool isAwsChunked = request->HasHeader(Aws::Http::CONTENT_ENCODING_HEADER) &&
+ request->GetHeaderValue(Aws::Http::CONTENT_ENCODING_HEADER) == Aws::Http::AWS_CHUNKED_VALUE;
+ // aws-chunk = hex(chunk-size) + CRLF + chunk-data + CRLF
+ // Needs to reserve bytes of sizeof(hex(chunk-size)) + sizeof(CRLF) + sizeof(CRLF)
+ if (isAwsChunked)
+ {
+ Aws::String amountToReadHexString = Aws::Utils::StringUtils::ToHexString(amountToRead);
+ amountToRead -= (amountToReadHexString.size() + 4);
+ }
+
if (ioStream != nullptr && amountToRead > 0)
{
- if (request->IsEventStreamRequest())
+ if (isStreaming)
{
if (ioStream->readsome(ptr, amountToRead) == 0 && !ioStream->eof())
{
@@ -247,6 +281,39 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata)
ioStream->read(ptr, amountToRead);
}
size_t amountRead = static_cast<size_t>(ioStream->gcount());
+
+ if (isAwsChunked)
+ {
+ if (amountRead > 0)
+ {
+ if (request->GetRequestHash().second != nullptr)
+ {
+ request->GetRequestHash().second->Update(reinterpret_cast<unsigned char*>(ptr), amountRead);
+ }
+
+ Aws::String hex = Aws::Utils::StringUtils::ToHexString(amountRead);
+ memmove(ptr + hex.size() + 2, ptr, amountRead);
+ memmove(ptr + hex.size() + 2 + amountRead, "\r\n", 2);
+ memmove(ptr, hex.c_str(), hex.size());
+ memmove(ptr + hex.size(), "\r\n", 2);
+ amountRead += hex.size() + 4;
+ }
+ else if (!context->m_chunkEnd)
+ {
+ Aws::StringStream chunkedTrailer;
+ chunkedTrailer << "0\r\n";
+ if (request->GetRequestHash().second != nullptr)
+ {
+ chunkedTrailer << "x-amz-checksum-" << request->GetRequestHash().first << ":"
+ << HashingUtils::Base64Encode(request->GetRequestHash().second->GetHash().GetResult()) << "\r\n";
+ }
+ chunkedTrailer << "\r\n";
+ amountRead = chunkedTrailer.str().size();
+ memcpy(ptr, chunkedTrailer.str().c_str(), amountRead);
+ context->m_chunkEnd = true;
+ }
+ }
+
auto& sentHandler = request->GetDataSentEventHandler();
if (sentHandler)
{
@@ -264,6 +331,14 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata)
return 0;
}
+static size_t ReadBodyStreaming(char* ptr, size_t size, size_t nmemb, void* userdata) {
+ return ReadBody(ptr, size, nmemb, userdata, true);
+}
+
+static size_t ReadBodyFunc(char* ptr, size_t size, size_t nmemb, void* userdata) {
+ return ReadBody(ptr, size, nmemb, userdata, false);
+}
+
static size_t SeekBody(void* userdata, curl_off_t offset, int origin)
{
CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata);
@@ -358,7 +433,11 @@ void SetOptCodeForHttpMethod(CURL* requestHandle, const std::shared_ptr<HttpRequ
}
else
{
+#if LIBCURL_VERSION_NUM >= 0x070c01 // 7.12.1
+ curl_easy_setopt(requestHandle, CURLOPT_UPLOAD, 1L);
+#else
curl_easy_setopt(requestHandle, CURLOPT_PUT, 1L);
+#endif
}
break;
case HttpMethod::HTTP_HEAD:
@@ -579,6 +658,9 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr<
curl_easy_setopt(connectionHandle, CURLOPT_CAINFO, m_caFile.c_str());
}
+ // enable the cookie engine without reading any initial cookies.
+ curl_easy_setopt(connectionHandle, CURLOPT_COOKIEFILE, "");
+
// only set by android test builds because the emulator is missing a cert needed for aws services
#ifdef TEST_CERT_PATH
curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, TEST_CERT_PATH);
@@ -664,12 +746,13 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr<
if (request->GetContentBody())
{
- curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBody);
+ curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBodyFunc);
curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &readContext);
curl_easy_setopt(connectionHandle, CURLOPT_SEEKFUNCTION, SeekBody);
curl_easy_setopt(connectionHandle, CURLOPT_SEEKDATA, &readContext);
- if (request->IsEventStreamRequest())
+ if (request->IsEventStreamRequest() && !response->HasHeader(Aws::Http::X_AMZN_ERROR_TYPE))
{
+ curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBodyStreaming);
curl_easy_setopt(connectionHandle, CURLOPT_NOPROGRESS, 0L);
#if LIBCURL_VERSION_NUM >= 0x072000 // 7.32.0
curl_easy_setopt(connectionHandle, CURLOPT_XFERINFOFUNCTION, CurlProgressCallback);
@@ -714,15 +797,18 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr<
AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned content type " << contentType);
}
+ bool hasContentLength = false;
+ int64_t contentLength =
+ GetContentLengthFromHeader(connectionHandle, hasContentLength);
+
if (request->GetMethod() != HttpMethod::HTTP_HEAD &&
writeContext.m_client->IsRequestProcessingEnabled() &&
- response->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER))
+ hasContentLength)
{
- const Aws::String& contentLength = response->GetHeader(Aws::Http::CONTENT_LENGTH_HEADER);
int64_t numBytesResponseReceived = writeContext.m_numBytesResponseReceived;
AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response content-length header: " << contentLength);
AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response body length: " << numBytesResponseReceived);
- if (StringUtils::ConvertToInt64(contentLength.c_str()) != numBytesResponseReceived)
+ if (contentLength != numBytesResponseReceived)
{
response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION);
response->SetClientErrorMessage("Response body length doesn't match the content-length header.");
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp
index 47a0ee4faca..87b857ca24e 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp
@@ -4,7 +4,7 @@
*/
#include <aws/core/http/standard/StandardHttpRequest.h>
-
+#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>
#include <iostream>
@@ -15,6 +15,8 @@ using namespace Aws::Http;
using namespace Aws::Http::Standard;
using namespace Aws::Utils;
+static const char* STANDARD_HTTP_REQUEST_LOG_TAG = "StandardHttpRequest";
+
static bool IsDefaultPort(const URI& uri)
{
switch(uri.GetPort())
@@ -59,8 +61,13 @@ HeaderValueCollection StandardHttpRequest::GetHeaders() const
const Aws::String& StandardHttpRequest::GetHeaderValue(const char* headerName) const
{
- auto iter = headerMap.find(headerName);
+ auto iter = headerMap.find(StringUtils::ToLower(headerName));
assert (iter != headerMap.end());
+ if (iter == headerMap.end()) {
+ AWS_LOGSTREAM_ERROR(STANDARD_HTTP_REQUEST_LOG_TAG, "Requested a header value for a missing header key: " << headerName);
+ static const Aws::String EMPTY_STRING = "";
+ return EMPTY_STRING;
+ }
return iter->second;
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp
index 92d7a062b6c..8b62ae5e634 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp
@@ -6,6 +6,7 @@
#include <aws/core/http/standard/StandardHttpResponse.h>
#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/memory/AWSMemory.h>
#include <istream>
@@ -14,6 +15,7 @@ using namespace Aws::Http;
using namespace Aws::Http::Standard;
using namespace Aws::Utils;
+static const char* STANDARD_HTTP_RESPONSE_LOG_TAG = "StandardHttpResponse";
HeaderValueCollection StandardHttpResponse::GetHeaders() const
{
@@ -35,6 +37,12 @@ bool StandardHttpResponse::HasHeader(const char* headerName) const
const Aws::String& StandardHttpResponse::GetHeader(const Aws::String& headerName) const
{
Aws::Map<Aws::String, Aws::String>::const_iterator foundValue = headerMap.find(StringUtils::ToLower(headerName.c_str()));
+ assert(foundValue != headerMap.end());
+ if (foundValue == headerMap.end()) {
+ AWS_LOGSTREAM_ERROR(STANDARD_HTTP_RESPONSE_LOG_TAG, "Requested a header value for a missing header key: " << headerName);
+ static const Aws::String EMPTY_STRING = "";
+ return EMPTY_STRING;
+ }
return foundValue->second;
}
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 2f372ec82a7..ca664cc6c43 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
@@ -140,12 +140,12 @@ namespace Aws
}
const Aws::Client::AWSError<Aws::Client::CoreErrors> error = [this, &response]() {
- if (response->HasClientError() || response->GetResponseBody().tellp() < 1)
+ if (response->HasClientError() || response->GetResponseCode() == HttpResponseCode::REQUEST_NOT_MADE)
{
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)
+ else if (m_errorMarshaller && response->GetResponseBody().tellp() > 0)
{
return m_errorMarshaller->Marshall(*response);
}
@@ -170,14 +170,23 @@ namespace Aws
}
}
- EC2MetadataClient::EC2MetadataClient(const char* endpoint)
- : AWSHttpResourceClient(EC2_METADATA_CLIENT_LOG_TAG), m_endpoint(endpoint), m_tokenRequired(true)
+ EC2MetadataClient::EC2MetadataClient(const char *endpoint) :
+ AWSHttpResourceClient(EC2_METADATA_CLIENT_LOG_TAG),
+ m_endpoint(endpoint),
+ m_disableIMDS(false),
+ 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(const Aws::Client::ClientConfiguration &clientConfiguration,
+ const char *endpoint) :
+ AWSHttpResourceClient(clientConfiguration, EC2_METADATA_CLIENT_LOG_TAG),
+ m_endpoint(endpoint),
+ m_disableIMDS(clientConfiguration.disableIMDS),
+ m_tokenRequired(true)
{
+
}
EC2MetadataClient::~EC2MetadataClient()
@@ -190,15 +199,20 @@ namespace Aws
return GetResource(m_endpoint.c_str(), resourcePath, nullptr/*authToken*/);
}
+#if !defined(DISABLE_IMDSV1)
Aws::String EC2MetadataClient::GetDefaultCredentials() const
{
+ if (m_disableIMDS) {
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Skipping call to IMDS Service");
+ return {};
+ }
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");
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Getting default credentials for ec2 instance from " << m_endpoint);
auto result = GetResourceWithAWSWebServiceResult(m_endpoint.c_str(), EC2_SECURITY_CREDENTIALS_RESOURCE, nullptr);
Aws::String credentialsString = result.GetPayload();
auto httpResponseCode = result.GetResponseCode();
@@ -232,14 +246,20 @@ namespace Aws
AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource " << ss.str());
return GetResource(ss.str().c_str());
}
+#endif
Aws::String EC2MetadataClient::GetDefaultCredentialsSecurely() const
{
+ if (m_disableIMDS) {
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Skipping call to IMDS Service");
+ return {};
+ }
std::unique_lock<std::recursive_mutex> locker(m_tokenMutex);
- if (!m_tokenRequired)
- {
+#if !defined(DISABLE_IMDSV1)
+ if (!m_tokenRequired) {
return GetDefaultCredentials();
}
+#endif
Aws::StringStream ss;
ss << m_endpoint << EC2_IMDS_TOKEN_RESOURCE;
@@ -257,12 +277,14 @@ namespace Aws
{
return {};
}
+#if !defined(DISABLE_IMDSV1)
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();
}
+#endif
m_token = trimmedTokenString;
locker.unlock();
ss.str("");
@@ -278,7 +300,7 @@ namespace Aws
AWS_LOGSTREAM_DEBUG(m_logtag.c_str(), "Calling EC2MetadataService resource, " << EC2_SECURITY_CREDENTIALS_RESOURCE
<< " with token returned profile string " << trimmedProfileString);
- if (securityCredentials.size() == 0)
+ if (securityCredentials.empty())
{
AWS_LOGSTREAM_WARN(m_logtag.c_str(), "Calling EC2Metadataservice to get profiles failed");
return {};
@@ -296,6 +318,10 @@ namespace Aws
Aws::String EC2MetadataClient::GetCurrentRegion() const
{
+ if (m_disableIMDS) {
+ AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Skipping call to IMDS Service");
+ return {};
+ }
if (!m_region.empty())
{
return m_region;
@@ -311,6 +337,7 @@ namespace Aws
std::lock_guard<std::recursive_mutex> locker(m_tokenMutex);
if (m_tokenRequired)
{
+ GetDefaultCredentialsSecurely();
regionRequest->SetHeaderValue(EC2_IMDS_TOKEN_HEADER, m_token);
}
}
@@ -351,6 +378,16 @@ namespace Aws
return region;
}
+ void EC2MetadataClient::SetEndpoint(const Aws::String& endpoint)
+ {
+ m_endpoint = endpoint;
+ }
+
+ Aws::String EC2MetadataClient::GetEndpoint() const
+ {
+ return Aws::String(m_endpoint);
+ }
+
#ifdef _MSC_VER
// VS2015 compiler's bug, warning s_ec2metadataClient: symbol will be dynamically initialized (implementation limitation)
AWS_SUPPRESS_WARNING(4592,
@@ -366,7 +403,39 @@ namespace Aws
{
return;
}
- s_ec2metadataClient = Aws::MakeShared<EC2MetadataClient>(EC2_METADATA_CLIENT_LOG_TAG);
+ Aws::String ec2MetadataServiceEndpoint = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT");
+ if (ec2MetadataServiceEndpoint.empty())
+ {
+ Aws::String ec2MetadataServiceEndpointMode = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE").c_str();
+ if (ec2MetadataServiceEndpointMode.length() == 0 )
+ {
+ ec2MetadataServiceEndpoint = "http://169.254.169.254"; //default to IPv4 default endpoint
+ }
+ else
+ {
+ if (ec2MetadataServiceEndpointMode.length() == 4 )
+ {
+ if (Aws::Utils::StringUtils::CaselessCompare(ec2MetadataServiceEndpointMode.c_str(), "ipv4"))
+ {
+ ec2MetadataServiceEndpoint = "http://169.254.169.254"; //default to IPv4 default endpoint
+ }
+ else if (Aws::Utils::StringUtils::CaselessCompare(ec2MetadataServiceEndpointMode.c_str(), "ipv6"))
+ {
+ ec2MetadataServiceEndpoint = "http://[fd00:ec2::254]";
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(EC2_METADATA_CLIENT_LOG_TAG, "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE can only be set to ipv4 or ipv6, received: " << ec2MetadataServiceEndpointMode );
+ }
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(EC2_METADATA_CLIENT_LOG_TAG, "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE can only be set to ipv4 or ipv6, received: " << ec2MetadataServiceEndpointMode );
+ }
+ }
+ }
+ AWS_LOGSTREAM_INFO(EC2_METADATA_CLIENT_LOG_TAG, "Using IMDS endpoint: " << ec2MetadataServiceEndpoint);
+ s_ec2metadataClient = Aws::MakeShared<EC2MetadataClient>(EC2_METADATA_CLIENT_LOG_TAG, ec2MetadataServiceEndpoint.c_str());
}
void CleanupEC2MetadataClient()
@@ -383,7 +452,6 @@ namespace Aws
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)
@@ -510,6 +578,17 @@ namespace Aws
{
SetErrorMarshaller(Aws::MakeUnique<Aws::Client::JsonErrorMarshaller>(SSO_RESOURCE_CLIENT_LOG_TAG));
+ m_endpoint = buildEndpoint(clientConfiguration, "portal.sso.", "federation/credentials");
+ m_oidcEndpoint = buildEndpoint(clientConfiguration, "oidc.", "token");
+
+ AWS_LOGSTREAM_INFO(SSO_RESOURCE_CLIENT_LOG_TAG, "Creating SSO ResourceClient with endpoint: " << m_endpoint);
+ }
+
+ Aws::String SSOCredentialsClient::buildEndpoint(
+ const Aws::Client::ClientConfiguration& clientConfiguration,
+ const Aws::String& domain,
+ const Aws::String& endpoint)
+ {
Aws::StringStream ss;
if (clientConfiguration.scheme == Aws::Http::Scheme::HTTP)
{
@@ -525,15 +604,12 @@ namespace Aws
auto hash = Aws::Utils::HashingUtils::HashString(clientConfiguration.region.c_str());
AWS_LOGSTREAM_DEBUG(SSO_RESOURCE_CLIENT_LOG_TAG, "Preparing SSO client for region: " << clientConfiguration.region);
-
- ss << "portal.sso." << clientConfiguration.region << ".amazonaws.com/federation/credentials";
+ ss << domain << clientConfiguration.region << ".amazonaws.com/" << endpoint;
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
{
ss << ".cn";
}
- m_endpoint = ss.str();
-
- AWS_LOGSTREAM_INFO(SSO_RESOURCE_CLIENT_LOG_TAG, "Creating SSO ResourceClient with endpoint: " << m_endpoint);
+ return ss.str();
}
SSOCredentialsClient::SSOGetRoleCredentialsResult SSOCredentialsClient::GetSSOCredentials(const SSOGetRoleCredentialsRequest &request)
@@ -571,5 +647,70 @@ namespace Aws
result.creds = creds;
return result;
}
+
+ // An internal SSO CreateToken implementation to lightweight core package and not introduce a dependency on sso-oidc
+ SSOCredentialsClient::SSOCreateTokenResult SSOCredentialsClient::CreateToken(const SSOCreateTokenRequest& request)
+ {
+ std::shared_ptr<HttpRequest> httpRequest(CreateHttpRequest(m_oidcEndpoint, HttpMethod::HTTP_POST,
+ Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
+ SSOCreateTokenResult result;
+ if(!httpRequest) {
+ AWS_LOGSTREAM_FATAL(SSO_RESOURCE_CLIENT_LOG_TAG, "Failed to CreateHttpRequest: nullptr returned");
+ return result;
+ }
+ httpRequest->SetUserAgent(ComputeUserAgentString());
+
+ Json::JsonValue requestDoc;
+ if(!request.clientId.empty()) {
+ requestDoc.WithString("clientId", request.clientId);
+ }
+ if(!request.clientSecret.empty()) {
+ requestDoc.WithString("clientSecret", request.clientSecret);
+ }
+ if(!request.grantType.empty()) {
+ requestDoc.WithString("grantType", request.grantType);
+ }
+ if(!request.refreshToken.empty()) {
+ requestDoc.WithString("refreshToken", request.refreshToken);
+ }
+
+ std::shared_ptr<Aws::IOStream> body = Aws::MakeShared<Aws::StringStream>("SSO_BEARER_TOKEN_CREATE_TOKEN");
+ if(!body) {
+ AWS_LOGSTREAM_FATAL(SSO_RESOURCE_CLIENT_LOG_TAG, "Failed to allocate body"); // exceptions disabled
+ return result;
+ }
+ *body << requestDoc.View().WriteReadable();;
+
+ 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/json");
+
+ Aws::String rawReply = GetResourceWithAWSWebServiceResult(httpRequest).GetPayload();
+ Json::JsonValue refreshTokenDoc(rawReply);
+ Utils::Json::JsonView jsonValue = refreshTokenDoc.View();
+
+ if(jsonValue.ValueExists("accessToken")) {
+ result.accessToken = jsonValue.GetString("accessToken");
+ }
+ if(jsonValue.ValueExists("tokenType")) {
+ result.tokenType = jsonValue.GetString("tokenType");
+ }
+ if(jsonValue.ValueExists("expiresIn")) {
+ result.expiresIn = jsonValue.GetInteger("expiresIn");
+ }
+ if(jsonValue.ValueExists("idToken")) {
+ result.idToken = jsonValue.GetString("idToken");
+ }
+ if(jsonValue.ValueExists("refreshToken")) {
+ result.refreshToken = jsonValue.GetString("refreshToken");
+ }
+
+ return result;
+ }
}
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp
index 7a8d3adb41c..d6891933c7c 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/monitoring/MonitoringManager.cpp
@@ -25,16 +25,18 @@ namespace Aws
/**
* Global factory to create global metrics instance.
*/
- static Aws::UniquePtr<Monitors> s_monitors;
+ static Monitors* s_monitors(nullptr);
Aws::Vector<void*> OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request)
{
- assert(s_monitors);
Aws::Vector<void*> contexts;
- contexts.reserve(s_monitors->size());
- for (const auto& interface: *s_monitors)
+ if (s_monitors)
{
- contexts.emplace_back(interface->OnRequestStarted(serviceName, requestName, request));
+ contexts.reserve(s_monitors->size());
+ for (const auto& interface: *s_monitors)
+ {
+ contexts.emplace_back(interface->OnRequestStarted(serviceName, requestName, request));
+ }
}
return contexts;
}
@@ -42,48 +44,56 @@ namespace Aws
void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request,
const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts)
{
- assert(s_monitors);
- assert(contexts.size() == s_monitors->size());
- size_t index = 0;
- for (const auto& interface: *s_monitors)
+ if (s_monitors)
{
- interface->OnRequestSucceeded(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]);
+ assert(contexts.size() == s_monitors->size());
+ size_t index = 0;
+ for (const auto& interface: *s_monitors)
+ {
+ interface->OnRequestSucceeded(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]);
+ }
}
}
void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr<const Aws::Http::HttpRequest>& request,
const Aws::Client::HttpResponseOutcome& outcome, const CoreMetricsCollection& metricsFromCore, const Aws::Vector<void*>& contexts)
{
- assert(s_monitors);
- assert(contexts.size() == s_monitors->size());
- size_t index = 0;
- for (const auto& interface: *s_monitors)
+ if (s_monitors)
{
- interface->OnRequestFailed(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]);
+ assert(contexts.size() == s_monitors->size());
+ size_t index = 0;
+ for (const auto& interface: *s_monitors)
+ {
+ interface->OnRequestFailed(serviceName, requestName, request, outcome, metricsFromCore, contexts[index++]);
+ }
}
}
void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName,
const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts)
{
- assert(s_monitors);
- assert(contexts.size() == s_monitors->size());
- size_t index = 0;
- for (const auto& interface: *s_monitors)
+ if (s_monitors)
{
- interface->OnRequestRetry(serviceName, requestName, request, contexts[index++]);
+ assert(contexts.size() == s_monitors->size());
+ size_t index = 0;
+ for (const auto& interface: *s_monitors)
+ {
+ interface->OnRequestRetry(serviceName, requestName, request, contexts[index++]);
+ }
}
}
void OnFinish(const Aws::String& serviceName, const Aws::String& requestName,
const std::shared_ptr<const Aws::Http::HttpRequest>& request, const Aws::Vector<void*>& contexts)
{
- assert(s_monitors);
- assert(contexts.size() == s_monitors->size());
- size_t index = 0;
- for (const auto& interface: *s_monitors)
+ if (s_monitors)
{
- interface->OnFinish(serviceName, requestName, request, contexts[index++]);
+ assert(contexts.size() == s_monitors->size());
+ size_t index = 0;
+ for (const auto& interface: *s_monitors)
+ {
+ interface->OnFinish(serviceName, requestName, request, contexts[index++]);
+ }
}
}
@@ -93,7 +103,8 @@ namespace Aws
{
return;
}
- s_monitors = Aws::MakeUnique<Monitors>(MonitoringTag);
+ assert(Aws::get_aws_allocator() != nullptr);
+ s_monitors = Aws::New<Monitors>(MonitoringTag);
for (const auto& function: monitoringFactoryCreateFunctions)
{
auto factory = function();
@@ -117,11 +128,7 @@ namespace Aws
void CleanupMonitoring()
{
- if (!s_monitors)
- {
- return;
- }
-
+ Aws::Delete(s_monitors);
s_monitors = nullptr;
}
} // namespace Monitoring
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp
index b690c90c2dd..5ef76dcfc67 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/DateTimeCommon.cpp
@@ -176,7 +176,7 @@ static int GetWeekDayNumberFromStr(const char* timeString, size_t startIndex, si
}
}
-//Get the 0-11 monthy number from a string representing Month. Case insensitive and will stop on abbreviation
+//Get the 0-11 monthly number from a string representing Month. Case insensitive and will stop on abbreviation
static int GetMonthNumberFromStr(const char* timeString, size_t startIndex, size_t stopIndex)
{
if (stopIndex - startIndex < 3)
@@ -842,7 +842,9 @@ public:
break;
case 6:
- if ((c == 'Z' || c == '+' || c == '-' ) && (index - stateStartIndex == 3))
+ if ((c == 'Z' || c == '+' || c == '-' ) &&
+ (index - stateStartIndex >= 3) &&
+ (index - stateStartIndex <= 9))
{
m_tz[0] = c;
m_state = 7;
@@ -1268,6 +1270,12 @@ double DateTime::SecondsWithMSPrecision() const
return timestamp.count();
}
+int64_t DateTime::Seconds() const
+{
+ auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(m_time.time_since_epoch());
+ return timestamp.count();
+}
+
int64_t DateTime::Millis() const
{
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(m_time.time_since_epoch());
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Document.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Document.cpp
new file mode 100644
index 00000000000..ef8210aeb1e
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/Document.cpp
@@ -0,0 +1,673 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/utils/Document.h>
+
+#include <iterator>
+#include <algorithm>
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/json/JsonSerializer.h>
+
+using namespace Aws::Utils;
+
+Document::Document() : m_wasParseSuccessful(true)
+{
+ m_json = nullptr;
+}
+
+Document::Document(cJSON* value) :
+ m_json(cJSON_AS4CPP_Duplicate(value, true /* recurse */)),
+ m_wasParseSuccessful(true)
+{
+}
+
+Document::Document(const Aws::String& value) : m_wasParseSuccessful(true)
+{
+ const char* return_parse_end;
+ m_json = cJSON_AS4CPP_ParseWithOpts(value.c_str(), &return_parse_end, 1/*require_null_terminated*/);
+
+ if (!m_json || cJSON_AS4CPP_IsInvalid(m_json))
+ {
+ m_wasParseSuccessful = false;
+ m_errorMessage = "Failed to parse JSON at: ";
+ m_errorMessage += return_parse_end;
+ }
+}
+
+Document::Document(Aws::IStream& istream) : m_wasParseSuccessful(true)
+{
+ Aws::StringStream memoryStream;
+ std::copy(std::istreambuf_iterator<char>(istream), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(memoryStream));
+ const char* return_parse_end;
+ const auto input = memoryStream.str();
+ m_json = cJSON_AS4CPP_ParseWithOpts(input.c_str(), &return_parse_end, 1/*require_null_terminated*/);
+
+ if (!m_json || cJSON_AS4CPP_IsInvalid(m_json))
+ {
+ m_wasParseSuccessful = false;
+ m_errorMessage = "Failed to parse JSON. Invalid input at: ";
+ m_errorMessage += return_parse_end;
+ }
+}
+
+Document::Document(const Document& value) :
+ m_json(cJSON_AS4CPP_Duplicate(value.m_json, true/*recurse*/)),
+ m_wasParseSuccessful(value.m_wasParseSuccessful),
+ m_errorMessage(value.m_errorMessage)
+{
+}
+
+Document::Document(Document&& value) :
+ m_json(value.m_json),
+ m_wasParseSuccessful(value.m_wasParseSuccessful),
+ m_errorMessage(std::move(value.m_errorMessage))
+{
+ value.m_json = nullptr;
+}
+
+Document::Document(const Json::JsonView& view) :
+ m_json(cJSON_AS4CPP_Duplicate(view.m_value, true/*recurse*/)),
+ m_wasParseSuccessful(true),
+ m_errorMessage({})
+{
+}
+
+void Document::Destroy()
+{
+ cJSON_AS4CPP_Delete(m_json);
+}
+
+Document::~Document()
+{
+ Destroy();
+}
+
+Document& Document::operator=(const Document& other)
+{
+ if (this == &other)
+ {
+ return *this;
+ }
+
+ Destroy();
+ m_json = cJSON_AS4CPP_Duplicate(other.m_json, true /*recurse*/);
+ m_wasParseSuccessful = other.m_wasParseSuccessful;
+ m_errorMessage = other.m_errorMessage;
+ return *this;
+}
+
+Document& Document::operator=(Document&& other)
+{
+ if (this == &other)
+ {
+ return *this;
+ }
+
+ using std::swap;
+ swap(m_json, other.m_json);
+ swap(m_errorMessage, other.m_errorMessage);
+ m_wasParseSuccessful = other.m_wasParseSuccessful;
+ return *this;
+}
+
+Document& Document::operator=(const Json::JsonView& other)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_Duplicate(other.m_value, true /*recurse*/);
+ m_wasParseSuccessful = true;
+ m_errorMessage = {};
+ return *this;
+}
+
+bool Document::operator==(const Document& other) const
+{
+ return cJSON_AS4CPP_Compare(m_json, other.m_json, true /*case-sensitive*/) != 0;
+}
+
+bool Document::operator!=(const Document& other) const
+{
+ return !(*this == other);
+}
+
+static void AddOrReplace(cJSON* root, const char* key, cJSON* value)
+{
+ const auto existing = cJSON_AS4CPP_GetObjectItemCaseSensitive(root, key);
+ if (existing)
+ {
+ cJSON_AS4CPP_ReplaceItemInObjectCaseSensitive(root, key, value);
+ }
+ else
+ {
+ cJSON_AS4CPP_AddItemToObject(root, key, value);
+ }
+}
+
+Document& Document::WithString(const char* key, const Aws::String& value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ const auto val = cJSON_AS4CPP_CreateString(value.c_str());
+ AddOrReplace(m_json, key, val);
+ return *this;
+}
+
+Document& Document::WithString(const Aws::String& key, const Aws::String& value)
+{
+ return WithString(key.c_str(), value);
+}
+
+Document& Document::AsString(const Aws::String& value)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_CreateString(value.c_str());
+ return *this;
+}
+
+Document& Document::WithBool(const char* key, bool value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ const auto val = cJSON_AS4CPP_CreateBool(value);
+ AddOrReplace(m_json, key, val);
+ return *this;
+}
+
+Document& Document::WithBool(const Aws::String& key, bool value)
+{
+ return WithBool(key.c_str(), value);
+}
+
+Document& Document::AsBool(bool value)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_CreateBool(value);
+ return *this;
+}
+
+Document& Document::WithInteger(const char* key, int value)
+{
+ return WithDouble(key, static_cast<double>(value));
+}
+
+Document& Document::WithInteger(const Aws::String& key, int value)
+{
+ return WithDouble(key.c_str(), static_cast<double>(value));
+}
+
+Document& Document::AsInteger(int value)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_CreateNumber(static_cast<double>(value));
+ return *this;
+}
+
+Document& Document::WithInt64(const char* key, long long value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ const auto val = cJSON_AS4CPP_CreateInt64(value);
+ AddOrReplace(m_json, key, val);
+ return *this;
+}
+
+Document& Document::WithInt64(const Aws::String& key, long long value)
+{
+ return WithInt64(key.c_str(), value);
+}
+
+Document& Document::AsInt64(long long value)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_CreateInt64(value);
+ return *this;
+}
+
+Document& Document::WithDouble(const char* key, double value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ const auto val = cJSON_AS4CPP_CreateNumber(value);
+ AddOrReplace(m_json, key, val);
+ return *this;
+}
+
+Document& Document::WithDouble(const Aws::String& key, double value)
+{
+ return WithDouble(key.c_str(), value);
+}
+
+Document& Document::AsDouble(double value)
+{
+ Destroy();
+ m_json = cJSON_AS4CPP_CreateNumber(value);
+ return *this;
+}
+
+Document& Document::WithArray(const char* key, const Array<Aws::String>& array)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ auto arrayValue = cJSON_AS4CPP_CreateArray();
+ for (unsigned i = 0; i < array.GetLength(); ++i)
+ {
+ cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_CreateString(array[i].c_str()));
+ }
+
+ AddOrReplace(m_json, key, arrayValue);
+ return *this;
+}
+
+Document& Document::WithArray(const Aws::String& key, const Array<Aws::String>& array)
+{
+ return WithArray(key.c_str(), array);
+}
+
+Document& Document::WithArray(const Aws::String& key, const Array<Document>& array)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ auto arrayValue = cJSON_AS4CPP_CreateArray();
+ for (unsigned i = 0; i < array.GetLength(); ++i)
+ {
+ cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_Duplicate(array[i].m_json, true /*recurse*/));
+ }
+
+ AddOrReplace(m_json, key.c_str(), arrayValue);
+ return *this;
+}
+
+Document& Document::WithArray(const Aws::String& key, Array<Document>&& array)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ auto arrayValue = cJSON_AS4CPP_CreateArray();
+ for (unsigned i = 0; i < array.GetLength(); ++i)
+ {
+ cJSON_AS4CPP_AddItemToArray(arrayValue, array[i].m_json);
+ array[i].m_json = nullptr;
+ }
+
+ AddOrReplace(m_json, key.c_str(), arrayValue);
+ return *this;
+}
+
+Document& Document::AsArray(const Array<Document>& array)
+{
+ auto arrayValue = cJSON_AS4CPP_CreateArray();
+ for (unsigned i = 0; i < array.GetLength(); ++i)
+ {
+ cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_Duplicate(array[i].m_json, true /*recurse*/));
+ }
+
+ Destroy();
+ m_json = arrayValue;
+ return *this;
+}
+
+Document& Document::AsArray(Array<Document>&& array)
+{
+ auto arrayValue = cJSON_AS4CPP_CreateArray();
+ for (unsigned i = 0; i < array.GetLength(); ++i)
+ {
+ cJSON_AS4CPP_AddItemToArray(arrayValue, array[i].m_json);
+ array[i].m_json = nullptr;
+ }
+
+ Destroy();
+ m_json = arrayValue;
+ return *this;
+}
+
+Document& Document::WithObject(const char* key, const Document& value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ const auto copy = value.m_json == nullptr ? cJSON_AS4CPP_CreateObject() : cJSON_AS4CPP_Duplicate(value.m_json, true /*recurse*/);
+ AddOrReplace(m_json, key, copy);
+ return *this;
+}
+
+Document& Document::WithObject(const Aws::String& key, const Document& value)
+{
+ return WithObject(key.c_str(), value);
+}
+
+Document& Document::WithObject(const char* key, Document&& value)
+{
+ if (!m_json)
+ {
+ m_json = cJSON_AS4CPP_CreateObject();
+ }
+
+ AddOrReplace(m_json, key, value.m_json == nullptr ? cJSON_AS4CPP_CreateObject() : value.m_json);
+ value.m_json = nullptr;
+ return *this;
+}
+
+Document& Document::WithObject(const Aws::String& key, Document&& value)
+{
+ return WithObject(key.c_str(), std::move(value));
+}
+
+Document& Document::AsObject(const Document& value)
+{
+ *this = value;
+ return *this;
+}
+
+Document& Document::AsObject(Document && value)
+{
+ *this = std::move(value);
+ return *this;
+}
+
+DocumentView Document::View() const
+{
+ return *this;
+}
+
+DocumentView::DocumentView() : m_json(nullptr)
+{
+}
+
+DocumentView::DocumentView(const Document& value) : m_json(value.m_json)
+{
+}
+
+DocumentView::DocumentView(cJSON* v) : m_json(v)
+{
+}
+
+DocumentView& DocumentView::operator=(const Document& value)
+{
+ m_json = value.m_json;
+ return *this;
+}
+
+DocumentView& DocumentView::operator=(cJSON* value)
+{
+ m_json = value;
+ return *this;
+}
+
+Aws::String DocumentView::GetString(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ auto str = cJSON_AS4CPP_GetStringValue(item);
+ return str ? str : "";
+}
+
+Aws::String DocumentView::AsString() const
+{
+ const char* str = cJSON_AS4CPP_GetStringValue(m_json);
+ if (str == nullptr)
+ {
+ return {};
+ }
+ return str;
+}
+
+bool DocumentView::IsString() const
+{
+ return cJSON_AS4CPP_IsString(m_json) != 0;
+}
+
+bool DocumentView::GetBool(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ assert(item);
+ return item->valueint != 0;
+}
+
+bool DocumentView::AsBool() const
+{
+ assert(cJSON_AS4CPP_IsBool(m_json));
+ return cJSON_AS4CPP_IsTrue(m_json) != 0;
+}
+
+bool DocumentView::IsBool() const
+{
+ return cJSON_AS4CPP_IsBool(m_json) != 0;
+}
+
+int DocumentView::GetInteger(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ assert(item);
+ return item->valueint;
+}
+
+int DocumentView::AsInteger() const
+{
+ assert(cJSON_AS4CPP_IsNumber(m_json)); // can be double or value larger than int_max, but at least not UB
+ return m_json->valueint;
+}
+
+bool DocumentView::IsIntegerType() const
+{
+ if (!cJSON_AS4CPP_IsNumber(m_json))
+ {
+ return false;
+ }
+
+ if (m_json->valuestring)
+ {
+ Aws::String valueString = m_json->valuestring;
+ return std::all_of(valueString.begin(), valueString.end(), [](unsigned char c){ return ::isdigit(c) || c == '+' || c == '-'; });
+ }
+ return m_json->valuedouble == static_cast<long long>(m_json->valuedouble);
+}
+
+int64_t DocumentView::GetInt64(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ assert(item);
+ if (item->valuestring)
+ {
+ return Aws::Utils::StringUtils::ConvertToInt64(item->valuestring);
+ }
+ else
+ {
+ return static_cast<int64_t>(item->valuedouble);
+ }
+}
+
+int64_t DocumentView::AsInt64() const
+{
+ assert(cJSON_AS4CPP_IsNumber(m_json));
+ if (m_json->valuestring)
+ {
+ return Aws::Utils::StringUtils::ConvertToInt64(m_json->valuestring);
+ }
+ else
+ {
+ return static_cast<int64_t>(m_json->valuedouble);
+ }
+}
+
+double DocumentView::GetDouble(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ assert(item);
+ return item->valuedouble;
+}
+
+double DocumentView::AsDouble() const
+{
+ assert(cJSON_AS4CPP_IsNumber(m_json));
+ return m_json->valuedouble;
+}
+
+bool DocumentView::IsFloatingPointType() const
+{
+ if (!cJSON_AS4CPP_IsNumber(m_json))
+ {
+ return false;
+ }
+
+ if (m_json->valuestring)
+ {
+ Aws::String valueString = m_json->valuestring;
+ return std::any_of(valueString.begin(), valueString.end(), [](unsigned char c){ return !::isdigit(c) && c != '+' && c != '-'; });
+ }
+ return m_json->valuedouble != static_cast<long long>(m_json->valuedouble);
+}
+
+Array<DocumentView> DocumentView::GetArray(const Aws::String& key) const
+{
+ assert(m_json);
+ auto array = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ assert(cJSON_AS4CPP_IsArray(array));
+ Array<DocumentView> returnArray(cJSON_AS4CPP_GetArraySize(array));
+
+ auto element = array->child;
+ for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next)
+ {
+ returnArray[i] = element;
+ }
+
+ return returnArray;
+}
+
+Array<DocumentView> DocumentView::AsArray() const
+{
+ assert(cJSON_AS4CPP_IsArray(m_json));
+ Array<DocumentView> returnArray(cJSON_AS4CPP_GetArraySize(m_json));
+
+ auto element = m_json->child;
+
+ for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next)
+ {
+ returnArray[i] = element;
+ }
+
+ return returnArray;
+}
+
+bool DocumentView::IsListType() const
+{
+ return cJSON_AS4CPP_IsArray(m_json) != 0;
+}
+
+DocumentView DocumentView::GetObject(const Aws::String& key) const
+{
+ assert(m_json);
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ return item;
+}
+
+DocumentView DocumentView::AsObject() const
+{
+ assert(cJSON_AS4CPP_IsObject(m_json) || cJSON_AS4CPP_IsNull(m_json));
+ return m_json;
+}
+
+bool DocumentView::IsObject() const
+{
+ return cJSON_AS4CPP_IsObject(m_json) != 0;
+}
+
+bool DocumentView::IsNull() const
+{
+ return cJSON_AS4CPP_IsNull(m_json) != 0;
+}
+
+Aws::Map<Aws::String, DocumentView> DocumentView::GetAllObjects() const
+{
+ Aws::Map<Aws::String, DocumentView> valueMap;
+ if (!m_json)
+ {
+ return valueMap;
+ }
+
+ for (auto iter = m_json->child; iter; iter = iter->next)
+ {
+ valueMap.emplace(std::make_pair(Aws::String(iter->string), DocumentView(iter)));
+ }
+
+ return valueMap;
+}
+
+bool DocumentView::ValueExists(const Aws::String& key) const
+{
+ if (!cJSON_AS4CPP_IsObject(m_json))
+ {
+ return false;
+ }
+
+ auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
+ return !(item == nullptr || cJSON_AS4CPP_IsNull(item));
+}
+
+bool DocumentView::KeyExists(const Aws::String& key) const
+{
+ if (!cJSON_AS4CPP_IsObject(m_json))
+ {
+ return false;
+ }
+
+ return cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str()) != nullptr;;
+}
+
+Aws::String DocumentView::WriteCompact() const
+{
+ if (!m_json)
+ {
+ return "null";
+ }
+
+ auto temp = cJSON_AS4CPP_PrintUnformatted(m_json);
+ Aws::String out(temp);
+ cJSON_AS4CPP_free(temp);
+ return out;
+}
+
+Aws::String DocumentView::WriteReadable() const
+{
+ if (!m_json)
+ {
+ return "null";
+ }
+
+ auto temp = cJSON_AS4CPP_Print(m_json);
+ Aws::String out(temp);
+ cJSON_AS4CPP_free(temp);
+ return out;
+}
+
+Document DocumentView::Materialize() const
+{
+ return m_json;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp
index 0e49a616343..0431835a615 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp
@@ -11,6 +11,7 @@
#include <aws/core/utils/crypto/Sha256HMAC.h>
#include <aws/core/utils/crypto/Sha1.h>
#include <aws/core/utils/crypto/MD5.h>
+#include <aws/core/utils/crypto/CRC32.h>
#include <aws/core/utils/Outcome.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <aws/core/utils/memory/stl/AWSList.h>
@@ -234,6 +235,30 @@ ByteBuffer HashingUtils::CalculateMD5(Aws::IOStream& stream)
return hash.Calculate(stream).GetResult();
}
+ByteBuffer HashingUtils::CalculateCRC32(const Aws::String& str)
+{
+ CRC32 hash;
+ return hash.Calculate(str).GetResult();
+}
+
+ByteBuffer HashingUtils::CalculateCRC32(Aws::IOStream& stream)
+{
+ CRC32 hash;
+ return hash.Calculate(stream).GetResult();
+}
+
+ByteBuffer HashingUtils::CalculateCRC32C(const Aws::String& str)
+{
+ CRC32C hash;
+ return hash.Calculate(str).GetResult();
+}
+
+ByteBuffer HashingUtils::CalculateCRC32C(Aws::IOStream& stream)
+{
+ CRC32C hash;
+ return hash.Calculate(stream).GetResult();
+}
+
int HashingUtils::HashString(const char* strToHash)
{
if (!strToHash)
@@ -242,7 +267,7 @@ int HashingUtils::HashString(const char* strToHash)
unsigned hash = 0;
while (char charValue = *strToHash++)
{
- hash = charValue + 31 * hash;
+ hash = charValue + 31 * hash;
}
return hash;
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CRC32.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CRC32.cpp
new file mode 100644
index 00000000000..c09806fbe0b
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/CRC32.cpp
@@ -0,0 +1,218 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+
+#include <aws/core/utils/crypto/CRC32.h>
+#include <aws/core/utils/Outcome.h>
+#include <aws/core/utils/crypto/Factories.h>
+#include <aws/crt/Types.h>
+#include <aws/checksums/crc.h>
+#include <aws/common/byte_buf.h>
+
+using namespace Aws::Utils::Crypto;
+
+static Aws::Utils::ByteBuffer ByteBufferFromInt32(uint32_t value)
+{
+ Aws::Utils::ByteBuffer buffer(4);
+ buffer[0] = (value >> 24) & 0xFF;
+ buffer[1] = (value >> 16) & 0xFF;
+ buffer[2] = (value >> 8) & 0xFF;
+ buffer[3] = value & 0xFF;
+ return buffer;
+}
+
+CRC32::CRC32() :
+ m_hashImpl(CreateCRC32Implementation())
+{
+}
+
+CRC32::~CRC32()
+{
+}
+
+HashResult CRC32::Calculate(const Aws::String& str)
+{
+ return m_hashImpl->Calculate(str);
+}
+
+HashResult CRC32::Calculate(Aws::IStream& stream)
+{
+ return m_hashImpl->Calculate(stream);
+}
+
+void CRC32::Update(unsigned char* buffer, size_t bufferSize)
+{
+ m_hashImpl->Update(buffer, bufferSize);
+}
+
+HashResult CRC32::GetHash()
+{
+ return m_hashImpl->GetHash();
+}
+
+CRC32C::CRC32C() :
+ m_hashImpl(CreateCRC32CImplementation())
+{
+}
+
+CRC32C::~CRC32C()
+{
+}
+
+HashResult CRC32C::Calculate(const Aws::String& str)
+{
+ return m_hashImpl->Calculate(str);
+}
+
+HashResult CRC32C::Calculate(Aws::IStream& stream)
+{
+ return m_hashImpl->Calculate(stream);
+}
+
+
+void CRC32C::Update(unsigned char* buffer, size_t bufferSize)
+{
+ m_hashImpl->Update(buffer, bufferSize);
+}
+
+HashResult CRC32C::GetHash()
+{
+ return m_hashImpl->GetHash();
+}
+
+
+CRC32Impl::CRC32Impl() : m_runningCrc32(0) {}
+
+HashResult CRC32Impl::Calculate(const Aws::String& str)
+{
+ Aws::Crt::ByteCursor byteCursor = Aws::Crt::ByteCursorFromArray(reinterpret_cast<const uint8_t*>(str.data()), str.size());
+
+ uint32_t runningCrc32 = 0;
+ while (byteCursor.len > INT_MAX)
+ {
+ runningCrc32 = aws_checksums_crc32(byteCursor.ptr, INT_MAX, runningCrc32);
+ aws_byte_cursor_advance(&byteCursor, INT_MAX);
+ }
+ runningCrc32 = aws_checksums_crc32(byteCursor.ptr, static_cast<int>(byteCursor.len), runningCrc32);
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(runningCrc32);
+ return HashResult(std::move(hash));
+}
+
+HashResult CRC32Impl::Calculate(Aws::IStream& stream)
+{
+ uint32_t runningCrc32 = 0;
+
+ auto currentPos = stream.tellg();
+ if (currentPos == std::ios::pos_type(-1))
+ {
+ currentPos = 0;
+ stream.clear();
+ }
+
+ stream.seekg(0, stream.beg);
+
+ uint8_t streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
+ while (stream.good())
+ {
+ stream.read(reinterpret_cast<char*>(streamBuffer), Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
+ auto bytesRead = stream.gcount();
+
+ if (bytesRead > 0)
+ {
+ runningCrc32 = aws_checksums_crc32(streamBuffer, static_cast<int>(bytesRead), runningCrc32);
+ }
+ }
+
+ stream.clear();
+ stream.seekg(currentPos, stream.beg);
+
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(runningCrc32);
+ return HashResult(std::move(hash));
+}
+
+void CRC32Impl::Update(unsigned char* buffer, size_t bufferSize)
+{
+ Aws::Crt::ByteCursor byteCursor = Aws::Crt::ByteCursorFromArray(buffer, bufferSize);
+
+ while (byteCursor.len > INT_MAX)
+ {
+ m_runningCrc32 = aws_checksums_crc32(byteCursor.ptr, INT_MAX, m_runningCrc32);
+ aws_byte_cursor_advance(&byteCursor, INT_MAX);
+ }
+ m_runningCrc32 = aws_checksums_crc32(byteCursor.ptr, static_cast<int>(byteCursor.len), m_runningCrc32);
+}
+
+HashResult CRC32Impl::GetHash()
+{
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(m_runningCrc32);
+ return HashResult(std::move(hash));
+}
+
+CRC32CImpl::CRC32CImpl() : m_runningCrc32c(0) {}
+
+HashResult CRC32CImpl::Calculate(const Aws::String& str)
+{
+ Aws::Crt::ByteCursor byteCursor = Aws::Crt::ByteCursorFromArray(reinterpret_cast<const uint8_t*>(str.data()), str.size());
+
+ uint32_t runningCrc32c = 0;
+ while (byteCursor.len > INT_MAX)
+ {
+ runningCrc32c = aws_checksums_crc32c(byteCursor.ptr, INT_MAX, runningCrc32c);
+ aws_byte_cursor_advance(&byteCursor, INT_MAX);
+ }
+ runningCrc32c = aws_checksums_crc32c(byteCursor.ptr, static_cast<int>(byteCursor.len), runningCrc32c);
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(runningCrc32c);
+ return HashResult(std::move(hash));
+}
+
+HashResult CRC32CImpl::Calculate(Aws::IStream& stream)
+{
+ uint32_t runningCrc32c = 0;
+
+ auto currentPos = stream.tellg();
+ if (currentPos == std::ios::pos_type(-1))
+ {
+ currentPos = 0;
+ stream.clear();
+ }
+
+ stream.seekg(0, stream.beg);
+
+ uint8_t streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
+ while (stream.good())
+ {
+ stream.read(reinterpret_cast<char*>(streamBuffer), Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
+ auto bytesRead = stream.gcount();
+
+ if (bytesRead > 0)
+ {
+ runningCrc32c = aws_checksums_crc32c(streamBuffer, static_cast<int>(bytesRead), runningCrc32c);
+ }
+ }
+
+ stream.clear();
+ stream.seekg(currentPos, stream.beg);
+
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(runningCrc32c);
+ return HashResult(std::move(hash));
+}
+
+void CRC32CImpl::Update(unsigned char* buffer, size_t bufferSize)
+{
+ Aws::Crt::ByteCursor byteCursor = Aws::Crt::ByteCursorFromArray(buffer, bufferSize);
+
+ while (byteCursor.len > INT_MAX)
+ {
+ m_runningCrc32c = aws_checksums_crc32c(byteCursor.ptr, INT_MAX, m_runningCrc32c);
+ aws_byte_cursor_advance(&byteCursor, INT_MAX);
+ }
+ m_runningCrc32c = aws_checksums_crc32c(byteCursor.ptr, static_cast<int>(byteCursor.len), m_runningCrc32c);
+}
+
+HashResult CRC32CImpl::GetHash()
+{
+ const Aws::Utils::ByteBuffer& hash = ByteBufferFromInt32(m_runningCrc32c);
+ return HashResult(std::move(hash));
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp
index bf14ace1ad3..f442878a90b 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/MD5.cpp
@@ -11,7 +11,7 @@
using namespace Aws::Utils::Crypto;
-MD5::MD5() :
+MD5::MD5() :
m_hashImpl(CreateMD5Implementation())
{
}
@@ -28,4 +28,14 @@ HashResult MD5::Calculate(const Aws::String& str)
HashResult MD5::Calculate(Aws::IStream& stream)
{
return m_hashImpl->Calculate(stream);
-} \ No newline at end of file
+}
+
+void MD5::Update(unsigned char* buffer, size_t bufferSize)
+{
+ return m_hashImpl->Update(buffer, bufferSize);
+}
+
+HashResult MD5::GetHash()
+{
+ return m_hashImpl->GetHash();
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha1.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha1.cpp
index 5da3e63d28f..a6783e18f0f 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha1.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha1.cpp
@@ -28,3 +28,13 @@ HashResult Sha1::Calculate(Aws::IStream& stream)
{
return m_hashImpl->Calculate(stream);
}
+
+void Sha1::Update(unsigned char* buffer, size_t bufferSize)
+{
+ return m_hashImpl->Update(buffer, bufferSize);
+}
+
+HashResult Sha1::GetHash()
+{
+ return m_hashImpl->GetHash();
+} \ No newline at end of file
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp
index a8aa5ae8790..48612e8cf03 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/Sha256.cpp
@@ -27,4 +27,14 @@ HashResult Sha256::Calculate(const Aws::String& str)
HashResult Sha256::Calculate(Aws::IStream& stream)
{
return m_hashImpl->Calculate(stream);
-} \ No newline at end of file
+}
+
+void Sha256::Update(unsigned char* buffer, size_t bufferSize)
+{
+ return m_hashImpl->Update(buffer, bufferSize);
+}
+
+HashResult Sha256::GetHash()
+{
+ return m_hashImpl->GetHash();
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp
index 88ca147d116..cba90af4f4d 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp
@@ -7,6 +7,7 @@
#include <aws/core/utils/crypto/Factories.h>
#include <aws/core/utils/crypto/Hash.h>
#include <aws/core/utils/crypto/HMAC.h>
+#include <aws/core/utils/crypto/CRC32.h>
#if ENABLE_BCRYPT_ENCRYPTION
#error #include <aws/core/utils/crypto/bcrypt/CryptoImpl.h>
@@ -35,6 +36,18 @@ static std::shared_ptr<HashFactory>& GetMD5Factory()
return s_MD5Factory;
}
+static std::shared_ptr<HashFactory>& GetCRC32Factory()
+{
+ static std::shared_ptr<HashFactory> s_CRC32Factory(nullptr);
+ return s_CRC32Factory;
+}
+
+static std::shared_ptr<HashFactory>& GetCRC32CFactory()
+{
+ static std::shared_ptr<HashFactory> s_CRC32CFactory(nullptr);
+ return s_CRC32CFactory;
+}
+
static std::shared_ptr<HashFactory>& GetSha1Factory()
{
static std::shared_ptr<HashFactory> s_Sha1Factory(nullptr);
@@ -136,6 +149,24 @@ public:
}
};
+class DefaultCRC32Factory : public HashFactory
+{
+public:
+ std::shared_ptr<Hash> CreateImplementation() const override
+ {
+ return Aws::MakeShared<CRC32Impl>(s_allocationTag);
+ }
+};
+
+class DefaultCRC32CFactory : public HashFactory
+{
+public:
+ std::shared_ptr<Hash> CreateImplementation() const override
+ {
+ return Aws::MakeShared<CRC32CImpl>(s_allocationTag);
+ }
+};
+
class DefaultSHA1Factory : public HashFactory
{
public:
@@ -667,6 +698,16 @@ void Aws::Utils::Crypto::InitCrypto()
GetMD5Factory()->InitStaticState();
}
+ if(!GetCRC32Factory())
+ {
+ GetCRC32Factory() = Aws::MakeShared<DefaultCRC32Factory>(s_allocationTag);
+ }
+
+ if(!GetCRC32CFactory())
+ {
+ GetCRC32CFactory() = Aws::MakeShared<DefaultCRC32CFactory>(s_allocationTag);
+ }
+
if(GetSha1Factory())
{
GetSha1Factory()->InitStaticState();
@@ -754,6 +795,16 @@ void Aws::Utils::Crypto::CleanupCrypto()
GetMD5Factory() = nullptr;
}
+ if(GetCRC32CFactory())
+ {
+ GetCRC32Factory() = nullptr;
+ }
+
+ if(GetCRC32CFactory())
+ {
+ GetCRC32CFactory() = nullptr;
+ }
+
if(GetSha1Factory())
{
GetSha1Factory()->CleanupStaticState();
@@ -809,6 +860,16 @@ void Aws::Utils::Crypto::SetMD5Factory(const std::shared_ptr<HashFactory>& facto
GetMD5Factory() = factory;
}
+void Aws::Utils::Crypto::SetCRC32Factory(const std::shared_ptr<HashFactory>& factory)
+{
+ GetCRC32Factory() = factory;
+}
+
+void Aws::Utils::Crypto::SetCRC32CFactory(const std::shared_ptr<HashFactory>& factory)
+{
+ GetCRC32CFactory() = factory;
+}
+
void Aws::Utils::Crypto::SetSha1Factory(const std::shared_ptr<HashFactory>& factory)
{
GetSha1Factory() = factory;
@@ -854,6 +915,16 @@ std::shared_ptr<Hash> Aws::Utils::Crypto::CreateMD5Implementation()
return GetMD5Factory()->CreateImplementation();
}
+std::shared_ptr<Hash> Aws::Utils::Crypto::CreateCRC32Implementation()
+{
+ return GetCRC32Factory()->CreateImplementation();
+}
+
+std::shared_ptr<Hash> Aws::Utils::Crypto::CreateCRC32CImplementation()
+{
+ return GetCRC32CFactory()->CreateImplementation();
+}
+
std::shared_ptr<Hash> Aws::Utils::Crypto::CreateSha1Implementation()
{
return GetSha1Factory()->CreateImplementation();
@@ -967,5 +1038,5 @@ std::shared_ptr<SymmetricCipher> Aws::Utils::Crypto::CreateAES_KeyWrapImplementa
std::shared_ptr<SecureRandomBytes> Aws::Utils::Crypto::CreateSecureRandomBytesImplementation()
{
- return GetSecureRandom();
+ return GetSecureRandomFactory()->CreateImplementation();
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp
index 3a89265e6ec..faebde3a8d5 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp
@@ -8,6 +8,7 @@
#include <aws/core/utils/memory/AWSMemory.h>
#include <aws/core/utils/crypto/openssl/CryptoImpl.h>
#include <aws/core/utils/Outcome.h>
+#include <openssl/crypto.h>
#include <openssl/md5.h>
#ifdef OPENSSL_IS_BORINGSSL
@@ -47,9 +48,19 @@ namespace Aws
*/
#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L)
#undef OPENSSL_VERSION_NUMBER
+#if LIBRESSL_VERSION_NUMBER < 0x3050000fL
#define OPENSSL_VERSION_NUMBER 0x1000107fL
+#else
+#define OPENSSL_VERSION_NUMBER 0x1010000fL
+#endif
#endif
+
#define OPENSSL_VERSION_LESS_1_1 (OPENSSL_VERSION_NUMBER < 0x10100003L)
+#define OPENSSL_VERSION_LESS_3_0 (OPENSSL_VERSION_NUMBER < 0x30000000L)
+
+#if !OPENSSL_VERSION_LESS_3_0
+#error #include <openssl/core_names.h>
+#endif
#if OPENSSL_VERSION_LESS_1_1
static const char* OPENSSL_INTERNALS_TAG = "OpenSSLCallbackState";
@@ -65,7 +76,7 @@ namespace Aws
#else
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS /*options*/ ,NULL /* OpenSSL init settings*/ );
#endif
-#if !defined(OPENSSL_IS_BORINGSSL)
+#if !(defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC))
OPENSSL_add_all_algorithms_noconf();
#endif
#if OPENSSL_VERSION_LESS_1_1
@@ -168,6 +179,22 @@ namespace Aws
EVP_MD_CTX *m_ctx;
};
+ MD5OpenSSLImpl::MD5OpenSSLImpl()
+ {
+ m_ctx = EVP_MD_CTX_create();
+ assert(m_ctx != nullptr);
+#if !defined(OPENSSL_IS_BORINGSSL)
+ EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ EVP_DigestInit_ex(m_ctx, EVP_md5(), nullptr);
+ }
+
+ MD5OpenSSLImpl::~MD5OpenSSLImpl()
+ {
+ EVP_MD_CTX_destroy(m_ctx);
+ m_ctx = nullptr;
+ }
+
HashResult MD5OpenSSLImpl::Calculate(const Aws::String& str)
{
OpensslCtxRAIIGuard guard;
@@ -222,6 +249,34 @@ namespace Aws
return HashResult(std::move(hash));
}
+ void MD5OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize)
+ {
+ EVP_DigestUpdate(m_ctx, buffer, bufferSize);
+ }
+
+ HashResult MD5OpenSSLImpl::GetHash()
+ {
+ ByteBuffer hash(EVP_MD_size(EVP_md5()));
+ EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr);
+ return HashResult(std::move(hash));
+ }
+
+ Sha1OpenSSLImpl::Sha1OpenSSLImpl()
+ {
+ m_ctx = EVP_MD_CTX_create();
+ assert(m_ctx != nullptr);
+#if !defined(OPENSSL_IS_BORINGSSL)
+ EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ EVP_DigestInit_ex(m_ctx, EVP_sha1(), nullptr);
+ }
+
+ Sha1OpenSSLImpl::~Sha1OpenSSLImpl()
+ {
+ EVP_MD_CTX_destroy(m_ctx);
+ m_ctx = nullptr;
+ }
+
HashResult Sha1OpenSSLImpl::Calculate(const Aws::String& str)
{
OpensslCtxRAIIGuard guard;
@@ -272,6 +327,34 @@ namespace Aws
return HashResult(std::move(hash));
}
+ void Sha1OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize)
+ {
+ EVP_DigestUpdate(m_ctx, buffer, bufferSize);
+ }
+
+ HashResult Sha1OpenSSLImpl::GetHash()
+ {
+ ByteBuffer hash(EVP_MD_size(EVP_sha1()));
+ EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr);
+ return HashResult(std::move(hash));
+ }
+
+ Sha256OpenSSLImpl::Sha256OpenSSLImpl()
+ {
+ m_ctx = EVP_MD_CTX_create();
+ assert(m_ctx != nullptr);
+#if !defined(OPENSSL_IS_BORINGSSL)
+ EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ EVP_DigestInit_ex(m_ctx, EVP_sha256(), nullptr);
+ }
+
+ Sha256OpenSSLImpl::~Sha256OpenSSLImpl()
+ {
+ EVP_MD_CTX_destroy(m_ctx);
+ m_ctx = nullptr;
+ }
+
HashResult Sha256OpenSSLImpl::Calculate(const Aws::String& str)
{
OpensslCtxRAIIGuard guard;
@@ -322,13 +405,28 @@ namespace Aws
return HashResult(std::move(hash));
}
+ void Sha256OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize)
+ {
+ EVP_DigestUpdate(m_ctx, buffer, bufferSize);
+ }
+
+ HashResult Sha256OpenSSLImpl::GetHash()
+ {
+ ByteBuffer hash(EVP_MD_size(EVP_sha256()));
+ EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr);
+ return HashResult(std::move(hash));
+ }
+
class HMACRAIIGuard {
public:
HMACRAIIGuard() {
#if OPENSSL_VERSION_LESS_1_1
m_ctx = Aws::New<HMAC_CTX>("AllocSha256HAMCOpenSSLContext");
-#else
+#elif OPENSSL_VERSION_LESS_3_0
m_ctx = HMAC_CTX_new();
+#else
+ m_mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ m_ctx = EVP_MAC_CTX_new(m_mac);
#endif
assert(m_ctx != nullptr);
}
@@ -336,17 +434,29 @@ namespace Aws
~HMACRAIIGuard() {
#if OPENSSL_VERSION_LESS_1_1
Aws::Delete<HMAC_CTX>(m_ctx);
-#else
+#elif OPENSSL_VERSION_LESS_3_0
HMAC_CTX_free(m_ctx);
+#else
+ EVP_MAC_free(m_mac);
+ EVP_MAC_CTX_free(m_ctx);
#endif
m_ctx = nullptr;
}
+#if OPENSSL_VERSION_LESS_3_0
HMAC_CTX* getResource() {
+#else
+ EVP_MAC_CTX* getResource() {
+#endif
return m_ctx;
}
private:
+#if OPENSSL_VERSION_LESS_3_0
HMAC_CTX *m_ctx;
+#else
+ EVP_MAC *m_mac;
+ EVP_MAC_CTX *m_ctx;
+#endif
};
HashResult Sha256HMACOpenSSLImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret)
@@ -356,20 +466,36 @@ namespace Aws
memset(digest.GetUnderlyingData(), 0, length);
HMACRAIIGuard guard;
+#if OPENSSL_VERSION_LESS_3_0
HMAC_CTX* m_ctx = guard.getResource();
+#else
+ EVP_MAC_CTX* m_ctx = guard.getResource();
+#endif
#if OPENSSL_VERSION_LESS_1_1
HMAC_CTX_init(m_ctx);
#endif
+#if OPENSSL_VERSION_LESS_3_0
HMAC_Init_ex(m_ctx, secret.GetUnderlyingData(), static_cast<int>(secret.GetLength()), EVP_sha256(),
NULL);
HMAC_Update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength());
HMAC_Final(m_ctx, digest.GetUnderlyingData(), &length);
+#else
+ char sha256[] {"SHA256"};
+ OSSL_PARAM ossl_params[2];
+ ossl_params[0] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, sha256, 0);
+ ossl_params[1] = OSSL_PARAM_construct_end();
+ EVP_MAC_init(m_ctx, secret.GetUnderlyingData(),
+ static_cast<int>(secret.GetLength()), ossl_params);
+ EVP_MAC_update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength());
+ EVP_MAC_final(m_ctx, digest.GetUnderlyingData(), NULL, length);
+#endif
#if OPENSSL_VERSION_LESS_1_1
HMAC_CTX_cleanup(m_ctx);
-#else
+#elif OPENSSL_VERSION_LESS_3_0
HMAC_CTX_reset(m_ctx);
#endif
return HashResult(std::move(digest));
@@ -547,7 +673,7 @@ namespace Aws
CryptoBuffer finalBlock(GetBlockSizeBytes());
int writtenSize = static_cast<int>(finalBlock.GetLength());
int ret = EVP_DecryptFinal_ex(m_decryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize);
-#if OPENSSL_VERSION_NUMBER > 0x1010104fL //1.1.1d
+#if !defined(OPENSSL_IS_AWSLC) && OPENSSL_VERSION_NUMBER > 0x1010104fL //1.1.1d
if (ret <= 0)
#else
if (ret <= 0 && !m_emptyPlaintext) // see details why making exception for empty string at: https://github.com/aws/aws-sdk-cpp/issues/1413
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamDecoder.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamDecoder.cpp
index f70a6c88f61..053ff938d44 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamDecoder.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamDecoder.cpp
@@ -72,9 +72,7 @@ namespace Aws
assert(handler);
if (!handler)
{
- AWS_LOGSTREAM_ERROR(EVENT_STREAM_DECODER_CLASS_TAG, "Payload received, but decoder encountered internal errors before."
- "ErrorCode: " << EventStreamErrorsMapper::GetNameForError(handler->GetInternalError()) << ", "
- "ErrorMessage: " << handler->GetEventPayloadAsString());
+ AWS_LOGSTREAM_ERROR(EVENT_STREAM_DECODER_CLASS_TAG, "Payload received, but handler is null.");
return;
}
handler->WriteMessageEventPayload(static_cast<unsigned char*>(payload->buffer), payload->len);
@@ -129,9 +127,7 @@ namespace Aws
assert(handler);
if (!handler)
{
- AWS_LOGSTREAM_ERROR(EVENT_STREAM_DECODER_CLASS_TAG, "Payload received, but decoder encountered internal errors before."
- "ErrorCode: " << EventStreamErrorsMapper::GetNameForError(handler->GetInternalError()) << ", "
- "ErrorMessage: " << handler->GetEventPayloadAsString());
+ AWS_LOGSTREAM_ERROR(EVENT_STREAM_DECODER_CLASS_TAG, "Header received, but handler is null.");
return;
}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp
index ef7104e839c..750bf9e1e6d 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp
@@ -80,80 +80,83 @@ namespace Aws
Aws::Vector<unsigned char> EventStreamEncoder::EncodeAndSign(const Aws::Utils::Event::Message& msg)
{
- aws_event_stream_message encoded = Encode(msg);
- aws_event_stream_message signedMessage = Sign(&encoded);
+ Aws::Vector<unsigned char> outputBits;
- const auto signedMessageLength = signedMessage.message_buffer ? aws_event_stream_message_total_length(&signedMessage) : 0;
+ aws_event_stream_message encoded;
+ if (InitEncodedStruct(msg, &encoded))
+ {
+ aws_event_stream_message signedMessage;
+ if (InitSignedStruct(&encoded, &signedMessage))
+ {
+ // success!
+ const auto signedMessageBuffer = aws_event_stream_message_buffer(&signedMessage);
+ const auto signedMessageLength = aws_event_stream_message_total_length(&signedMessage);
+ outputBits.reserve(signedMessageLength);
+ outputBits.insert(outputBits.end(), signedMessageBuffer, signedMessageBuffer + signedMessageLength);
+
+ aws_event_stream_message_clean_up(&signedMessage);
+ }
+ aws_event_stream_message_clean_up(&encoded);
+ }
- Aws::Vector<unsigned char> outputBits(signedMessage.message_buffer, signedMessage.message_buffer + signedMessageLength);
- aws_event_stream_message_clean_up(&encoded);
- aws_event_stream_message_clean_up(&signedMessage);
return outputBits;
}
- aws_event_stream_message EventStreamEncoder::Encode(const Aws::Utils::Event::Message& msg)
+ bool EventStreamEncoder::InitEncodedStruct(const Aws::Utils::Event::Message& msg, aws_event_stream_message* encoded)
{
+ bool success = false;
+
aws_array_list headers;
EncodeHeaders(msg, &headers);
- aws_byte_buf payload;
- payload.len = msg.GetEventPayload().size();
- // this const_cast is OK because aws_byte_buf will only be "read from" by the following functions.
- payload.buffer = const_cast<uint8_t*>(msg.GetEventPayload().data());
- payload.capacity = 0;
- payload.allocator = nullptr;
+ aws_byte_buf payload = aws_byte_buf_from_array(msg.GetEventPayload().data(), msg.GetEventPayload().size());
- aws_event_stream_message encoded;
- if(aws_event_stream_message_init(&encoded, get_aws_allocator(), &headers, &payload) == AWS_OP_ERR)
+ if(aws_event_stream_message_init(encoded, get_aws_allocator(), &headers, &payload) == AWS_OP_SUCCESS)
+ {
+ success = true;
+ }
+ else
{
AWS_LOGSTREAM_ERROR(TAG, "Error creating event-stream message from payload.");
- aws_event_stream_headers_list_cleanup(&headers);
- // GCC 4.9.4 issues a warning with -Wextra if we simply do
- // return {};
- aws_event_stream_message empty{nullptr, nullptr, 0};
- return empty;
}
+
aws_event_stream_headers_list_cleanup(&headers);
- return encoded;
+ return success;
}
- aws_event_stream_message EventStreamEncoder::Sign(aws_event_stream_message* msg)
+ bool EventStreamEncoder::InitSignedStruct(const aws_event_stream_message* msg, aws_event_stream_message* signedmsg)
{
- const auto msglen = msg->message_buffer ? aws_event_stream_message_total_length(msg) : 0;
+ bool success = false;
+
+ const auto msgbuf = aws_event_stream_message_buffer(msg);
+ const auto msglen = aws_event_stream_message_total_length(msg);
Event::Message signedMessage;
- signedMessage.WriteEventPayload(msg->message_buffer, msglen);
+ signedMessage.WriteEventPayload(msgbuf, msglen);
assert(m_signer);
- if (!m_signer->SignEventMessage(signedMessage, m_signatureSeed))
+ if (m_signer->SignEventMessage(signedMessage, m_signatureSeed))
{
- AWS_LOGSTREAM_ERROR(TAG, "Failed to sign event message frame.");
- // GCC 4.9.4 issues a warning with -Wextra if we simply do
- // return {};
- aws_event_stream_message empty{nullptr, nullptr, 0};
- return empty;
- }
-
- aws_array_list headers;
- EncodeHeaders(signedMessage, &headers);
+ aws_array_list headers;
+ EncodeHeaders(signedMessage, &headers);
- aws_byte_buf payload;
- payload.len = signedMessage.GetEventPayload().size();
- payload.buffer = signedMessage.GetEventPayload().data();
- payload.capacity = 0;
- payload.allocator = nullptr;
+ aws_byte_buf payload = aws_byte_buf_from_array(signedMessage.GetEventPayload().data(), signedMessage.GetEventPayload().size());
- aws_event_stream_message signedmsg;
- if(aws_event_stream_message_init(&signedmsg, get_aws_allocator(), &headers, &payload))
- {
- AWS_LOGSTREAM_ERROR(TAG, "Error creating event-stream message from payload.");
+ if(aws_event_stream_message_init(signedmsg, get_aws_allocator(), &headers, &payload) == AWS_OP_SUCCESS)
+ {
+ success = true;
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(TAG, "Error creating event-stream message from payload.");
+ }
aws_event_stream_headers_list_cleanup(&headers);
- // GCC 4.9.4 issues a warning with -Wextra if we simply do
- // return {};
- aws_event_stream_message empty{nullptr, nullptr, 0};
- return empty;
}
- aws_event_stream_headers_list_cleanup(&headers);
- return signedmsg;
+ else
+ {
+ AWS_LOGSTREAM_ERROR(TAG, "Failed to sign event message frame.");
+ }
+
+ return success;
}
} // namespace Event
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp
index 9358d00c0a8..ebfd5d44568 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/json/JsonSerializer.cpp
@@ -9,6 +9,7 @@
#include <algorithm>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/Document.h>
using namespace Aws::Utils;
using namespace Aws::Utils::Json;
@@ -68,6 +69,13 @@ JsonValue::JsonValue(JsonValue&& value) :
value.m_value = nullptr;
}
+JsonValue::JsonValue(const Aws::Utils::DocumentView& value) :
+ m_value(cJSON_AS4CPP_Duplicate(value.m_json, true/*recurse*/)),
+ m_wasParseSuccessful(true),
+ m_errorMessage({})
+{
+}
+
void JsonValue::Destroy()
{
cJSON_AS4CPP_Delete(m_value);
@@ -106,6 +114,15 @@ JsonValue& JsonValue::operator=(JsonValue&& other)
return *this;
}
+JsonValue& JsonValue::operator=(const Aws::Utils::DocumentView& other)
+{
+ Destroy();
+ m_value = cJSON_AS4CPP_Duplicate(other.m_json, true /*recurse*/);
+ m_wasParseSuccessful = true;
+ m_errorMessage = {};
+ return *this;
+}
+
static void AddOrReplace(cJSON* root, const char* key, cJSON* value)
{
const auto existing = cJSON_AS4CPP_GetObjectItemCaseSensitive(root, key);
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogSystem.cpp
new file mode 100644
index 00000000000..81f94d0d3af
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogSystem.cpp
@@ -0,0 +1,107 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/utils/logging/CRTLogSystem.h>
+#include <aws/core/utils/logging/AWSLogging.h>
+#include <aws/core/utils/logging/LogSystemInterface.h>
+#include <aws/core/utils/Array.h>
+#include <aws/common/common.h>
+#include <cstdarg>
+
+using namespace Aws::Utils;
+using namespace Aws::Utils::Logging;
+
+namespace Aws
+{
+ namespace Utils
+ {
+ namespace Logging
+ {
+ static int s_aws_logger_redirect_log(
+ struct aws_logger *logger,
+ enum aws_log_level log_level,
+ aws_log_subject_t subject,
+ const char *format, ...)
+ {
+ DefaultCRTLogSystem* crtLogSystem = reinterpret_cast<DefaultCRTLogSystem*>(logger->p_impl);
+ Logging::LogLevel logLevel = static_cast<LogLevel>(log_level);
+ const char* subjectName = aws_log_subject_name(subject);
+ va_list args;
+ va_start(args, format);
+ crtLogSystem->Log(logLevel, subjectName, format, args);
+ va_end(args);
+ return AWS_OP_SUCCESS;
+ }
+
+ static enum aws_log_level s_aws_logger_redirect_get_log_level(struct aws_logger *logger, aws_log_subject_t subject) {
+ (void)subject;
+ DefaultCRTLogSystem* crtLogSystem = reinterpret_cast<DefaultCRTLogSystem*>(logger->p_impl);
+ return (aws_log_level)(crtLogSystem->GetLogLevel());
+ }
+
+ static void s_aws_logger_redirect_clean_up(struct aws_logger *logger) {
+ (void)logger;
+ }
+
+ static int s_aws_logger_redirect_set_log_level(struct aws_logger *logger, enum aws_log_level log_level)
+ {
+ DefaultCRTLogSystem* crtLogSystem = reinterpret_cast<DefaultCRTLogSystem*>(logger->p_impl);
+ crtLogSystem->SetLogLevel(static_cast<LogLevel>(log_level));
+ return AWS_OP_SUCCESS;
+ }
+
+ static struct aws_logger_vtable s_aws_logger_redirect_vtable = {
+ s_aws_logger_redirect_log, // .log
+ s_aws_logger_redirect_get_log_level, // .get_log_level
+ s_aws_logger_redirect_clean_up, // .clean_up
+ s_aws_logger_redirect_set_log_level // set_log_level
+ };
+
+ DefaultCRTLogSystem::DefaultCRTLogSystem(LogLevel logLevel) :
+ m_logLevel(logLevel),
+ m_logger()
+ {
+ m_logger.vtable = &s_aws_logger_redirect_vtable;
+ m_logger.allocator = Aws::get_aws_allocator();
+ m_logger.p_impl = this;
+
+ aws_logger_set(&m_logger);
+ }
+
+ DefaultCRTLogSystem::~DefaultCRTLogSystem()
+ {
+ if (aws_logger_get() == &m_logger)
+ {
+ aws_logger_set(NULL);
+ aws_logger_clean_up(&m_logger);
+ }
+ }
+
+ void DefaultCRTLogSystem::Log(LogLevel logLevel, const char* subjectName, const char* formatStr, va_list args)
+ {
+ va_list tmp_args;
+ va_copy(tmp_args, args);
+ #ifdef _WIN32
+ const int requiredLength = _vscprintf(formatStr, tmp_args) + 1;
+ #else
+ const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1;
+ #endif
+ va_end(tmp_args);
+
+ Array<char> outputBuff(requiredLength);
+ #ifdef _WIN32
+ vsnprintf_s(outputBuff.GetUnderlyingData(), requiredLength, _TRUNCATE, formatStr, args);
+ #else
+ vsnprintf(outputBuff.GetUnderlyingData(), requiredLength, formatStr, args);
+ #endif // _WIN32
+
+ Aws::OStringStream logStream;
+ logStream << outputBuff.GetUnderlyingData();
+ Logging::GetLogSystem()->LogStream(logLevel, subjectName, logStream);
+ }
+ }
+ }
+}
+
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogging.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogging.cpp
new file mode 100644
index 00000000000..5875ead9c01
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/CRTLogging.cpp
@@ -0,0 +1,31 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/utils/logging/CRTLogging.h>
+#include <aws/common/logging.h>
+#include <memory>
+
+using namespace Aws::Utils;
+using namespace Aws::Utils::Logging;
+
+namespace Aws
+{
+namespace Utils
+{
+namespace Logging {
+
+static std::shared_ptr<CRTLogSystemInterface> CRTLogSystem(nullptr);
+
+void InitializeCRTLogging(const std::shared_ptr<CRTLogSystemInterface>& crtLogSystem) {
+ CRTLogSystem = crtLogSystem;
+}
+
+void ShutdownCRTLogging() {
+ CRTLogSystem = nullptr;
+}
+
+} // namespace Logging
+} // namespace Utils
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp
index 41c4d7e09c5..26348b68fe2 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/logging/FormattedLogSystem.cpp
@@ -72,7 +72,7 @@ void FormattedLogSystem::Log(LogLevel logLevel, const char* tag, const char* for
va_list tmp_args; //unfortunately you cannot consume a va_list twice
va_copy(tmp_args, args); //so we have to copy it
- #ifdef WIN32
+ #ifdef _WIN32
const int requiredLength = _vscprintf(formatStr, tmp_args) + 1;
#else
const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1;
@@ -80,11 +80,11 @@ void FormattedLogSystem::Log(LogLevel logLevel, const char* tag, const char* for
va_end(tmp_args);
Array<char> outputBuff(requiredLength);
- #ifdef WIN32
+ #ifdef _WIN32
vsnprintf_s(outputBuff.GetUnderlyingData(), requiredLength, _TRUNCATE, formatStr, args);
#else
vsnprintf(outputBuff.GetUnderlyingData(), requiredLength, formatStr, args);
- #endif // WIN32
+ #endif // _WIN32
ss << outputBuff.GetUnderlyingData() << std::endl;
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp
index 6d1f90ed124..26c92eaafdf 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/ResponseStream.cpp
@@ -5,6 +5,7 @@
#include <aws/core/utils/stream/ResponseStream.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/core/utils/logging/LogMacros.h>
#if defined(_GLIBCXX_FULLY_DYNAMIC_STRING) && _GLIBCXX_FULLY_DYNAMIC_STRING == 0 && defined(__ANDROID__)
#include <aws/core/utils/stream/SimpleStreamBuf.h>
@@ -15,6 +16,8 @@ using DefaultStreamBufType = Aws::StringBuf;
using namespace Aws::Utils::Stream;
+const int ResponseStream::ResponseStream::xindex = std::ios_base::xalloc();
+
ResponseStream::ResponseStream(void) :
m_underlyingStream(nullptr)
{
@@ -23,16 +26,20 @@ ResponseStream::ResponseStream(void) :
ResponseStream::ResponseStream(Aws::IOStream* underlyingStreamToManage) :
m_underlyingStream(underlyingStreamToManage)
{
+ RegisterStream();
}
ResponseStream::ResponseStream(const Aws::IOStreamFactory& factory) :
m_underlyingStream(factory())
{
+ RegisterStream();
}
ResponseStream::ResponseStream(ResponseStream&& toMove) : m_underlyingStream(toMove.m_underlyingStream)
{
+ toMove.DeregisterStream();
toMove.m_underlyingStream = nullptr;
+ RegisterStream();
}
ResponseStream& ResponseStream::operator=(ResponseStream&& toMove)
@@ -43,12 +50,26 @@ ResponseStream& ResponseStream::operator=(ResponseStream&& toMove)
}
ReleaseStream();
+ toMove.DeregisterStream();
m_underlyingStream = toMove.m_underlyingStream;
toMove.m_underlyingStream = nullptr;
+ RegisterStream();
return *this;
}
+Aws::IOStream& ResponseStream::GetUnderlyingStream() const
+{
+ if (!m_underlyingStream)
+ {
+ assert(m_underlyingStream);
+ AWS_LOGSTREAM_FATAL("ResponseStream", "Unexpected nullptr m_underlyingStream");
+ static DefaultUnderlyingStream fallbackStream; // we are already in UB, let's just not crash existing apps
+ return fallbackStream;
+ }
+ return *m_underlyingStream;
+}
+
ResponseStream::~ResponseStream()
{
ReleaseStream();
@@ -58,13 +79,53 @@ void ResponseStream::ReleaseStream()
{
if (m_underlyingStream)
{
- m_underlyingStream->flush();
+ DeregisterStream();
Aws::Delete(m_underlyingStream);
}
m_underlyingStream = nullptr;
}
+void ResponseStream::RegisterStream()
+{
+ if (m_underlyingStream)
+ {
+ ResponseStream* pThat = static_cast<ResponseStream*>(m_underlyingStream->pword(ResponseStream::xindex));
+ if (pThat != nullptr)
+ {
+ // callback is already registered
+ assert(pThat != this); // Underlying stream must not be owned by more than one ResponseStream
+ }
+ else
+ {
+ m_underlyingStream->register_callback(ResponseStream::StreamCallback, ResponseStream::xindex);
+ }
+ m_underlyingStream->pword(ResponseStream::xindex) = this;
+ }
+}
+
+void ResponseStream::DeregisterStream()
+{
+ if (m_underlyingStream)
+ {
+ assert(static_cast<ResponseStream*>(m_underlyingStream->pword(ResponseStream::xindex)) == this); // Attempt to deregister another ResponseStream's stream
+ m_underlyingStream->pword(ResponseStream::xindex) = nullptr; // ios does not support deregister, so just erasing the context
+ }
+}
+
+void ResponseStream::StreamCallback(Aws::IOStream::event evt, std::ios_base& stream, int idx)
+{
+ if (evt == std::ios_base::erase_event)
+ {
+ ResponseStream* pThis = static_cast<ResponseStream*>(stream.pword(idx));
+ if (pThis)
+ {
+ // m_underlyingStream is being destructed, let's avoid double destruction or having a dangling pointer
+ pThis->m_underlyingStream = nullptr;
+ }
+ }
+}
+
static const char *DEFAULT_STREAM_TAG = "DefaultUnderlyingStream";
DefaultUnderlyingStream::DefaultUnderlyingStream() :
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp
index 6e429947445..dbf77ab6468 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/stream/SimpleStreamBuf.cpp
@@ -5,6 +5,7 @@
*/
#include <aws/core/utils/stream/SimpleStreamBuf.h>
+#include <aws/core/utils/logging/LogMacros.h>
#include <algorithm>
#include <cassert>
@@ -123,7 +124,14 @@ bool SimpleStreamBuf::GrowBuffer()
if(currentSize > 0)
{
- std::memcpy(newBuffer, m_buffer, currentSize);
+ if(m_buffer)
+ {
+ std::memcpy(newBuffer, m_buffer, currentSize);
+ }
+ else
+ {
+ AWS_LOGSTREAM_FATAL(SIMPLE_STREAMBUF_ALLOCATION_TAG, "Unexpected nullptr m_buffer");
+ }
}
if(m_buffer)
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp
index 4a3c4209c41..f9538f00336 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/threading/Executor.cpp
@@ -14,10 +14,15 @@ using namespace Aws::Utils::Threading;
bool DefaultExecutor::SubmitToThread(std::function<void()>&& fx)
{
- auto main = [fx, this] {
- fx();
- Detach(std::this_thread::get_id());
- };
+ // Generalized lambda capture is C++14, using std::bind as a workaround to force moving fx (instead of copying)
+ std::function<void()> main = std::bind(
+ [this](std::function<void()>& storedFx)
+ {
+ storedFx();
+ Detach(std::this_thread::get_id());
+ },
+ std::move(fx)
+ );
State expected;
do
@@ -25,7 +30,7 @@ bool DefaultExecutor::SubmitToThread(std::function<void()>&& fx)
expected = State::Free;
if(m_state.compare_exchange_strong(expected, State::Locked))
{
- std::thread t(main);
+ std::thread t(std::move(main));
const auto id = t.get_id(); // copy the id before we std::move the thread
m_threads.emplace(id, std::move(t));
m_state = State::Free;
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp
index c06befaf9b0..2d91f700005 100644
--- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/xml/XmlSerializer.cpp
@@ -23,6 +23,8 @@ Aws::String Aws::Utils::Xml::DecodeEscapedXmlText(const Aws::String& textToDecod
StringUtils::Replace(decodedString, "&lt;", "<");
StringUtils::Replace(decodedString, "&gt;", ">");
StringUtils::Replace(decodedString, "&amp;", "&");
+ StringUtils::Replace(decodedString, "&#xA;", "\n");
+ StringUtils::Replace(decodedString, "&#xD;", "\r");
return decodedString;
}