diff --git a/src/aws-cpp-sdk-core/CMakeLists.txt b/src/aws-cpp-sdk-core/CMakeLists.txt index 80f09662fd6..2ff442aab85 100644 --- a/src/aws-cpp-sdk-core/CMakeLists.txt +++ b/src/aws-cpp-sdk-core/CMakeLists.txt @@ -73,8 +73,10 @@ file(GLOB UTILS_STREAM_HEADERS "include/aws/core/utils/stream/*.h") file(GLOB CJSON_HEADERS "include/aws/core/external/cjson/*.h") file(GLOB TINYXML2_HEADERS "include/aws/core/external/tinyxml2/tinyxml2.h") file(GLOB SMITHY_HEADERS "include/smithy/*.h") +file(GLOB SMITHY_CLIENT_HEADERS "include/smithy/client/*.h" "include/smithy/client/impl/*.h") file(GLOB SMITHY_TRACING_HEADERS "include/smithy/tracing/*.h") file(GLOB SMITHY_IDENTITY_HEADERS "include/smithy/identity/*.h") +file(GLOB SMITHY_IDENTITY_AUTH_HEADERS "include/smithy/identity/auth/*.h" "include/smithy/identity/auth/impl/*.h") file(GLOB SMITHY_IDENTITY_IDENTITY_HEADERS "include/smithy/identity/identity/*.h" "include/smithy/identity/identity/impl/*.h") file(GLOB SMITHY_IDENTITY_RESOLVER_HEADERS "include/smithy/identity/resolver/*.h" "include/smithy/identity/resolver/impl/*.h") @@ -109,6 +111,7 @@ file(GLOB UTILS_MEMORY_STL_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/memo file(GLOB UTILS_STREAM_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/stream/*.cpp") file(GLOB UTILS_CRYPTO_FACTORY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/crypto/factory/*.cpp") file(GLOB SMITHY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/smithy/*.cpp") +file(GLOB SMITHY_CLIENT_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/smithy/client/*.cpp") file(GLOB SMITHY_IDENTITY_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/smithy/identity/*.cpp") file(GLOB SMITHY_TRACING_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/smithy/tracing/*.cpp") @@ -287,6 +290,7 @@ file(GLOB AWS_NATIVE_SDK_COMMON_SRC ${UTILS_MEMORY_STL_SOURCE} ${UTILS_CRYPTO_CRT_SOURCE} ${SMITHY_SOURCE} + ${SMITHY_CLIENT_SOURCE} ${SMITHY_IDENTITY_SOURCE} ${SMITHY_TRACING_SOURCE} ) @@ -328,8 +332,10 @@ file(GLOB AWS_NATIVE_SDK_COMMON_HEADERS ${HTTP_CURL_CLIENT_HEADERS} ${HTTP_WINDOWS_CLIENT_HEADERS} ${SMITHY_HEADERS} + ${SMITHY_CLIENT_HEADERS} ${SMITHY_TRACING_HEADERS} ${SMITHY_IDENTITY_HEADERS} + ${SMITHY_IDENTITY_AUTH_HEADERS} ${SMITHY_IDENTITY_IDENTITY_HEADERS} ${SMITHY_IDENTITY_RESOLVER_HEADERS} ${OPTEL_HEADERS} @@ -448,7 +454,9 @@ if(MSVC) source_group("Header Files\\aws\\core\\external\\cjson" FILES ${CJSON_HEADERS}) source_group("Header Files\\aws\\core\\external\\tinyxml2" FILES ${TINYXML2_HEADERS}) source_group("Header Files\\smithy" FILES ${SMITHY_HEADERS}) + source_group("Header Files\\smithy\\client" FILES ${SMITHY_CLIENT_HEADERS}) source_group("Header Files\\smithy\\tracing" FILES ${SMITHY_TRACING_HEADERS}) + source_group("Header Files\\smithy\\identity\\auth" FILES ${SMITHY_IDENTITY_AUTH_HEADERS}) source_group("Header Files\\smithy\\identity\\identity" FILES ${SMITHY_IDENTITY_IDENTITY_HEADERS}) source_group("Header Files\\smithy\\identity\\resolver" FILES ${SMITHY_IDENTITY_RESOLVER_HEADERS}) @@ -497,6 +505,7 @@ if(MSVC) source_group("Source Files\\utils\\component-registry" FILES ${UTILS_COMPONENT_REGISTRY_SOURCE}) source_group("Source Files\\utils\\memory\\stl" FILES ${UTILS_MEMORY_STL_SOURCE}) source_group("Source Files\\smithy" FILES ${SMITHY_SOURCE}) + source_group("Source Files\\smithy\\client" FILES ${SMITHY_CLIENT_SOURCE}) source_group("Source Files\\smithy\\identity" FILES ${SMITHY_IDENTITY_SOURCE}) source_group("Source Files\\smithy\\tracing" FILES ${SMITHY_TRACING_SOURCE}) @@ -707,8 +716,10 @@ install (FILES ${UTILS_THREADING_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/c install (FILES ${CJSON_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/external/cjson) install (FILES ${TINYXML2_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/external/tinyxml2) install (FILES ${SMITHY_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy) +install (FILES ${SMITHY_CLIENT_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/client) install (FILES ${SMITHY_TRACING_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/tracing) install (FILES ${SMITHY_IDENTITY_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/identity) +install (FILES ${SMITHY_IDENTITY_AUTH_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/identity/auth) install (FILES ${SMITHY_IDENTITY_IDENTITY_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/identity/identity) install (FILES ${SMITHY_IDENTITY_RESOLVER_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/smithy/identity/resolver) diff --git a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h new file mode 100644 index 00000000000..361189b0081 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h @@ -0,0 +1,65 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include + +#include +#include +#include + +#include +#include + + +namespace smithy +{ + class AwsClientAsyncRequestCtx + { + public: + using AwsCoreError = Aws::Client::AWSError; + using HttpResponseOutcome = Aws::Utils::Outcome, AwsCoreError>; + + struct RequestInfo + { + Aws::Utils::DateTime ttl; + long attempt; + long maxAttempts; + + explicit operator Aws::String() const + { + Aws::StringStream ss; + if (ttl.WasParseSuccessful() && ttl != Aws::Utils::DateTime()) + { + assert(attempt > 1); + ss << "ttl=" << ttl.ToGmtString(Aws::Utils::DateFormat::ISO_8601_BASIC) << "; "; + } + ss << "attempt=" << attempt; + if (maxAttempts > 0) + { + ss << "; max=" << maxAttempts; + } + return ss.str(); + } + }; + + Aws::String m_invocationId; + Aws::Http::HttpMethod m_method; + const Aws::AmazonWebServiceRequest* m_pRequest; // optional + + RequestInfo m_requestInfo; + Aws::String m_requestName; + std::shared_ptr m_httpRequest; + Aws::Endpoint::AWSEndpoint m_endpoint; + + Aws::Crt::Optional m_lastError; + + size_t m_retryCount; + Aws::Vector m_monitoringContexts; + + std::function m_responseHandler; + std::shared_ptr m_pExecutor; + }; +} // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyRequestSigning.h b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyRequestSigning.h new file mode 100644 index 00000000000..11cc0d47a6e --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyRequestSigning.h @@ -0,0 +1,126 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + + +namespace smithy +{ + template + class AwsClientRequestSigning + { + public: + using HttpRequest = Aws::Http::HttpRequest; + using SigningError = Aws::Client::AWSError; + using SigningOutcome = Aws::Utils::FutureOutcome; + + static SigningOutcome SignRequest(const HttpRequest& HTTPRequest, const AuthOption& authOption, + const Aws::UnorderedMap& authSchemes) + { + auto authSchemeIt = authSchemes.find(authOption.schemeId); + if (authSchemeIt == authSchemes.end()) + { + assert(!"Auth scheme has not been found for a given auth option!"); + return (SigningError(Aws::Client::CoreErrors::CLIENT_SIGNING_FAILURE, + "", + "Requested AuthOption was not found within client Auth Schemes", + false/*retryable*/)); + } + + AuthSchemesVariantT authScheme = *authSchemeIt; + + return SignWithAuthScheme(HTTPRequest, authScheme, authOption); + } + + protected: + struct SignerVisitor + { + SignerVisitor(const HttpRequest& httpRequest, const AuthOption& targetAuthOption) + : m_httpRequest(httpRequest), m_targetAuthOption(targetAuthOption) + { + } + + const HttpRequest& m_httpRequest; + const AuthOption& m_targetAuthOption; + + Aws::Crt::Optional result; + + template + void operator()(AuthSchemeAlternativeT& authScheme) + { + // Auth Scheme Variant alternative contains the requested auth option + assert(strcmp(authScheme.schemeId, m_targetAuthOption.schemeId) == 0); + + using IdentityT = typename decltype(authScheme)::IdentityT; + using IdentityResolver = IdentityResolverBase; + using Signer = AwsSignerBase; + + std::shared_ptr identityResolver = authScheme.identityResolver(); + if (!identityResolver) + { + result.emplace(SigningError(Aws::Client::CoreErrors::CLIENT_SIGNING_FAILURE, + "", + "Auth scheme provided a nullptr identityResolver", + false/*retryable*/)); + return; + } + + static_assert( + std::is_same, typename decltype(identityResolver + )::IdentityT>::value); + static_assert(std::is_base_of, decltype(identityResolver)>::value); + + IdentityT identity = identityResolver->getIdentity(m_targetAuthOption.identityProperties); + + std::shared_ptr signer = authScheme.signer(); + if (!signer) + { + result.emplace(SigningError(Aws::Client::CoreErrors::CLIENT_SIGNING_FAILURE, + "", + "Auth scheme provided a nullptr signer", + false/*retryable*/)); + return; + } + + + static_assert(std::is_same, typename decltype(signer)::IdentityT>::value); + static_assert(std::is_base_of, decltype(signer)>::value); + + result.emplace(signer->sign(m_httpRequest, identity, m_targetAuthOption.signerProperties)); + } + }; + + static + SigningOutcome SignWithAuthScheme(const HttpRequest& HTTPRequest, const AuthSchemesVariantT& authSchemesVariant, + const AuthOption& targetAuthOption) + { + SignerVisitor visitor(HTTPRequest, targetAuthOption); + visitor.Visit(authSchemesVariant); + + if (!visitor.result) + { + return (SigningError(Aws::Client::CoreErrors::CLIENT_SIGNING_FAILURE, + "", + "Failed to sign with an unknown error", + false/*retryable*/)); + } + return std::move(*visitor.result); + } + }; +} diff --git a/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthOption.h b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthOption.h new file mode 100644 index 00000000000..1403ed61eae --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthOption.h @@ -0,0 +1,24 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include + +#include +#include + +namespace smithy { + /* AuthOption and AuthOptionResolver */ + class AuthOption + { + using PropertyBag = Aws::UnorderedMap>; + /* note: AuthOption is not connected with AuthScheme by type system, only by the String of schemeId, this is in accordance with SRA */ + public: + static const char* schemeId; + + PropertyBag identityProperties{}; + PropertyBag signerProperties{}; + }; +} \ No newline at end of file diff --git a/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthScheme.h b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthScheme.h new file mode 100644 index 00000000000..3f22ad2cb54 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthScheme.h @@ -0,0 +1,25 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include +#include + +namespace smithy { + template + class AuthScheme + { + public: + using IdentityT = IDENTITY_T; + + static const uint64_t schemeId; + + virtual ~AuthScheme() = default; + + virtual std::shared_ptr> identityResolver() = 0; + + virtual std::shared_ptr> signer() = 0; + }; +} \ No newline at end of file diff --git a/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthSchemeResolverBase.h b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthSchemeResolverBase.h new file mode 100644 index 00000000000..d1021979b2b --- /dev/null +++ b/src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthSchemeResolverBase.h @@ -0,0 +1,24 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#pragma once + +#include +#include + +#include +#include + +namespace smithy { + template>> + class AuthSchemeResolverBase + { + public: + using ServiceAuthSchemeParameters = ServiceAuthSchemeParametersT; + + virtual ~AuthSchemeResolverBase() = default; + // AuthScheme Resolver returns a list of AuthOptions for some reason, according to the SRA... + virtual std::vector resolveAuthScheme(const ServiceAuthSchemeParameters& identityProperties) = 0; + }; +} \ No newline at end of file