Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws/session: Enable SSO provider to be mixed with other credential providers #3905

Merged
merged 2 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions aws/session/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
70 changes: 65 additions & 5 deletions aws/session/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -403,6 +441,28 @@ const assumeRoleRespMsg = `
</AssumeRoleResponse>
`

var assumeRoleWithWebIdentityResponse = `<AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleWithWebIdentityResult>
<SubjectFromWebIdentityToken>amzn1.account.AF6RHO7KZU5XRVQJGXK6HB56KR2A</SubjectFromWebIdentityToken>
<Audience>client.5498841531868486423.1548@apps.example.com</Audience>
<AssumedRoleUser>
<Arn>arn:aws:sts::123456789012:assumed-role/FederatedWebIdentityRole/app1</Arn>
<AssumedRoleId>AROACLKWSDQRAOEXAMPLE:app1</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>WEB_IDENTITY_AKID</AccessKeyId>
<SecretAccessKey>WEB_IDENTITY_SECRET</SecretAccessKey>
<SessionToken>WEB_IDENTITY_SESSION_TOKEN</SessionToken>
<Expiration>%s</Expiration>
</Credentials>
<Provider>www.amazon.com</Provider>
</AssumeRoleWithWebIdentityResult>
<ResponseMetadata>
<RequestId>request-id</RequestId>
</ResponseMetadata>
</AssumeRoleWithWebIdentityResponse>
`

const getRoleCredentialsResponse = `{
"roleCredentials": {
"accessKeyId": "SSO_AKID",
Expand Down
5 changes: 4 additions & 1 deletion aws/session/shared_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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() {
Expand Down
33 changes: 32 additions & 1 deletion aws/session/shared_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
},
}

Expand Down
14 changes: 14 additions & 0 deletions aws/session/testdata/credential_source_config
Original file line number Diff line number Diff line change
Expand Up @@ -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
17 changes: 16 additions & 1 deletion aws/session/testdata/credential_source_config_for_windows
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
7 changes: 7 additions & 0 deletions aws/session/testdata/shared_config
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions aws/session/testdata/wit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
YXdzIHNkayBmb3IgZ28gd2ViIGlkZW50aXR5IHRva2Vu