Skip to content

Commit f25e5b5

Browse files
committed
Removed STS assume role in sts provider.
added to clientconfiguration so we know where the token is coming from (env/profile)
1 parent cc89d9e commit f25e5b5

File tree

5 files changed

+137
-42
lines changed

5 files changed

+137
-42
lines changed

src/aws-cpp-sdk-core/include/aws/core/client/ClientConfiguration.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,12 +441,37 @@ namespace Aws
441441
ResponseChecksumValidation responseChecksumValidation = ResponseChecksumValidation::WHEN_SUPPORTED;
442442
} checksumConfig;
443443

444+
/**
445+
* Configuration source types for tracking where values come from
446+
*/
447+
enum class ConfigSourceType {
448+
ENVIRONMENT,
449+
PROFILE,
450+
DEFAULT_VALUE
451+
};
452+
453+
/**
454+
* Structure to hold both config value and its source
455+
*/
456+
struct ConfigSource {
457+
Aws::String value;
458+
ConfigSourceType source;
459+
ConfigSource(const Aws::String& val, ConfigSourceType src) : value(val), source(src) {}
460+
};
461+
444462
/**
445463
* A helper function to read config value from env variable or aws profile config
446464
*/
447465
static Aws::String LoadConfigFromEnvOrProfile(const Aws::String& envKey, const Aws::String& profile,
448466
const Aws::String& profileProperty, const Aws::Vector<Aws::String>& allowedValues,
449467
const Aws::String& defaultValue);
468+
469+
/**
470+
* A helper function to read config value and track its source
471+
*/
472+
static ConfigSource LoadConfigFromEnvOrProfileWithSource(const Aws::String& envKey, const Aws::String& profile,
473+
const Aws::String& profileProperty, const Aws::Vector<Aws::String>& allowedValues,
474+
const Aws::String& defaultValue);
450475

451476
/**
452477
* A wrapper for interfacing with telemetry functionality. Defaults to Noop provider.
@@ -539,6 +564,11 @@ namespace Aws
539564
* The OAuth 2.0 access token or OpenID Connect ID token
540565
*/
541566
Aws::String tokenFilePath;
567+
568+
/**
569+
* Credential source type for user agent tracking
570+
*/
571+
Aws::String credentialSource;
542572

