From 3b7905564266958ed54cf2028297bf6d347f3ae6 Mon Sep 17 00:00:00 2001 From: sbiscigl Date: Tue, 29 Jul 2025 09:08:49 -0400 Subject: [PATCH] update to use regionalized STS credentials client --- .../source/DynamoDBClientConfiguration.cpp | 6 ++ .../aws/core/auth/STSCredentialsProvider.h | 1 + .../aws/core/client/ClientConfiguration.h | 8 ++- .../auth/AWSCredentialsProviderChain.cpp | 2 +- .../source/auth/STSCredentialsProvider.cpp | 37 ++++++------ .../source/client/ClientConfiguration.cpp | 60 ++++++++++++------- .../ServiceClientConfigurationSource.vm | 9 +++ 7 files changed, 78 insertions(+), 45 deletions(-) diff --git a/generated/src/aws-cpp-sdk-dynamodb/source/DynamoDBClientConfiguration.cpp b/generated/src/aws-cpp-sdk-dynamodb/source/DynamoDBClientConfiguration.cpp index 709bcc0fe68..b8e1fada6cd 100644 --- a/generated/src/aws-cpp-sdk-dynamodb/source/DynamoDBClientConfiguration.cpp +++ b/generated/src/aws-cpp-sdk-dynamodb/source/DynamoDBClientConfiguration.cpp @@ -45,6 +45,12 @@ void DynamoDBClientConfiguration::LoadDynamoDBSpecificConfig(const Aws::String& if(!enableEndpointDiscovery) { enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, inputProfileName); } + this->configFactories.retryStrategyCreateFn = []() -> std::shared_ptr { + // TODO: renable once default retries are evaluated + // Align with other SDKs to default retry to 10 times for dynamodb. + // return Client::InitRetryStrategy(10); + return Client::InitRetryStrategy(); + }; } DynamoDBClientConfiguration::DynamoDBClientConfiguration(const Client::ClientConfigurationInitValues &configuration) diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/STSCredentialsProvider.h b/src/aws-cpp-sdk-core/include/aws/core/auth/STSCredentialsProvider.h index 720006592c9..fbac3009b05 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/STSCredentialsProvider.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/STSCredentialsProvider.h @@ -26,6 +26,7 @@ namespace Aws { public: STSAssumeRoleWebIdentityCredentialsProvider(); + STSAssumeRoleWebIdentityCredentialsProvider(Aws::Client::ClientConfiguration::CredentialProviderConfiguration config); /** * Retrieves the credentials if found, otherwise returns empty credential set. diff --git a/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h b/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h index f128cdebecd..bfe39f2b42b 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h +++ b/src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h @@ -492,6 +492,11 @@ namespace Aws * AWS profile name to use for credentials. */ Aws::String profile; + + /** + * Region to use for calls + */ + Aws::String region; }credentialProviderConfig; }; @@ -499,7 +504,8 @@ namespace Aws * A helper function to initialize a retry strategy. * Default is DefaultRetryStrategy (i.e. exponential backoff) */ - std::shared_ptr InitRetryStrategy(Aws::String retryMode = ""); + AWS_CORE_API std::shared_ptr InitRetryStrategy(Aws::String retryMode = ""); + AWS_CORE_API std::shared_ptr InitRetryStrategy(int maxRetries, Aws::String retryMode = ""); /** * A helper function to compute a user agent diff --git a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp index 2a48c063705..45407e6d947 100644 --- a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp +++ b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp @@ -90,7 +90,7 @@ DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain(const Aws AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag)); AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag,config.profile.c_str())); AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag,config.profile)); - AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag)); + AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag, config)); AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag,config.profile)); // General HTTP Credentials (prev. known as ECS TaskRole credentials) only available when ENVIRONMENT VARIABLE is set diff --git a/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp b/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp index 65e61fc8675..187c5defc5f 100644 --- a/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp +++ b/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp @@ -32,24 +32,18 @@ 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 * 60 * 1000; // 5 Minutes. -STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentialsProvider() : +STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentialsProvider(Aws::Client::ClientConfiguration::CredentialProviderConfiguration credentialsConfig): m_initialized(false) { - // check environment variables - Aws::String tmpRegion = Aws::Environment::GetEnv("AWS_DEFAULT_REGION"); m_roleArn = Aws::Environment::GetEnv("AWS_ROLE_ARN"); m_tokenFile = Aws::Environment::GetEnv("AWS_WEB_IDENTITY_TOKEN_FILE"); m_sessionName = Aws::Environment::GetEnv("AWS_ROLE_SESSION_NAME"); // check profile_config if either m_roleArn or m_tokenFile is not loaded from environment variable // region source is not enforced, but we need it to construct sts endpoint, if we can't find from environment, we should check if it's set in config file. - if (m_roleArn.empty() || m_tokenFile.empty() || tmpRegion.empty()) + if (m_roleArn.empty() || m_tokenFile.empty()) { - auto profile = Aws::Config::GetCachedConfigProfile(Aws::Auth::GetConfigProfileName()); - if (tmpRegion.empty()) - { - tmpRegion = profile.GetRegion(); - } + auto profile = Aws::Config::GetCachedConfigProfile(credentialsConfig.profile); // If either of these two were not found from environment, use whatever found for all three in config file if (m_roleArn.empty() || m_tokenFile.empty()) { @@ -79,15 +73,6 @@ STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentials AWS_LOGSTREAM_DEBUG(STS_ASSUME_ROLE_WEB_IDENTITY_LOG_TAG, "Resolved role_arn from profile_config or environment variable to be " << m_roleArn); } - if (tmpRegion.empty()) - { - tmpRegion = Aws::Region::US_EAST_1; - } - else - { - AWS_LOGSTREAM_DEBUG(STS_ASSUME_ROLE_WEB_IDENTITY_LOG_TAG, "Resolved region from profile_config or environment variable to be " << tmpRegion); - } - if (m_sessionName.empty()) { m_sessionName = Aws::Utils::UUID::PseudoRandomUUID(); @@ -99,8 +84,7 @@ STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentials Aws::Client::ClientConfiguration config; config.scheme = Aws::Http::Scheme::HTTPS; - config.region = tmpRegion; - + config.region = credentialsConfig.region; Aws::Vector retryableErrors; retryableErrors.push_back("IDPCommunicationError"); retryableErrors.push_back("InvalidIdentityToken"); @@ -112,6 +96,19 @@ STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentials AWS_LOGSTREAM_INFO(STS_ASSUME_ROLE_WEB_IDENTITY_LOG_TAG, "Creating STS AssumeRole with web identity creds provider."); } +Aws::String LegacyGetRegion() { + auto region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION"); + if (region.empty()) { + auto profile = Aws::Config::GetCachedConfigProfile(Aws::Auth::GetConfigProfileName()); + region = profile.GetRegion(); + } + return region; +} + +STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentialsProvider() + : STSAssumeRoleWebIdentityCredentialsProvider( + Aws::Client::ClientConfiguration::CredentialProviderConfiguration{Aws::Auth::GetConfigProfileName(), LegacyGetRegion()}) {} + AWSCredentials STSAssumeRoleWebIdentityCredentialsProvider::GetAWSCredentials() { // A valid client means required information like role arn and token file were constructed correctly. diff --git a/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp b/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp index 9808aa1a818..b3d78b249f6 100644 --- a/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp +++ b/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp @@ -238,6 +238,7 @@ void setLegacyClientConfigurationParameters(ClientConfiguration& clientConfig) AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << clientConfig.profileName << "] if not specified by users."); clientConfig.region = calculateRegion(); + clientConfig.credentialProviderConfig.region = clientConfig.region; // Set the endpoint to interact with EC2 instance's metadata service Aws::String ec2MetadataServiceEndpoint = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT"); @@ -305,6 +306,7 @@ ClientConfiguration::ClientConfiguration() if (client) { region = client->GetCurrentRegion(); + this->credentialProviderConfig.region = region; } } if (!region.empty()) @@ -312,6 +314,7 @@ ClientConfiguration::ClientConfiguration() return; } region = Aws::String(Aws::Region::US_EAST_1); + this->credentialProviderConfig.region = region; } ClientConfiguration::ClientConfiguration(const ClientConfigurationInitValues &configuration) @@ -329,6 +332,7 @@ ClientConfiguration::ClientConfiguration(const ClientConfigurationInitValues &co if (client) { region = client->GetCurrentRegion(); + this->credentialProviderConfig.region = region; } } if (!region.empty()) @@ -336,6 +340,7 @@ ClientConfiguration::ClientConfiguration(const ClientConfigurationInitValues &co return; } region = Aws::String(Aws::Region::US_EAST_1); + this->credentialProviderConfig.region = region; } ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisableIMDS) @@ -359,12 +364,14 @@ ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisable ec2MetadataRegion = client->GetCurrentRegion(); hasEc2MetadataRegion = true; region = ec2MetadataRegion; + this->credentialProviderConfig.region = region; } } if(region.empty()) { region = Aws::String(Aws::Region::US_EAST_1); + this->credentialProviderConfig.region = region; } if (profile && Aws::Config::HasCachedConfigProfile(profile)) { @@ -373,6 +380,7 @@ ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisable auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion(); if (!tmpRegion.empty()) { region = tmpRegion; + this->credentialProviderConfig.region = region; } Aws::String profileDefaultsMode = Aws::Config::GetCachedConfigProfile(this->profileName).GetDefaultsMode(); @@ -404,39 +412,19 @@ ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char* ec2MetadataRegion = client->GetCurrentRegion(); hasEc2MetadataRegion = true; region = ec2MetadataRegion; + this->credentialProviderConfig.region = region; } } if (region.empty()) { region = Aws::String(Aws::Region::US_EAST_1); + this->credentialProviderConfig.region = region; } Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion); } -std::shared_ptr InitRetryStrategy(Aws::String retryMode) -{ - int maxAttempts = 0; - Aws::String maxAttemptsString = Aws::Environment::GetEnv("AWS_MAX_ATTEMPTS"); - if (maxAttemptsString.empty()) - { - maxAttemptsString = Aws::Config::GetCachedConfigValue("max_attempts"); - } - // In case users specify 0 explicitly to disable retry. - if (maxAttemptsString == "0") - { - maxAttempts = 0; - } - else - { - maxAttempts = static_cast(Aws::Utils::StringUtils::ConvertToInt32(maxAttemptsString.c_str())); - if (maxAttempts == 0) - { - AWS_LOGSTREAM_INFO(CLIENT_CONFIG_TAG, "Retry Strategy will use the default max attempts."); - maxAttempts = -1; - } - } - +std::shared_ptr InitRetryStrategy(int maxAttempts, Aws::String retryMode) { if (retryMode.empty()) { retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE"); @@ -479,6 +467,32 @@ std::shared_ptr InitRetryStrategy(Aws::String retryMode) return retryStrategy; } +std::shared_ptr InitRetryStrategy(Aws::String retryMode) +{ + int maxAttempts = 0; + Aws::String maxAttemptsString = Aws::Environment::GetEnv("AWS_MAX_ATTEMPTS"); + if (maxAttemptsString.empty()) + { + maxAttemptsString = Aws::Config::GetCachedConfigValue("max_attempts"); + } + // In case users specify 0 explicitly to disable retry. + if (maxAttemptsString == "0") + { + maxAttempts = 0; + } + else + { + maxAttempts = static_cast(Aws::Utils::StringUtils::ConvertToInt32(maxAttemptsString.c_str())); + if (maxAttempts == 0) + { + AWS_LOGSTREAM_INFO(CLIENT_CONFIG_TAG, "Retry Strategy will use the default max attempts."); + maxAttempts = -1; + } + } + + return InitRetryStrategy(maxAttempts, retryMode); +} + Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey, const Aws::String& profile, const Aws::String& profileProperty, diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/common/ServiceClientConfigurationSource.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/common/ServiceClientConfigurationSource.vm index 6f94e2e2202..007b5900fc9 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/common/ServiceClientConfigurationSource.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/common/ServiceClientConfigurationSource.vm @@ -123,6 +123,15 @@ void ${metadata.classNamePrefix}ClientConfiguration::Load${serviceNamespace}Spec enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, inputProfileName); } #end +## DyanmoDB historically requires 10 retries for backwards compatibility +#if($serviceModel.metadata.serviceId == "DynamoDB") + this->configFactories.retryStrategyCreateFn = []() -> std::shared_ptr { + // TODO: renable once default retries are evaluated + // Align with other SDKs to default retry to 10 times for dynamodb. + // return Client::InitRetryStrategy(10); + return Client::InitRetryStrategy(); + }; +#end } ${metadata.classNamePrefix}ClientConfiguration::${metadata.classNamePrefix}ClientConfiguration(const Client::ClientConfigurationInitValues &configuration)