From 2999ddca5459b65561e0689badf35dda98521073 Mon Sep 17 00:00:00 2001 From: Peter Song Date: Sun, 13 Apr 2025 11:27:18 -0700 Subject: [PATCH] Allow source_profile and sso properties to be used together. Assume Role will take precedence over SSO --- .../b24980c4-b6f6-4181-9789-fda85df054a3.json | 9 ++++ .../Internal/CredentialProfileTypeDetector.cs | 41 +++++++++++++++---- .../Credentials/AWSCredentialsFactoryTest.cs | 2 +- 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 generator/.DevConfigs/b24980c4-b6f6-4181-9789-fda85df054a3.json diff --git a/generator/.DevConfigs/b24980c4-b6f6-4181-9789-fda85df054a3.json b/generator/.DevConfigs/b24980c4-b6f6-4181-9789-fda85df054a3.json new file mode 100644 index 000000000000..0a04653809dc --- /dev/null +++ b/generator/.DevConfigs/b24980c4-b6f6-4181-9789-fda85df054a3.json @@ -0,0 +1,9 @@ +{ + "core": { + "changeLogMessages": [ + "[Breaking Change] Allow source_profile to be used in conjunction with sso_session. If the profile specified via source_profile has sso_session, and the sso_session section is correctly configured, credentials will be retrieved from sso. The sso credentials will then be used to assume the role specified in the original profile. Previous behavior was that it assumed the role specified in source_profile, which does not follow the assume role profile chaining pattern." + ], + "type": "patch", + "updateMinimum": true + } + } \ No newline at end of file diff --git a/sdk/src/Core/Amazon.Runtime/CredentialManagement/Internal/CredentialProfileTypeDetector.cs b/sdk/src/Core/Amazon.Runtime/CredentialManagement/Internal/CredentialProfileTypeDetector.cs index 70563f01e048..791730e2bca4 100644 --- a/sdk/src/Core/Amazon.Runtime/CredentialManagement/Internal/CredentialProfileTypeDetector.cs +++ b/sdk/src/Core/Amazon.Runtime/CredentialManagement/Internal/CredentialProfileTypeDetector.cs @@ -101,43 +101,62 @@ public static class CredentialProfileTypeDetector { new HashSet { RoleArn, SourceProfile }, new HashSet { RoleArn, SourceProfile, AwsAccountId }, + new HashSet { RoleArn, SourceProfile, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, + new HashSet { RoleArn, SourceProfile, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.AssumeRoleCredentialSource, new List>() { new HashSet { RoleArn, CredentialSource }, - new HashSet { RoleArn, CredentialSource, AwsAccountId } + new HashSet { RoleArn, CredentialSource, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, + new HashSet { RoleArn, CredentialSource, AwsAccountId }, + new HashSet { RoleArn, CredentialSource, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl } } }, { CredentialProfileType.AssumeRoleExternal, new List>() { new HashSet { ExternalID, RoleArn, SourceProfile }, + new HashSet { ExternalID, RoleArn, SourceProfile, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { ExternalID, RoleArn, SourceProfile, AwsAccountId }, + new HashSet { ExternalID, RoleArn, SourceProfile, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl} + } + }, + { + CredentialProfileType.AssumeRoleExternalMFA, new List>() + { + new HashSet { ExternalID, RoleArn, SourceProfile, MfaSerial }, + new HashSet { ExternalID, RoleArn, SourceProfile, MfaSerial, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl } } }, - { CredentialProfileType.AssumeRoleExternalMFA, new List>() { new HashSet { ExternalID, RoleArn, SourceProfile, MfaSerial } } }, { CredentialProfileType.AssumeRoleWithWebIdentity, new List>() { new HashSet { RoleArn, WebIdentityTokenFile }, + new HashSet { RoleArn, WebIdentityTokenFile, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { RoleArn, WebIdentityTokenFile, CredentialSource }, + new HashSet { RoleArn, WebIdentityTokenFile, CredentialSource, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { RoleArn, WebIdentityTokenFile, CredentialSource, AwsAccountId }, + new HashSet { RoleArn, WebIdentityTokenFile, CredentialSource, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.AssumeRoleWithWebIdentitySessionName, new List>() { new HashSet { RoleArn, WebIdentityTokenFile, RoleSessionName }, - new HashSet { RoleArn, WebIdentityTokenFile, RoleSessionName, AwsAccountId } , + new HashSet { RoleArn, WebIdentityTokenFile, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, + new HashSet { RoleArn, WebIdentityTokenFile, RoleSessionName, AwsAccountId }, + new HashSet { RoleArn, WebIdentityTokenFile, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl } , } }, { CredentialProfileType.AssumeRoleMFA, new List>() { new HashSet { MfaSerial, RoleArn, SourceProfile }, + new HashSet { MfaSerial, RoleArn, SourceProfile, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { MfaSerial, RoleArn, SourceProfile, AwsAccountId }, + new HashSet { MfaSerial, RoleArn, SourceProfile, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.Basic, new List>() @@ -165,28 +184,36 @@ public static class CredentialProfileTypeDetector CredentialProfileType.AssumeRoleSessionName, new List>() { new HashSet { RoleArn, SourceProfile, RoleSessionName }, + new HashSet { RoleArn, SourceProfile, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl}, new HashSet { RoleArn, SourceProfile, RoleSessionName, AwsAccountId }, + new HashSet { RoleArn, SourceProfile, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.AssumeRoleCredentialSourceSessionName, new List>() { new HashSet { RoleArn, CredentialSource, RoleSessionName }, + new HashSet { RoleArn, CredentialSource, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { RoleArn, CredentialSource, RoleSessionName, AwsAccountId}, + new HashSet { RoleArn, CredentialSource, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.AssumeRoleExternalSessionName, new List>() { new HashSet { ExternalID, RoleArn, SourceProfile, RoleSessionName }, + new HashSet { ExternalID, RoleArn, SourceProfile, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { ExternalID, RoleArn, SourceProfile, RoleSessionName, AwsAccountId }, + new HashSet { ExternalID, RoleArn, SourceProfile, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.AssumeRoleExternalMFASessionName, new List>() { new HashSet { ExternalID, MfaSerial, RoleArn, SourceProfile, RoleSessionName }, + new HashSet { ExternalID, MfaSerial, RoleArn, SourceProfile, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { ExternalID, MfaSerial, RoleArn, SourceProfile, RoleSessionName, AwsAccountId }, + new HashSet { ExternalID, MfaSerial, RoleArn, SourceProfile, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, } }, { CredentialProfileType.SSO, new List>() { new HashSet { SsoAccountId, SsoRegion, SsoRegistrationScopes, SsoRoleName, SsoStartUrl, SsoSession } } }, @@ -194,7 +221,9 @@ public static class CredentialProfileTypeDetector CredentialProfileType.AssumeRoleMFASessionName, new List>() { new HashSet { MfaSerial, RoleArn, SourceProfile, RoleSessionName }, + new HashSet { MfaSerial, RoleArn, SourceProfile, RoleSessionName, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl }, new HashSet { MfaSerial, RoleArn, SourceProfile, RoleSessionName, AwsAccountId }, + new HashSet { MfaSerial, RoleArn, SourceProfile, RoleSessionName, AwsAccountId, SsoSession, SsoRegion, SsoRegistrationScopes, SsoStartUrl } } }, }; @@ -238,11 +267,9 @@ public static string GetUserFriendlyCredentialType(CredentialProfileType? profil HashSet propertyNames = GetPropertyNames(profileOptions); - // Spec: If one or more of the SSO properties is present, the profile MUST be resolved by the SSO credential provider. - if (propertyNames.Any(propertyName => SsoProperties.Contains(propertyName))) - { + //SPEC: if sso_account_id or sso_role_name exist credentials MUST be resolved by the sso credential provider. + if (propertyNames.Contains(SsoAccountId) || propertyNames.Contains(SsoRoleName)) return CredentialProfileType.SSO; - } // brute force algorithm - but it's a very small set foreach (var pair in TypePropertyDictionary) diff --git a/sdk/test/UnitTests/Custom/Runtime/Credentials/AWSCredentialsFactoryTest.cs b/sdk/test/UnitTests/Custom/Runtime/Credentials/AWSCredentialsFactoryTest.cs index 123197c56ef0..b4a8094c1a52 100644 --- a/sdk/test/UnitTests/Custom/Runtime/Credentials/AWSCredentialsFactoryTest.cs +++ b/sdk/test/UnitTests/Custom/Runtime/Credentials/AWSCredentialsFactoryTest.cs @@ -493,7 +493,7 @@ public void GetSsoCredentialsWithMissingFields() AssertExtensions.ExpectException(() => AWSCredentialsFactory.GetAWSCredentials(SsoProfileMissingFields, ProfileStore), - typeof(ArgumentNullException)); + typeof(InvalidDataException)); } [TestMethod]