543573
/**
544574
* Time out for the credentials future call.

src/aws-cpp-sdk-core/include/aws/core/client/UserAgent.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ enum class UserAgentFeature {
3333
RESOLVED_ACCOUNT_ID,
3434
GZIP_REQUEST_COMPRESSION,
3535
CREDENTIALS_ENV_VARS,
36+
CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN,
3637
CREDENTIALS_PROFILE,
3738
CREDENTIALS_PROFILE_PROCESS,
3839
CREDENTIALS_IMDS,
3940
CREDENTIALS_STS_ASSUME_ROLE,
41+
CREDENTIALS_STS_WEB_IDENTITY_TOKEN,
4042
CREDENTIALS_HTTP,
4143
};
4244

src/aws-cpp-sdk-core/source/auth/STSCredentialsProvider.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,6 @@ AWSCredentials STSAssumeRoleWebIdentityCredentialsProvider::GetAWSCredentials()
105105
std::unique_lock<std::mutex> lock{m_refreshMutex};
106106
m_refreshSignal.wait_for(lock, m_providerFuturesTimeoutMs, [&refreshDone]() -> bool { return refreshDone; });
107107

108-
if (!credentials.IsEmpty()) {
109-
credentials.AddUserAgentFeature(Aws::Client::UserAgentFeature::CREDENTIALS_STS_ASSUME_ROLE);
110-
}
111-
112108
return credentials;
113109
}
114110

src/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp

Lines changed: 96 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ static T LoadEnumFromString(const std::array<std::pair<const char*, T>, N>& mapp
7373
return mapping->second;
7474
}
7575

76+
// Helper to load raw values without lowercasing (for file paths, ARNs, etc.)
77+
static Aws::String LoadRawFromEnvOrProfile(const Aws::String& envKey,
78+
const Aws::String& profile,
79+
const Aws::String& profileProperty,
80+
const Aws::String& defaultValue) {
81+
Aws::String option = Aws::Environment::GetEnv(envKey.c_str());
82+
if (option.empty()) {
83+
option = Aws::Config::GetCachedConfigValue(profile, profileProperty);
84+
}
85+
return option.empty() ? defaultValue : Aws::Utils::StringUtils::Trim(option.c_str());
86+
}
87+
7688
ClientConfiguration::ProviderFactories ClientConfiguration::ProviderFactories::defaultFactories = []()
7789
{
7890
ProviderFactories factories;
@@ -327,23 +339,25 @@ void setConfigFromEnvOrProfile(ClientConfiguration &config)
327339
// Uses default retry mode with the specified max attempts from metadata_service_num_attempts
328340
config.credentialProviderConfig.imdsConfig.imdsRetryStrategy = InitRetryStrategy(attempts, "");
329341

330-
config.credentialProviderConfig.stsCredentialsProviderConfig.roleArn = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_IAM_ROLE_ARN_ENV_VAR,
331-
config.profileName,
332-
AWS_IAM_ROLE_ARN_CONFIG_FILE_OPTION,
333-
{}, /* allowed values */
334-
"" /* default value */);
335-
336-
config.credentialProviderConfig.stsCredentialsProviderConfig.sessionName = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_IAM_ROLE_SESSION_NAME_ENV_VAR,
337-
config.profileName,
338-
AWS_IAM_ROLE_SESSION_NAME_CONFIG_FILE_OPTION,
339-
{}, /* allowed values */
340-
"" /* default value */);
341-
342-
config.credentialProviderConfig.stsCredentialsProviderConfig.tokenFilePath = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_WEB_IDENTITY_TOKEN_FILE_ENV_VAR,
343-
config.profileName,
344-
AWS_WEB_IDENTITY_TOKEN_FILE_CONFIG_FILE_OPTION,
345-
{}, /* allowed values */
346-
"" /* default value */);
342+
auto roleArnSrc = ClientConfiguration::LoadConfigFromEnvOrProfileWithSource(
343+
AWS_IAM_ROLE_ARN_ENV_VAR, config.profileName, AWS_IAM_ROLE_ARN_CONFIG_FILE_OPTION, {}, "");
344+
config.credentialProviderConfig.stsCredentialsProviderConfig.roleArn = roleArnSrc.value;
345+
346+
config.credentialProviderConfig.stsCredentialsProviderConfig.sessionName = LoadRawFromEnvOrProfile(
347+
AWS_IAM_ROLE_SESSION_NAME_ENV_VAR, config.profileName, AWS_IAM_ROLE_SESSION_NAME_CONFIG_FILE_OPTION, "");
348+
349+
auto tokenFileSrc = ClientConfiguration::LoadConfigFromEnvOrProfileWithSource(
350+
AWS_WEB_IDENTITY_TOKEN_FILE_ENV_VAR, config.profileName, AWS_WEB_IDENTITY_TOKEN_FILE_CONFIG_FILE_OPTION, {}, "");
351+
config.credentialProviderConfig.stsCredentialsProviderConfig.tokenFilePath = tokenFileSrc.value;
352+
353+
if (!roleArnSrc.value.empty() && !tokenFileSrc.value.empty()) {
354+
using Src = ClientConfiguration::ConfigSourceType;
355+
const bool fromEnv = (roleArnSrc.source == Src::ENVIRONMENT) || (tokenFileSrc.source == Src::ENVIRONMENT);
356+
config.credentialProviderConfig.stsCredentialsProviderConfig.credentialSource =
357+
fromEnv ? "env_web_identity" : "web_identity";
358+
} else {
359+
config.credentialProviderConfig.stsCredentialsProviderConfig.credentialSource.clear();
360+
}
347361
}
348362

349363
ClientConfiguration::ClientConfiguration()
@@ -552,35 +566,79 @@ std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode)
552566
return InitRetryStrategy(maxAttempts, retryMode);
553567
}
554568

