Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smithy reference architecture identity base APIs #2900

Merged
merged 2 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/aws-cpp-sdk-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ 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")

file(GLOB AWS_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
file(GLOB AWS_TINYXML2_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/external/tinyxml2/*.cpp")
Expand Down Expand Up @@ -106,6 +111,8 @@ 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")

include(CheckCSourceCompiles)
Expand Down Expand Up @@ -283,6 +290,8 @@ 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 @@ -323,7 +332,12 @@ 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 @@ -440,7 +454,11 @@ 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})

# http client conditional headers
if(ENABLE_CURL_CLIENT)
Expand Down Expand Up @@ -487,6 +505,8 @@ 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})

# http client conditional source
Expand Down Expand Up @@ -696,7 +716,12 @@ 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)

# android logcat headers
if(PLATFORM_ANDROID)
Expand Down
24 changes: 24 additions & 0 deletions src/aws-cpp-sdk-core/include/aws/core/utils/FutureOutcome.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/core/utils/Outcome.h>

namespace Aws
{
namespace Utils
{

/**
* Template class representing the std::future object of outcome of calling some other API.
* It will contain a future of an either a successful result or the failure error.
* The caller must check whether the outcome of the request was a success before attempting to access
* the result or the error.
*/
template<typename R, typename E> // Result, Error
using FutureOutcome = Aws::Utils::Outcome<R, E>;
} // namespace Utils
} // namespace Aws
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;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#pragma once

#include <smithy/identity/identity/AwsBearerTokenIdentityBase.h>

namespace smithy {
class AwsBearerTokenIdentity : public AwsBearerTokenIdentityBase {
public:
virtual Aws::String token() override;

virtual Aws::Crt::Optional<AwsIdentity::DateTime> expiration() override;

protected:
Aws::String m_token;
Aws::Crt::Optional<AwsIdentity::DateTime> m_expiration;
};
}

#include <smithy/identity/identity/impl/AwsBearerTokenIdentityImpl.h>
Loading
Loading