From f01c77eade4d0305490b35cce2093215e1f1980d Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Tue, 11 May 2021 12:54:44 -0700 Subject: [PATCH] aws/session: Enable SSO provider to be mixed with other credential provider declarations. --- aws/session/credentials.go | 14 ++-- aws/session/credentials_test.go | 70 +++++++++++++++++-- aws/session/shared_config.go | 5 +- aws/session/shared_config_test.go | 33 ++++++++- aws/session/testdata/credential_source_config | 14 ++++ .../credential_source_config_for_windows | 17 ++++- aws/session/testdata/shared_config | 7 ++ aws/session/testdata/wit.txt | 1 + 8 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 aws/session/testdata/wit.txt diff --git a/aws/session/credentials.go b/aws/session/credentials.go index 3ddd4e51282..3efdac29ff4 100644 --- a/aws/session/credentials.go +++ b/aws/session/credentials.go @@ -101,13 +101,6 @@ func resolveCredsFromProfile(cfg *aws.Config, sharedCfg.Creds, ) - case sharedCfg.hasSSOConfiguration(): - creds, err = resolveSSOCredentials(cfg, sharedCfg, handlers) - - case len(sharedCfg.CredentialProcess) != 0: - // Get credentials from CredentialProcess - creds = processcreds.NewCredentials(sharedCfg.CredentialProcess) - case len(sharedCfg.CredentialSource) != 0: creds, err = resolveCredsFromSource(cfg, envCfg, sharedCfg, handlers, sessOpts, @@ -123,6 +116,13 @@ func resolveCredsFromProfile(cfg *aws.Config, sharedCfg.RoleSessionName, ) + case sharedCfg.hasSSOConfiguration(): + creds, err = resolveSSOCredentials(cfg, sharedCfg, handlers) + + case len(sharedCfg.CredentialProcess) != 0: + // Get credentials from CredentialProcess + creds = processcreds.NewCredentials(sharedCfg.CredentialProcess) + default: // Fallback to default credentials provider, include mock errors for // the credential chain so user can identify why credentials failed to diff --git a/aws/session/credentials_test.go b/aws/session/credentials_test.go index 2ff6e8f2552..145961a72c4 100644 --- a/aws/session/credentials_test.go +++ b/aws/session/credentials_test.go @@ -23,6 +23,7 @@ import ( "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/internal/sdktesting" "github.com/aws/aws-sdk-go/internal/shareddefaults" + "github.com/aws/aws-sdk-go/private/protocol" "github.com/aws/aws-sdk-go/service/sts" ) @@ -63,11 +64,31 @@ func setupCredentialsEndpoints(t *testing.T) (endpoints.Resolver, func()) { stsServer := httptest.NewServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(fmt.Sprintf( - assumeRoleRespMsg, - time.Now(). - Add(15*time.Minute). - Format("2006-01-02T15:04:05Z")))) + if err := r.ParseForm(); err != nil { + w.WriteHeader(500) + return + } + + form := r.Form + + switch form.Get("Action") { + case "AssumeRole": + w.Write([]byte(fmt.Sprintf( + assumeRoleRespMsg, + time.Now(). + Add(15*time.Minute). + Format(protocol.ISO8601TimeFormat)))) + return + case "AssumeRoleWithWebIdentity": + w.Write([]byte(fmt.Sprintf(assumeRoleWithWebIdentityResponse, + time.Now(). + Add(15*time.Minute). + Format(protocol.ISO8601TimeFormat)))) + return + default: + w.WriteHeader(404) + return + } })) ssoServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -275,6 +296,23 @@ func TestSharedConfigCredentialSource(t *testing.T) { return func() {}, nil }, }, + { + name: "sso mixed with credential process provider", + profile: "sso_mixed_credproc", + expectedAccessKey: "SSO_AKID", + expectedSecretKey: "SSO_SECRET_KEY", + expectedSessionToken: "SSO_SESSION_TOKEN", + init: func() (func(), error) { + return ssoTestSetup() + }, + }, + { + name: "sso mixed with web identity token provider", + profile: "sso_mixed_webident", + expectedAccessKey: "WEB_IDENTITY_AKID", + expectedSecretKey: "WEB_IDENTITY_SECRET", + expectedSessionToken: "WEB_IDENTITY_SESSION_TOKEN", + }, } for i, c := range cases { @@ -403,6 +441,28 @@ const assumeRoleRespMsg = ` ` +var assumeRoleWithWebIdentityResponse = ` + + amzn1.account.AF6RHO7KZU5XRVQJGXK6HB56KR2A + client.5498841531868486423.1548@apps.example.com + + arn:aws:sts::123456789012:assumed-role/FederatedWebIdentityRole/app1 + AROACLKWSDQRAOEXAMPLE:app1 + + + WEB_IDENTITY_AKID + WEB_IDENTITY_SECRET + WEB_IDENTITY_SESSION_TOKEN + %s + + www.amazon.com + + + request-id + + +` + const getRoleCredentialsResponse = `{ "roleCredentials": { "accessKeyId": "SSO_AKID", diff --git a/aws/session/shared_config.go b/aws/session/shared_config.go index c3f38b6ec07..42b16a7db9e 100644 --- a/aws/session/shared_config.go +++ b/aws/session/shared_config.go @@ -401,7 +401,6 @@ func (cfg *sharedConfig) validateCredentialType() error { len(cfg.CredentialSource) != 0, len(cfg.CredentialProcess) != 0, len(cfg.WebIdentityTokenFile) != 0, - cfg.hasSSOConfiguration(), ) { return ErrSharedConfigSourceCollision } @@ -459,6 +458,10 @@ func (cfg *sharedConfig) clearCredentialOptions() { cfg.CredentialProcess = "" cfg.WebIdentityTokenFile = "" cfg.Creds = credentials.Value{} + cfg.SSOAccountID = "" + cfg.SSORegion = "" + cfg.SSORoleName = "" + cfg.SSOStartURL = "" } func (cfg *sharedConfig) clearAssumeRoleOptions() { diff --git a/aws/session/shared_config_test.go b/aws/session/shared_config_test.go index 713c2238710..00bdfb0d0ba 100644 --- a/aws/session/shared_config_test.go +++ b/aws/session/shared_config_test.go @@ -261,7 +261,38 @@ func TestLoadSharedConfig(t *testing.T) { { Filenames: []string{testConfigFilename}, Profile: "source_sso_and_assume", - Err: fmt.Errorf("only one credential type may be specified per profile"), + Expected: sharedConfig{ + Profile: "source_sso_and_assume", + RoleARN: "source_sso_and_assume_arn", + SourceProfileName: "sso_and_assume", + SourceProfile: &sharedConfig{ + Profile: "sso_and_assume", + RoleARN: "sso_with_assume_role_arn", + SourceProfileName: "multiple_assume_role_with_credential_source", + SourceProfile: &sharedConfig{ + Profile: "multiple_assume_role_with_credential_source", + RoleARN: "multiple_assume_role_with_credential_source_role_arn", + SourceProfileName: "assume_role_with_credential_source", + SourceProfile: &sharedConfig{ + Profile: "assume_role_with_credential_source", + RoleARN: "assume_role_with_credential_source_role_arn", + CredentialSource: credSourceEc2Metadata, + }, + }, + }, + }, + }, + { + Filenames: []string{testConfigFilename}, + Profile: "sso_mixed_credproc", + Expected: sharedConfig{ + Profile: "sso_mixed_credproc", + SSOAccountID: "012345678901", + SSORegion: "us-west-2", + SSORoleName: "TestRole", + SSOStartURL: "https://127.0.0.1/start", + CredentialProcess: "/path/to/process", + }, }, } diff --git a/aws/session/testdata/credential_source_config b/aws/session/testdata/credential_source_config index 291a7d83f0a..f51bd72337c 100644 --- a/aws/session/testdata/credential_source_config +++ b/aws/session/testdata/credential_source_config @@ -57,3 +57,17 @@ sso_start_url = https://THIS_SHOULD_NOT_BE_IN_TESTDATA_CACHE/start sso_account_id = 012345678901 sso_role_name = TestRole +[profile sso_mixed_credproc] +sso_account_id = 012345678901 +sso_region = us-west-2 +sso_role_name = TestRole +sso_start_url = https://127.0.0.1/start +credential_process = cat ./testdata/test_json.json + +[profile sso_mixed_webident] +web_identity_token_file = ./testdata/wit.txt +role_arn = sso_mixed_webident_arn +sso_account_id = 012345678901 +sso_region = us-west-2 +sso_role_name = TestRole +sso_start_url = https://127.0.0.1/start diff --git a/aws/session/testdata/credential_source_config_for_windows b/aws/session/testdata/credential_source_config_for_windows index 34073afb516..a2f107166cd 100644 --- a/aws/session/testdata/credential_source_config_for_windows +++ b/aws/session/testdata/credential_source_config_for_windows @@ -7,4 +7,19 @@ credential_process = type .\testdata\test_json.json [chained_cred_proc] role_arn = assume_role_w_creds_proc_source_prof -source_profile = cred_proc_no_arn_set \ No newline at end of file +source_profile = cred_proc_no_arn_set + +[profile sso_mixed_credproc] +sso_account_id = 012345678901 +sso_region = us-west-2 +sso_role_name = TestRole +sso_start_url = https://127.0.0.1/start +credential_process = type .\testdata\test_json.json + +[profile sso_mixed_webident] +web_identity_token_file = .\testdata\wit.txt +role_arn = sso_mixed_webident_arn +sso_account_id = 012345678901 +sso_region = us-west-2 +sso_role_name = TestRole +sso_start_url = https://127.0.0.1/start diff --git a/aws/session/testdata/shared_config b/aws/session/testdata/shared_config index c19f349beb1..63148032bc6 100644 --- a/aws/session/testdata/shared_config +++ b/aws/session/testdata/shared_config @@ -140,3 +140,10 @@ source_profile = multiple_assume_role_with_credential_source [profile source_sso_and_assume] role_arn = source_sso_and_assume_arn source_profile = sso_and_assume + +[profile sso_mixed_credproc] +sso_account_id = 012345678901 +sso_region = us-west-2 +sso_role_name = TestRole +sso_start_url = https://127.0.0.1/start +credential_process = /path/to/process diff --git a/aws/session/testdata/wit.txt b/aws/session/testdata/wit.txt new file mode 100644 index 00000000000..809def20ec1 --- /dev/null +++ b/aws/session/testdata/wit.txt @@ -0,0 +1 @@ +YXdzIHNkayBmb3IgZ28gd2ViIGlkZW50aXR5IHRva2Vu