555-
Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey,
556-
const Aws::String& profile,
557-
const Aws::String& profileProperty,
558-
const Aws::Vector<Aws::String>& allowedValues,
559-
const Aws::String& defaultValue)
569+
ClientConfiguration::ConfigSource ClientConfiguration::LoadConfigFromEnvOrProfileWithSource(const Aws::String& envKey,
570+
const Aws::String& profile,
571+
const Aws::String& profileProperty,
572+
const Aws::Vector<Aws::String>& allowedValues,
573+
const Aws::String& defaultValue)
560574
{
561-
Aws::String option = Aws::Environment::GetEnv(envKey.c_str());
562-
if (option.empty()) {
575+
Aws::String option;
576+
ConfigSourceType sourceType = ConfigSourceType::DEFAULT_VALUE;
577+
578+
if (!envKey.empty()) {
579+
option = Aws::Environment::GetEnv(envKey.c_str());
580+
if (!option.empty()) {
581+
sourceType = ConfigSourceType::ENVIRONMENT;
582+
}
583+
}
584+
585+
if (option.empty() && !profileProperty.empty()) {
563586
option = Aws::Config::GetCachedConfigValue(profile, profileProperty);
587+
if (!option.empty()) {
588+
sourceType = ConfigSourceType::PROFILE;
589+
}
564590
}
565-
option = Aws::Utils::StringUtils::ToLower(option.c_str());
591+
592+
option = Aws::Utils::StringUtils::Trim(option.c_str());
593+
566594
if (option.empty()) {
567-
return defaultValue;
595+
return ConfigSource(defaultValue, ConfigSourceType::DEFAULT_VALUE);
568596
}
569597

570-
if (!allowedValues.empty() && std::find(allowedValues.cbegin(), allowedValues.cend(), option) == allowedValues.cend()) {
571-
Aws::OStringStream expectedStr;
572-
expectedStr << "[";
573-
for(const auto& allowed : allowedValues) {
574-
expectedStr << allowed << ";";
598+
// Validate only if we have an allowed list (enum-like). Do NOT mutate case of the returned value.
599+
if (!allowedValues.empty()) {
600+
const Aws::String optionLower = Aws::Utils::StringUtils::ToLower(option.c_str());
601+
602+
// Build a lowercased view of the allowed set once
603+
bool allowed = std::any_of(allowedValues.cbegin(), allowedValues.cend(),
604+
[&](const Aws::String& v){ return optionLower == Aws::Utils::StringUtils::ToLower(v.c_str()); });
605+
606+
if (!allowed) {
607+
Aws::OStringStream expectedStr;
608+
expectedStr << "[";
609+
for (size_t i = 0; i < allowedValues.size(); ++i) {
610+
expectedStr << allowedValues[i];
611+
if ( i + 1 < allowedValues.size() ) expectedStr << ";";
612+
}
613+
expectedStr << "]";
614+
615+
const char* src = (sourceType == ConfigSourceType::ENVIRONMENT) ? "environment" :
616+
(sourceType == ConfigSourceType::PROFILE) ? "profile" : "default";
617+
618+
AWS_LOGSTREAM_WARN(
619+
CLIENT_CONFIG_TAG,
620+
"Unrecognized value from " << src
621+
<< (sourceType == ConfigSourceType::ENVIRONMENT ? (Aws::String(" (") + envKey + ")") :
622+
sourceType == ConfigSourceType::PROFILE ? (Aws::String(" (") + profile + ":" + profileProperty + ")") : "")
623+
<< ": \"" << option << "\". Using default: \"" << defaultValue
624+
<< "\". Expected one of: " << expectedStr.str()
625+
);
626+
627+
return ConfigSource(defaultValue, ConfigSourceType::DEFAULT_VALUE);
575628
}
576-
expectedStr << "]";
577-
578-
AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "Unrecognised value for " << envKey << ": " << option <<
579-
". Using default instead: " << defaultValue <<
580-
". Expected empty or one of: " << expectedStr.str());
581-
option = defaultValue;
582629
}
583-
return option;
630+
631+
// Return original (un-lowercased) token and the actual source
632+
return ConfigSource(option, sourceType);
633+
}
634+
635+
Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey,
636+
const Aws::String& profile,
637+
const Aws::String& profileProperty,
638+
const Aws::Vector<Aws::String>& allowedValues,
639+
const Aws::String& defaultValue)
640+
{
641+
return LoadConfigFromEnvOrProfileWithSource(envKey, profile, profileProperty, allowedValues, defaultValue).value;
584642
}
585643

586644
} // namespace Client

src/aws-cpp-sdk-core/source/client/UserAgent.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ const std::pair<UserAgentFeature, const char*> BUSINESS_METRIC_MAPPING[] = {
4343
{UserAgentFeature::RESOLVED_ACCOUNT_ID, "T"},
4444
{UserAgentFeature::GZIP_REQUEST_COMPRESSION, "L"},
4545
{UserAgentFeature::CREDENTIALS_ENV_VARS, "g"},
46+
{UserAgentFeature::CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN, "h"},
4647
{UserAgentFeature::CREDENTIALS_PROFILE, "n"},
4748
{UserAgentFeature::CREDENTIALS_PROFILE_PROCESS, "v"},
4849
{UserAgentFeature::CREDENTIALS_IMDS, "0"},
4950
{UserAgentFeature::CREDENTIALS_STS_ASSUME_ROLE, "i"},
51+
{UserAgentFeature::CREDENTIALS_STS_WEB_IDENTITY_TOKEN, "q"},
5052
{UserAgentFeature::CREDENTIALS_HTTP, "z"},
5153
};
5254

@@ -129,6 +131,13 @@ UserAgent::UserAgent(const ClientConfiguration& clientConfiguration,
129131
if (accountIdMode.has_value()) {
130132
m_features.emplace(accountIdMode.value());
131133
}
134+
135+
const auto& sts = clientConfiguration.credentialProviderConfig.stsCredentialsProviderConfig;
136+
if (sts.credentialSource == "env_web_identity") {
137+
m_features.emplace(UserAgentFeature::CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN);
138+
} else if (sts.credentialSource == "web_identity") {
139+
m_features.emplace(UserAgentFeature::CREDENTIALS_STS_WEB_IDENTITY_TOKEN);
140+
}
132141
}
133142

134143
Aws::String UserAgent::SerializeWithFeatures(const Aws::Set<UserAgentFeature>& features) const {

0 commit comments

Comments
 (0)