1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-23 01:11:07 +01:00

fix(libstore/aws-creds): add STS support for default profile

The default (empty) profile case was using CreateCredentialsProviderChainDefault
which didn't properly support role_arn/source_profile based role assumption via
STS because TLS context wasn't being passed to the Profile provider.

This change unifies the credential chain for all profiles (default and named),
ensuring:
- Consistent behavior between default and named profiles
- Proper TLS context is passed for STS operations
- SSO support works for both cases
This commit is contained in:
Bernardo Meurer 2025-11-25 17:34:16 -05:00 committed by Jörg Thalheim
parent 3c8e45c061
commit 508d4463e5

View file

@ -142,6 +142,12 @@ public:
warn("failed to create TLS context for AWS SSO; SSO authentication will be unavailable"); warn("failed to create TLS context for AWS SSO; SSO authentication will be unavailable");
tlsContext = nullptr; tlsContext = nullptr;
} }
// Get bootstrap (lives as long as apiHandle)
bootstrap = Aws::Crt::ApiHandle::GetOrCreateStaticDefaultClientBootstrap();
if (!bootstrap) {
throw AwsAuthError("failed to create AWS client bootstrap");
}
} }
AwsCredentials getCredentialsRaw(const std::string & profile); AwsCredentials getCredentialsRaw(const std::string & profile);
@ -163,6 +169,7 @@ public:
private: private:
Aws::Crt::ApiHandle apiHandle; Aws::Crt::ApiHandle apiHandle;
std::shared_ptr<Aws::Crt::Io::TlsContext> tlsContext; std::shared_ptr<Aws::Crt::Io::TlsContext> tlsContext;
Aws::Crt::Io::ClientBootstrap * bootstrap;
boost::concurrent_flat_map<std::string, std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider>> boost::concurrent_flat_map<std::string, std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider>>
credentialProviderCache; credentialProviderCache;
}; };
@ -170,35 +177,24 @@ private:
std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider>
AwsCredentialProviderImpl::createProviderForProfile(const std::string & profile) AwsCredentialProviderImpl::createProviderForProfile(const std::string & profile)
{ {
debug( // profileDisplayName is only used for debug logging - SDK uses its default profile
"[pid=%d] creating new AWS credential provider for profile '%s'", // when ProfileNameOverride is not set
getpid(), const char * profileDisplayName = profile.empty() ? "(default)" : profile.c_str();
profile.empty() ? "(default)" : profile.c_str());
auto bootstrap = Aws::Crt::ApiHandle::GetOrCreateStaticDefaultClientBootstrap(); debug("[pid=%d] creating new AWS credential provider for profile '%s'", getpid(), profileDisplayName);
if (!bootstrap) {
throw AwsAuthError("failed to create AWS client bootstrap");
}
// If no profile specified, use the default chain // Build a custom credential chain: Environment → SSO → Profile → IMDS
if (profile.empty()) { // This works for both default and named profiles, ensuring consistent behavior
Aws::Crt::Auth::CredentialsProviderChainDefaultConfig config; // including SSO support and proper TLS context for STS-based role assumption.
config.Bootstrap = bootstrap;
return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(config);
}
// For named profiles, build a custom credential chain: Environment → SSO → Profile → IMDS
// The SSO provider will gracefully fail if SSO isn't configured for this profile,
// and the chain will move on to the next provider.
Aws::Crt::Auth::CredentialsProviderChainConfig chainConfig; Aws::Crt::Auth::CredentialsProviderChainConfig chainConfig;
auto allocator = Aws::Crt::ApiAllocator(); auto allocator = Aws::Crt::ApiAllocator();
auto addProviderToChain = [&](std::string_view name, auto createProvider) { auto addProviderToChain = [&](std::string_view name, auto createProvider) {
if (auto provider = createProvider()) { if (auto provider = createProvider()) {
chainConfig.Providers.push_back(provider); chainConfig.Providers.push_back(provider);
debug("Added AWS %s Credential Provider to chain for profile '%s'", name, profile); debug("Added AWS %s Credential Provider to chain for profile '%s'", name, profileDisplayName);
} else { } else {
debug("Skipped AWS %s Credential Provider for profile '%s'", name, profile); debug("Skipped AWS %s Credential Provider for profile '%s'", name, profileDisplayName);
} }
}; };
@ -211,14 +207,17 @@ AwsCredentialProviderImpl::createProviderForProfile(const std::string & profile)
if (tlsContext) { if (tlsContext) {
addProviderToChain("SSO", [&]() { return createSSOProvider(profile, bootstrap, tlsContext.get(), allocator); }); addProviderToChain("SSO", [&]() { return createSSOProvider(profile, bootstrap, tlsContext.get(), allocator); });
} else { } else {
debug("Skipped AWS SSO Credential Provider for profile '%s': TLS context unavailable", profile); debug("Skipped AWS SSO Credential Provider for profile '%s': TLS context unavailable", profileDisplayName);
} }
// 3. Profile provider (for static credentials) // 3. Profile provider (for static credentials and role_arn/source_profile with STS)
addProviderToChain("Profile", [&]() { addProviderToChain("Profile", [&]() {
Aws::Crt::Auth::CredentialsProviderProfileConfig profileConfig; Aws::Crt::Auth::CredentialsProviderProfileConfig profileConfig;
profileConfig.Bootstrap = bootstrap; profileConfig.Bootstrap = bootstrap;
profileConfig.ProfileNameOverride = Aws::Crt::ByteCursorFromCString(profile.c_str()); profileConfig.TlsContext = tlsContext.get();
if (!profile.empty()) {
profileConfig.ProfileNameOverride = Aws::Crt::ByteCursorFromCString(profile.c_str());
}
return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(profileConfig, allocator); return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(profileConfig, allocator);
}); });