diff --git a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClient.h b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClient.h index 0b79aceda1a..a25d3117d4c 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClient.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClient.h @@ -171,9 +171,9 @@ namespace client false/*retryable*/); } - SigningOutcome SignHttpRequest(std::shared_ptr httpRequest, const AuthSchemeOption& targetAuthSchemeOption) const override + SigningOutcome SignHttpRequest(std::shared_ptr httpRequest, const AwsSmithyClientAsyncRequestContext& ctx) const override { - return AwsClientRequestSigning::SignRequest(httpRequest, targetAuthSchemeOption, m_authSchemes); + return AwsClientRequestSigning::SignRequest(httpRequest, ctx, m_authSchemes); } bool AdjustClockSkew(HttpResponseOutcome& outcome, const AuthSchemeOption& authSchemeOption) const override @@ -181,6 +181,19 @@ namespace client return AwsClientRequestSigning::AdjustClockSkew(outcome, authSchemeOption, m_authSchemes); } + IdentityOutcome ResolveIdentity(const AwsSmithyClientAsyncRequestContext& ctx) const override { + // TODO: return identity as outcome + AWS_UNREFERENCED_PARAM(ctx); + return AWSError{CoreErrors::UNKNOWN, "NotImplemented", "method not implemented", false}; + } + + RefreshBuiltInOutcome RefreshBuiltinParameters(const AwsSmithyClientAsyncRequestContext& ctx) const override { + //TODO: template specialization when ServiceClientConfigurationT doesnt have account id + //TODO: use identity in context to get account id + AWS_UNREFERENCED_PARAM(ctx); + return AWSError{CoreErrors::UNKNOWN, "NotImplemented", "method not implemented", false}; + }; + ResponseT MakeRequestDeserialize(Aws::AmazonWebServiceRequest const * const request, const char* requestName, Aws::Http::HttpMethod method, diff --git a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h index 7492aed3d18..6cf9ecd559d 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientAsyncRequestContext.h @@ -70,6 +70,7 @@ namespace smithy ResponseHandlerFunc m_responseHandler; std::shared_ptr m_pExecutor; std::shared_ptr m_interceptorContext; + std::shared_ptr m_awsIdentity; }; } // namespace client } // namespace smithy diff --git a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientBase.h b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientBase.h index f6e6e436e70..2e38b1b8951 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientBase.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyClientBase.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,8 @@ namespace client using SelectAuthSchemeOptionOutcome = Aws::Utils::Outcome; using ResolveEndpointOutcome = Aws::Utils::Outcome; using StreamOutcome = Aws::Utils::Outcome, AWSError >; + using IdentityOutcome = Aws::Utils::Outcome, AWSError>; + using RefreshBuiltInOutcome = Aws::Utils::Outcome; AwsSmithyClientBase(Aws::UniquePtr&& clientConfig, Aws::String serviceName, @@ -188,8 +191,10 @@ namespace client virtual ResolveEndpointOutcome ResolveEndpoint(const Aws::Endpoint::EndpointParameters& endpointParameters, EndpointUpdateCallback&& epCallback) const = 0; virtual SelectAuthSchemeOptionOutcome SelectAuthSchemeOption(const AwsSmithyClientAsyncRequestContext& ctx) const = 0; - virtual SigningOutcome SignHttpRequest(std::shared_ptr httpRequest, const AuthSchemeOption& targetAuthSchemeOption) const = 0; + virtual SigningOutcome SignHttpRequest(std::shared_ptr httpRequest, const AwsSmithyClientAsyncRequestContext& ctx) const = 0; virtual bool AdjustClockSkew(HttpResponseOutcome& outcome, const AuthSchemeOption& authSchemeOption) const = 0; + virtual IdentityOutcome ResolveIdentity(const AwsSmithyClientAsyncRequestContext& ctx) const = 0; + virtual RefreshBuiltInOutcome RefreshBuiltinParameters(const AwsSmithyClientAsyncRequestContext& ctx) const = 0; std::shared_ptr m_clientConfig; Aws::String m_serviceName; diff --git a/src/aws-cpp-sdk-core/include/smithy/client/common/AwsSmithyRequestSigning.h b/src/aws-cpp-sdk-core/include/smithy/client/common/AwsSmithyRequestSigning.h index 1ccb1f80a46..6e7d5b342f2 100644 --- a/src/aws-cpp-sdk-core/include/smithy/client/common/AwsSmithyRequestSigning.h +++ b/src/aws-cpp-sdk-core/include/smithy/client/common/AwsSmithyRequestSigning.h @@ -39,11 +39,11 @@ namespace smithy using SigningOutcome = Aws::Utils::FutureOutcome, SigningError>; using HttpResponseOutcome = Aws::Utils::Outcome, Aws::Client::AWSError>; - static SigningOutcome SignRequest(std::shared_ptr HTTPRequest, const AuthSchemeOption& authSchemeOption, - const Aws::UnorderedMap& authSchemes) + static SigningOutcome SignRequest(std::shared_ptr HTTPRequest, + const client::AwsSmithyClientAsyncRequestContext& ctx, + const Aws::UnorderedMap& authSchemes) { - - auto authSchemeIt = authSchemes.find(authSchemeOption.schemeId); + auto authSchemeIt = authSchemes.find(ctx.m_authSchemeOption.schemeId); if (authSchemeIt == authSchemes.end()) { assert(!"Auth scheme has not been found for a given auth option!"); @@ -55,7 +55,7 @@ namespace smithy const AuthSchemesVariantT& authScheme = authSchemeIt->second; - return SignWithAuthScheme(std::move(HTTPRequest), authScheme, authSchemeOption); + return SignWithAuthScheme(std::move(HTTPRequest), authScheme, ctx); } static SigningOutcome PreSignRequest(std::shared_ptr httpRequest, const AuthSchemeOption& authSchemeOption, @@ -115,13 +115,13 @@ namespace smithy protected: struct SignerVisitor { - SignerVisitor(std::shared_ptr httpRequest, const AuthSchemeOption& targetAuthSchemeOption) - : m_httpRequest(std::move(httpRequest)), m_targetAuthSchemeOption(targetAuthSchemeOption) + SignerVisitor(std::shared_ptr httpRequest, const client::AwsSmithyClientAsyncRequestContext& ctx) + : m_httpRequest(std::move(httpRequest)), m_requestContext(ctx) { } const std::shared_ptr m_httpRequest; - const AuthSchemeOption& m_targetAuthSchemeOption; + const client::AwsSmithyClientAsyncRequestContext& m_requestContext; Aws::Crt::Optional result; @@ -129,7 +129,7 @@ namespace smithy void operator()(AuthSchemeAlternativeT& authScheme) { // Auth Scheme Variant alternative contains the requested auth option - assert(strcmp(authScheme.schemeId, m_targetAuthSchemeOption.schemeId) == 0); + assert(strcmp(authScheme.schemeId, m_requestContext.m_authSchemeOption.schemeId) == 0); using IdentityT = typename std::remove_reference::type::IdentityT; using IdentityResolver = IdentityResolverBase; @@ -157,15 +157,6 @@ namespace smithy } } - auto identityResult = identityResolver->getIdentity(m_targetAuthSchemeOption.identityProperties(), additionalIdentityProperties); - - if (!identityResult.IsSuccess()) - { - result.emplace(identityResult.GetError()); - return; - } - auto identity = std::move(identityResult.GetResultWithOwnership()); - std::shared_ptr signer = authScheme.signer(); if (!signer) { @@ -176,7 +167,9 @@ namespace smithy return; } - result.emplace(signer->sign(m_httpRequest, *identity, m_targetAuthSchemeOption.signerProperties())); + result.emplace(signer->sign(m_httpRequest, + *static_cast(m_requestContext.m_awsIdentity.get()), + m_requestContext.m_authSchemeOption.signerProperties())); } }; @@ -237,10 +230,11 @@ namespace smithy }; static - SigningOutcome SignWithAuthScheme(std::shared_ptr httpRequest, const AuthSchemesVariantT& authSchemesVariant, - const AuthSchemeOption& targetAuthSchemeOption) + SigningOutcome SignWithAuthScheme(std::shared_ptr httpRequest, + const AuthSchemesVariantT& authSchemesVariant, + const client::AwsSmithyClientAsyncRequestContext& ctx) { - SignerVisitor visitor(httpRequest, targetAuthSchemeOption); + SignerVisitor visitor(httpRequest, ctx); AuthSchemesVariantT authSchemesVariantCopy(authSchemesVariant); // TODO: allow const visiting authSchemesVariantCopy.Visit(visitor); diff --git a/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp b/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp index 4bdee754245..e8be15ce02b 100644 --- a/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp +++ b/src/aws-cpp-sdk-core/source/smithy/client/AwsSmithyClientBase.cpp @@ -198,6 +198,30 @@ void AwsSmithyClientBase::MakeRequestAsync(Aws::AmazonWebServiceRequest const* c } pRequestCtx->m_authSchemeOption = std::move(authSchemeOptionOutcome.GetResultWithOwnership()); assert(pRequestCtx->m_authSchemeOption.schemeId); + + // resolve identity + auto identityOutcome = this->ResolveIdentity(*pRequestCtx); + if (!identityOutcome.IsSuccess()) + { + pExecutor->Submit([identityOutcome, responseHandler]() mutable + { + responseHandler(std::move(identityOutcome)); + }); + return; + } + pRequestCtx->m_awsIdentity = std::move(identityOutcome.GetResultWithOwnership()); + + // refresh built-in endpoint params with the request context + const auto refreshBuiltInsOutcome = this->RefreshBuiltinParameters(*pRequestCtx); + if (!refreshBuiltInsOutcome.IsSuccess()) + { + pExecutor->Submit([refreshBuiltInsOutcome, responseHandler]() mutable + { + responseHandler(std::move(refreshBuiltInsOutcome.GetError())); + }); + return; + } + Aws::Endpoint::EndpointParameters epParams = request ? request->GetEndpointContextParams() : Aws::Endpoint::EndpointParameters(); const auto authSchemeEpParams = pRequestCtx->m_authSchemeOption.endpointParameters(); epParams.insert(epParams.end(), authSchemeEpParams.begin(), authSchemeEpParams.end()); @@ -323,7 +347,7 @@ void AwsSmithyClientBase::AttemptOneRequestAsync(std::shared_ptr([&]() -> SigningOutcome { - return this->SignHttpRequest(pRequestCtx->m_httpRequest, pRequestCtx->m_authSchemeOption); + return this->SignHttpRequest(pRequestCtx->m_httpRequest, *pRequestCtx); }, TracingUtils::SMITHY_CLIENT_SIGNING_METRIC, *m_clientConfig->telemetryProvider->getMeter(this->GetServiceClientName(), {}), diff --git a/tests/aws-cpp-sdk-core-tests/smithy/client/SmithyClientTest.cpp b/tests/aws-cpp-sdk-core-tests/smithy/client/SmithyClientTest.cpp index 555b429b432..48252919b15 100644 --- a/tests/aws-cpp-sdk-core-tests/smithy/client/SmithyClientTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/smithy/client/SmithyClientTest.cpp @@ -200,9 +200,9 @@ class TestClient : public MySmithyClient return MySmithyClient::SelectAuthSchemeOption(ctx); } - SigningOutcome SignRequest(std::shared_ptr httpRequest, const smithy::AuthSchemeOption& targetAuthSchemeOption) const + SigningOutcome SignRequest(std::shared_ptr httpRequest, const smithy::client::AwsSmithyClientAsyncRequestContext& ctx) const { - return MySmithyClient::SignHttpRequest(httpRequest, targetAuthSchemeOption); + return MySmithyClient::SignHttpRequest(httpRequest, ctx); } @@ -239,15 +239,15 @@ TEST_F(SmithyClientTest, testSigV4) { ctx.m_pRequest = nullptr; auto res = ptr->SelectAuthSchemeOption(ctx); - EXPECT_EQ(res.IsSuccess(), true); EXPECT_EQ(res.GetResult().schemeId, key); + ctx.m_authSchemeOption = res.GetResultWithOwnership(); Aws::String uri{"https://treasureisland-cb93079d-24a0-4862-8es2-88456ead.xyz.amazonaws.com"}; std::shared_ptr httpRequest(Aws::Http::CreateHttpRequest(uri, Aws::Http::HttpMethod::HTTP_GET, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); - auto res2 = ptr->SignRequest(httpRequest, res.GetResult()); + auto res2 = ptr->SignRequest(httpRequest, ctx); EXPECT_EQ(res2.IsSuccess(), true); EXPECT_EQ(res2.GetResult()->GetSigningAccessKey(), "dummyAccessId"); @@ -287,15 +287,15 @@ TEST_F(SmithyClientTest, testSigV4a) { ctx.m_pRequest = nullptr; auto res = ptr->SelectAuthSchemeOption(ctx); - EXPECT_EQ(res.IsSuccess(), true); EXPECT_EQ(res.GetResult().schemeId, key); + ctx.m_authSchemeOption = res.GetResultWithOwnership(); Aws::String uri{"https://treasureisland-cb93079d-24a0-4862-8es2-88456ead.xyz.amazonaws.com"}; std::shared_ptr httpRequest(Aws::Http::CreateHttpRequest(uri, Aws::Http::HttpMethod::HTTP_GET, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); - auto res2 = ptr->SignRequest(httpRequest, res.GetResult()); + auto res2 = ptr->SignRequest(httpRequest, ctx); EXPECT_EQ(res2.IsSuccess(), true); @@ -333,9 +333,9 @@ TEST_F(SmithyClientTest, bearer) ctx.m_pRequest = nullptr; auto res = ptr->SelectAuthSchemeOption(ctx); - EXPECT_EQ(res.IsSuccess(), true); EXPECT_EQ(res.GetResult().schemeId, key); + ctx.m_authSchemeOption = res.GetResultWithOwnership(); Aws::String uri{ "https://" @@ -346,7 +346,7 @@ TEST_F(SmithyClientTest, bearer) uri, Aws::Http::HttpMethod::HTTP_GET, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod)); - auto res2 = ptr->SignRequest(httpRequest, res.GetResult()); + auto res2 = ptr->SignRequest(httpRequest, ctx); EXPECT_EQ(res2.IsSuccess(), true);