From 938f65347c619fe2851c1d315d959a6928f727b6 Mon Sep 17 00:00:00 2001 From: cai lin Date: Wed, 16 Jul 2025 17:28:20 +0000 Subject: [PATCH] new configuration support for IMDSConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ClientConfiguration support for IMDS settings and update related classes Fix: Shared pointer bug in AWSCredentialsProvider allocator mismatch bug fix, change type using c_str() new configuration support for IMDSConfig Add ClientConfiguration support for IMDS settings and update related classes Fix: Shared pointer bug in AWSCredentialsProvider allocator mismatch bug fix, change type using c_str() Fix shared pointer bug and update IMDS config structure - Fix std::stol compilation error with Aws::String by using .c_str() - Update IMDS configuration to use credentialProviderConfig.imdsConfig structure - Add proper environment variable support for AWS_METADATA_SERVICE_TIMEOUT and AWS_METADATA_SERVICE_NUM_ATTEMPTS Update IMDS configuration and credentials provider fix: Remove duplicate IMDS config struct and fix comment syntax feat: Add IMDS configuration support to credential provider chain - Add CredentialProviderConfiguration struct with IMDS timeout and retry settings - Add constructor to DefaultAWSCredentialsProviderChain accepting CredentialProviderConfiguration - Add constructor to InstanceProfileCredentialsProvider accepting CredentialProviderConfiguration - Add constructor to EC2InstanceProfileConfigLoader accepting CredentialProviderConfiguration - Add constructor to EC2MetadataClient accepting CredentialProviderConfiguration with IMDS timeout/retry configuration - Enable IMDS configuration to flow through: CredentialProviderConfiguration → InstanceProfileCredentialsProvider → EC2InstanceProfileConfigLoader → EC2MetadataClient - Reduce object creation redundancy by passing configuration directly through the chain fix disableImdsvV1 member added new include feat: Add IMDS configuration support for AWS_METADATA_SERVICE_TIMEOUT Add support for AWS_METADATA_SERVICE_TIMEOUT and AWS_METADATA_SERVICE_NUM_ATTEMPTS environment variables and config file settings to configure IMDS client behavior. - Add imdsConfig struct to ClientConfiguration.credentialProviderConfig - Support AWS_METADATA_SERVICE_TIMEOUT env var and metadata_service_timeout config - Support AWS_METADATA_SERVICE_NUM_ATTEMPTS env var and metadata_service_num_attempts config - Add InstanceProfileCredentialsProvider constructor accepting ClientConfiguration - Add EC2InstanceProfileConfigLoader constructor accepting CredentialProviderConfiguration - Update EC2MetadataClient to use configured timeout and retry values - Use StringUtils::ConvertToInt32 for parsing instead of std::stol Resolves customer request for configurable IMDS timeout settings. fixed snake case removed m_disableIMDSV1 and comment recreated retry strategy during client configuration updated forward declaration fixed nip New Max Attemp Retry Strategy updated conflicts updated conflicts nit DisableIMDSV1 --- .../aws/core/auth/AWSCredentialsProvider.h | 9 +++++ .../aws/core/client/ClientConfiguration.h | 22 ++++++++++++ .../config/EC2InstanceProfileConfigLoader.h | 7 +++- .../aws/core/internal/AWSHttpResourceClient.h | 1 + .../source/auth/AWSCredentialsProvider.cpp | 7 ++++ .../auth/AWSCredentialsProviderChain.cpp | 3 +- .../source/auth/STSCredentialsProvider.cpp | 2 +- .../source/client/ClientConfiguration.cpp | 35 +++++++++++++++++++ .../config/EC2InstanceProfileConfigLoader.cpp | 5 +++ .../source/internal/AWSHttpResourceClient.cpp | 22 ++++++++++++ 10 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentialsProvider.h b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentialsProvider.h index 32936785bdf..8222cdc3361 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentialsProvider.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentialsProvider.h @@ -22,6 +22,10 @@ namespace Aws { + namespace Client + { + struct ClientConfiguration; + } namespace Auth { constexpr int REFRESH_THRESHOLD = 1000 * 60 * 5; @@ -212,6 +216,11 @@ namespace Aws */ InstanceProfileCredentialsProvider(const std::shared_ptr&, long refreshRateMs = REFRESH_THRESHOLD); + /** + * Initializes the provider using ClientConfiguration for IMDS settings. + */ + InstanceProfileCredentialsProvider(const Aws::Client::ClientConfiguration::CredentialProviderConfiguration& credentialProviderConfig, long refreshRateMs = REFRESH_THRESHOLD); + /** * 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 bfe39f2b42b..4e9e34fd1a3 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 @@ -497,6 +497,28 @@ namespace Aws * Region to use for calls */ Aws::String region; + + /** + * IMDS configuration settings + */ + struct { + /** + * Number of total attempts to make when retrieving data from IMDS. Default 1. + */ + long metadataServiceNumAttempts = 1; + + /** + * Timeout in seconds when retrieving data from IMDS. Default 1. + */ + long metadataServiceTimeout = 1; + + /** + * Retry Strategy for IMDS + */ + std::shared_ptr imdsRetryStrategy; + bool disableImdsV1; + bool disableImds; + } imdsConfig; }credentialProviderConfig; }; diff --git a/src/aws-cpp-sdk-core/include/aws/core/config/EC2InstanceProfileConfigLoader.h b/src/aws-cpp-sdk-core/include/aws/core/config/EC2InstanceProfileConfigLoader.h index ae3a743fc3f..4c1e23259bc 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/config/EC2InstanceProfileConfigLoader.h +++ b/src/aws-cpp-sdk-core/include/aws/core/config/EC2InstanceProfileConfigLoader.h @@ -6,7 +6,7 @@ #pragma once #include - +#include #include #include #include @@ -34,6 +34,11 @@ namespace Aws */ EC2InstanceProfileConfigLoader(const std::shared_ptr& = nullptr); + /** + * Creates EC2MetadataClient using the provided CredentialProviderConfiguration. + */ + EC2InstanceProfileConfigLoader(const Aws::Client::ClientConfiguration::CredentialProviderConfiguration& credentialConfig); + virtual ~EC2InstanceProfileConfigLoader() = default; protected: diff --git a/src/aws-cpp-sdk-core/include/aws/core/internal/AWSHttpResourceClient.h b/src/aws-cpp-sdk-core/include/aws/core/internal/AWSHttpResourceClient.h index e30204ef1ce..b65d3c5bf52 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/internal/AWSHttpResourceClient.h +++ b/src/aws-cpp-sdk-core/include/aws/core/internal/AWSHttpResourceClient.h @@ -103,6 +103,7 @@ namespace Aws */ EC2MetadataClient(const char* endpoint = "http://169.254.169.254"); EC2MetadataClient(const Client::ClientConfiguration& clientConfiguration, const char* endpoint = "http://169.254.169.254"); + EC2MetadataClient(const Client::ClientConfiguration::CredentialProviderConfiguration& credentialConfig, const char* endpoint = "http://169.254.169.254"); EC2MetadataClient& operator =(const EC2MetadataClient& rhs) = delete; EC2MetadataClient(const EC2MetadataClient& rhs) = delete; diff --git a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp index 69fc27e4514..451944931c1 100644 --- a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp +++ b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProvider.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -242,6 +243,12 @@ InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(const std AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with injected EC2MetadataClient and refresh rate " << refreshRateMs); } +InstanceProfileCredentialsProvider::InstanceProfileCredentialsProvider(const Aws::Client::ClientConfiguration::CredentialProviderConfiguration& credentialConfig, long refreshRateMs) : + m_ec2MetadataConfigLoader(Aws::MakeShared(INSTANCE_LOG_TAG, credentialConfig)), + m_loadFrequencyMs(refreshRateMs) +{ + AWS_LOGSTREAM_INFO(INSTANCE_LOG_TAG, "Creating Instance with IMDS timeout: " << credentialConfig.imdsConfig.metadataServiceTimeout << "s, attempts: " << credentialConfig.imdsConfig.metadataServiceNumAttempts); +} AWSCredentials InstanceProfileCredentialsProvider::GetAWSCredentials() { diff --git a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp index 45407e6d947..55f8a9a5efc 100644 --- a/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp +++ b/src/aws-cpp-sdk-core/source/auth/AWSCredentialsProviderChain.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -125,7 +126,7 @@ DefaultAWSCredentialsProviderChain::DefaultAWSCredentialsProviderChain(const Aws } else if (Aws::Utils::StringUtils::ToLower(ec2MetadataDisabled.c_str()) != "true") { - AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag)); + AddProvider(Aws::MakeShared(DefaultCredentialsProviderChainTag, config)); AWS_LOGSTREAM_INFO(DefaultCredentialsProviderChainTag, "Added EC2 metadata service credentials provider to the provider chain."); } } diff --git a/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp b/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp index 187c5defc5f..15a6931bcff 100644 --- a/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp +++ b/src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp @@ -107,7 +107,7 @@ Aws::String LegacyGetRegion() { STSAssumeRoleWebIdentityCredentialsProvider::STSAssumeRoleWebIdentityCredentialsProvider() : STSAssumeRoleWebIdentityCredentialsProvider( - Aws::Client::ClientConfiguration::CredentialProviderConfiguration{Aws::Auth::GetConfigProfileName(), LegacyGetRegion()}) {} + Aws::Client::ClientConfiguration::CredentialProviderConfiguration{Aws::Auth::GetConfigProfileName(), LegacyGetRegion(), {}}) {} AWSCredentials STSAssumeRoleWebIdentityCredentialsProvider::GetAWSCredentials() { diff --git a/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp b/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp index b3d78b249f6..d08d981deda 100644 --- a/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp +++ b/src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp @@ -41,6 +41,10 @@ static const char* DISABLE_IMDSV1_CONFIG_VAR = "AWS_EC2_METADATA_V1_DISABLED"; static const char* DISABLE_IMDSV1_ENV_VAR = "ec2_metadata_v1_disabled"; static const char* AWS_ACCOUNT_ID_ENDPOINT_MODE_ENVIRONMENT_VARIABLE = "AWS_ACCOUNT_ID_ENDPOINT_MODE"; static const char* AWS_ACCOUNT_ID_ENDPOINT_MODE_CONFIG_FILE_OPTION = "account_id_endpoint_mode"; +static const char* AWS_METADATA_SERVICE_TIMEOUT_ENV_VAR = "AWS_METADATA_SERVICE_TIMEOUT"; +static const char* AWS_METADATA_SERVICE_TIMEOUT_CONFIG_VAR = "metadata_service_timeout"; +static const char* AWS_METADATA_SERVICE_NUM_ATTEMPTS_ENV_VAR = "AWS_METADATA_SERVICE_NUM_ATTEMPTS"; +static const char* AWS_METADATA_SERVICE_NUM_ATTEMPTS_CONFIG_VAR = "metadata_service_num_attempts"; using RequestChecksumConfigurationEnumMapping = std::pair; static const std::array REQUEST_CHECKSUM_CONFIG_MAPPING = {{ @@ -280,6 +284,7 @@ void setConfigFromEnvOrProfile(ClientConfiguration &config) "false"); if (disableIMDSv1 == "true") { config.disableImdsV1 = true; + config.credentialProviderConfig.imdsConfig.disableImdsV1 = true; } // accountId is intentionally not set here: AWS_ACCOUNT_ID env variable may not match the provided credentials. @@ -289,11 +294,38 @@ void setConfigFromEnvOrProfile(ClientConfiguration &config) AWS_ACCOUNT_ID_ENDPOINT_MODE_CONFIG_FILE_OPTION, {"required", "disabled", "preferred"}, /* allowed values */ "preferred" /* default value */); + + // Load IMDS configuration from environment variables and config file + Aws::String timeoutStr = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_METADATA_SERVICE_TIMEOUT_ENV_VAR, + config.profileName, + AWS_METADATA_SERVICE_TIMEOUT_CONFIG_VAR, + {}, /* allowed values */ + "1" /* default value */); + + // Load IMDS configuration from environment variables and config file + Aws::String numAttemptsStr = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_METADATA_SERVICE_NUM_ATTEMPTS_ENV_VAR, + config.profileName, + AWS_METADATA_SERVICE_NUM_ATTEMPTS_CONFIG_VAR, + {}, /* allowed values */ + "1" /* default value */); + + // Parse and set IMDS timeout + long timeout = static_cast(Aws::Utils::StringUtils::ConvertToInt32(timeoutStr.c_str())); + config.credentialProviderConfig.imdsConfig.metadataServiceTimeout = timeout; + + // Parse and set IMDS num attempts + long attempts = static_cast(Aws::Utils::StringUtils::ConvertToInt32(numAttemptsStr.c_str())); + config.credentialProviderConfig.imdsConfig.metadataServiceNumAttempts = attempts; + + // Initialize IMDS-specific retry strategy with configured number of attempts + // Uses default retry mode with the specified max attempts from metadata_service_num_attempts + config.credentialProviderConfig.imdsConfig.imdsRetryStrategy = InitRetryStrategy(attempts, ""); } ClientConfiguration::ClientConfiguration() { this->disableIMDS = false; + this->credentialProviderConfig.imdsConfig.disableImds = false; setLegacyClientConfigurationParameters(*this); setConfigFromEnvOrProfile(*this); this->credentialProviderConfig.profile = this->profileName; @@ -320,6 +352,7 @@ ClientConfiguration::ClientConfiguration() ClientConfiguration::ClientConfiguration(const ClientConfigurationInitValues &configuration) { this->disableIMDS = configuration.shouldDisableIMDS; + this->credentialProviderConfig.imdsConfig.disableImds = configuration.shouldDisableIMDS; setLegacyClientConfigurationParameters(*this); setConfigFromEnvOrProfile(*this); this->credentialProviderConfig.profile = this->profileName; @@ -346,6 +379,7 @@ ClientConfiguration::ClientConfiguration(const ClientConfigurationInitValues &co ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisableIMDS) { this->disableIMDS = shouldDisableIMDS; + this->credentialProviderConfig.imdsConfig.disableImds = shouldDisableIMDS; if (profile && Aws::Config::HasCachedConfigProfile(profile)) { this->profileName = Aws::String(profile); } @@ -395,6 +429,7 @@ ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisable ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char* defaultMode, bool shouldDisableIMDS) { this->disableIMDS = shouldDisableIMDS; + this->credentialProviderConfig.imdsConfig.disableImds = shouldDisableIMDS; setLegacyClientConfigurationParameters(*this); setConfigFromEnvOrProfile(*this); this->credentialProviderConfig.profile = this->profileName; diff --git a/src/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp b/src/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp index 883d45cc695..1d7528fc34d 100644 --- a/src/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp +++ b/src/aws-cpp-sdk-core/source/config/EC2InstanceProfileConfigLoader.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,10 @@ namespace Aws m_ec2metadataClient = client; } } + + EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const Aws::Client::ClientConfiguration::CredentialProviderConfiguration& credentialConfig) + : m_ec2metadataClient(Aws::MakeShared(EC2_INSTANCE_PROFILE_LOG_TAG, credentialConfig)) + {} bool EC2InstanceProfileConfigLoader::LoadInternal() { diff --git a/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp b/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp index b4ed4fedd31..e9fed4f2fd6 100644 --- a/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp +++ b/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp @@ -208,6 +208,28 @@ namespace Aws #endif } + EC2MetadataClient::EC2MetadataClient(const Aws::Client::ClientConfiguration::CredentialProviderConfiguration& credentialConfig, + const char* endpoint) + : AWSHttpResourceClient( + [&credentialConfig]() -> ClientConfiguration{ + Aws::Client::ClientConfiguration clientConfig{credentialConfig.profile.c_str()}; + clientConfig.region = credentialConfig.region; + clientConfig.credentialProviderConfig = credentialConfig; + clientConfig.requestTimeoutMs = credentialConfig.imdsConfig.metadataServiceTimeout * 1000; + clientConfig.retryStrategy = credentialConfig.imdsConfig.imdsRetryStrategy; + return clientConfig; + }(), + EC2_METADATA_CLIENT_LOG_TAG), + m_endpoint(endpoint), + m_disableIMDS(credentialConfig.imdsConfig.disableImds), + m_tokenRequired(true), + m_disableIMDSV1(credentialConfig.imdsConfig.disableImdsV1) { +#if defined(DISABLE_IMDSV1) + m_disableIMDSV1 = true; + AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "IMDSv1 had been disabled at the SDK build time"); +#endif + } + EC2MetadataClient::~EC2MetadataClient() {