Skip to content

Commit

Permalink
Smithy Identity AuthOption and AuthScheme
Browse files Browse the repository at this point in the history
  • Loading branch information
SergeyRyabinin committed Jun 13, 2024
1 parent 30d6642 commit fbc2f92
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/aws-cpp-sdk-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down Expand Up @@ -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")

Expand Down Expand Up @@ -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}
)
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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})

Expand Down Expand Up @@ -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})

Expand Down Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <smithy/Smithy_EXPORTS.h>

#include <aws/core/endpoint/AWSEndpoint.h>
#include <aws/core/http/HttpRequest.h>
#include <aws/core/AmazonWebServiceRequest.h>

#include <aws/core/utils/DateTime.h>
#include <aws/core/utils/Outcome.h>


namespace smithy
{
class AwsClientAsyncRequestCtx
{
public:
using AwsCoreError = Aws::Client::AWSError<Aws::Client::CoreErrors>;
using HttpResponseOutcome = Aws::Utils::Outcome<std::shared_ptr<Aws::Http::HttpResponse>, 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<Aws::Http::HttpRequest> m_httpRequest;
Aws::Endpoint::AWSEndpoint m_endpoint;

Aws::Crt::Optional<AwsCoreError> m_lastError;

size_t m_retryCount;
Aws::Vector<void*> m_monitoringContexts;

std::function<void(HttpResponseOutcome)> m_responseHandler;
std::shared_ptr<Aws::Utils::Threading::Executor> m_pExecutor;
};
} // namespace smithy
126 changes: 126 additions & 0 deletions src/aws-cpp-sdk-core/include/smithy/client/AwsSmithyRequestSigning.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <smithy/identity/auth/AuthOption.h>
#include <smithy/identity/identity/AwsIdentity.h>
#include <smithy/identity/resolver/AwsIdentityResolverBase.h>
#include <smithy/identity/signer/AwsSignerBase.h>

#include <aws/core/utils/FutureOutcome.h>
#include <aws/core/client/AWSError.h>
#include <aws/core/http/HttpRequest.h>

#include <aws/crt/Variant.h>
#include <aws/crt/Optional.h>
#include <aws/core/utils/memory/stl/AWSMap.h>

#include <cassert>


namespace smithy
{
template <typename AuthSchemesVariantT>
class AwsClientRequestSigning
{
public:
using HttpRequest = Aws::Http::HttpRequest;
using SigningError = Aws::Client::AWSError<Aws::Client::CoreErrors>;
using SigningOutcome = Aws::Utils::FutureOutcome<Aws::Http::HttpRequest, SigningError>;

static SigningOutcome SignRequest(const HttpRequest& HTTPRequest, const AuthOption& authOption,
const Aws::UnorderedMap<Aws::String, AuthSchemesVariantT>& 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<SigningOutcome> result;

template <typename AuthSchemeAlternativeT>
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<IdentityT>;
using Signer = AwsSignerBase<IdentityT>;

std::shared_ptr<IdentityResolver> 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<IdentityResolverBase<IdentityT>, typename decltype(identityResolver
)::IdentityT>::value);
static_assert(std::is_base_of<IdentityResolverBase<IdentityT>, decltype(identityResolver)>::value);

IdentityT identity = identityResolver->getIdentity(m_targetAuthOption.identityProperties);

std::shared_ptr<Signer> 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<AwsSignerBase<IdentityT>, typename decltype(signer)::IdentityT>::value);
static_assert(std::is_base_of<AwsSignerBase<IdentityT>, 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);
}
};
}
24 changes: 24 additions & 0 deletions src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthOption.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <aws/crt/Variant.h>

#include <aws/core/utils/DateTime.h>
#include <aws/core/utils/memory/stl/AWSMap.h>

namespace smithy {
/* AuthOption and AuthOptionResolver */
class AuthOption
{
using PropertyBag = Aws::UnorderedMap<Aws::String, Aws::Crt::Variant<Aws::String, bool>>;
/* 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{};
};
}
25 changes: 25 additions & 0 deletions src/aws-cpp-sdk-core/include/smithy/identity/auth/AuthScheme.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <smithy/identity/resolver/AwsIdentityResolverBase.h>
#include <smithy/identity/signer/AwsSignerBase.h>

namespace smithy {
template<uint64_t SCHEME_ID_HASH, typename IDENTITY_T>
class AuthScheme
{
public:
using IdentityT = IDENTITY_T;

static const uint64_t schemeId;

virtual ~AuthScheme() = default;

virtual std::shared_ptr<IdentityResolverBase<IdentityT>> identityResolver() = 0;

virtual std::shared_ptr<AwsSignerBase<IdentityT>> signer() = 0;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <smithy/identity/auth/AuthOption.h>
#include <smithy/identity/signer/AwsSignerBase.h>

#include <aws/crt/Variant.h>
#include <aws/core/utils/memory/stl/AWSMap.h>

namespace smithy {
template<typename ServiceAuthSchemeParametersT = Aws::UnorderedMap<Aws::String, Aws::Crt::Variant<Aws::String, bool>>>
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<AuthOption> resolveAuthScheme(const ServiceAuthSchemeParameters& identityProperties) = 0;
};
}

0 comments on commit fbc2f92

Please sign in to comment.