Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit 4a3fa39

Browse files
authored
Fix: Only Validate SSO profile configuration when attempting to use SSO credentials. (#3769)
1 parent 3974dd0 commit 4a3fa39

6 files changed

Lines changed: 75 additions & 20 deletions

File tree

CHANGELOG_PENDING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
### SDK Enhancements
44

55
### SDK Bugs
6+
* `aws/session`: Fixed a bug that prevented credentials from being sourced from the environment if the loaded shared config profile contained partial SSO configuration. ([#3769](https://github.com/aws/aws-sdk-go/pull/3769))
7+
* Fixes ([#3768](https://github.com/aws/aws-sdk-go/issues/3768))

aws/session/credentials.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func resolveCredsFromProfile(cfg *aws.Config,
102102
)
103103

104104
case sharedCfg.hasSSOConfiguration():
105-
creds = resolveSSOCredentials(cfg, sharedCfg, handlers)
105+
creds, err = resolveSSOCredentials(cfg, sharedCfg, handlers)
106106

107107
case len(sharedCfg.CredentialProcess) != 0:
108108
// Get credentials from CredentialProcess
@@ -155,7 +155,11 @@ func resolveCredsFromProfile(cfg *aws.Config,
155155
return creds, nil
156156
}
157157

158-
func resolveSSOCredentials(cfg *aws.Config, sharedCfg sharedConfig, handlers request.Handlers) *credentials.Credentials {
158+
func resolveSSOCredentials(cfg *aws.Config, sharedCfg sharedConfig, handlers request.Handlers) (*credentials.Credentials, error) {
159+
if err := sharedCfg.validateSSOConfiguration(); err != nil {
160+
return nil, err
161+
}
162+
159163
cfgCopy := cfg.Copy()
160164
cfgCopy.Region = &sharedCfg.SSORegion
161165

@@ -167,7 +171,7 @@ func resolveSSOCredentials(cfg *aws.Config, sharedCfg sharedConfig, handlers req
167171
sharedCfg.SSOAccountID,
168172
sharedCfg.SSORoleName,
169173
sharedCfg.SSOStartURL,
170-
)
174+
), nil
171175
}
172176

173177
// valid credential source values

aws/session/credentials_test.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ func TestSharedConfigCredentialSource(t *testing.T) {
259259
"assume_sso_and_static_arn",
260260
},
261261
},
262+
{
263+
name: "invalid sso configuration",
264+
profile: "sso_invalid",
265+
expectedError: fmt.Errorf("profile \"sso_invalid\" is configured to use SSO but is missing required configuration: sso_region, sso_start_url"),
266+
},
267+
{
268+
name: "environment credentials with invalid sso",
269+
profile: "sso_invalid",
270+
expectedAccessKey: "access_key",
271+
expectedSecretKey: "secret_key",
272+
init: func() (func(), error) {
273+
os.Setenv("AWS_ACCESS_KEY", "access_key")
274+
os.Setenv("AWS_SECRET_KEY", "secret_key")
275+
return func() {}, nil
276+
},
277+
},
262278
}
263279

264280
for i, c := range cases {
@@ -308,8 +324,15 @@ func TestSharedConfigCredentialSource(t *testing.T) {
308324
Handlers: handlers,
309325
EC2IMDSEndpoint: c.sessOptEC2IMDSEndpoint,
310326
})
311-
if e, a := c.expectedError, err; e != a {
312-
t.Fatalf("expected %v, but received %v", e, a)
327+
328+
if c.expectedError != nil {
329+
var errStr string
330+
if err != nil {
331+
errStr = err.Error()
332+
}
333+
if e, a := c.expectedError.Error(), errStr; !strings.Contains(a, e) {
334+
t.Fatalf("expected %v, but received %v", e, a)
335+
}
313336
}
314337

315338
if c.expectedError != nil {

aws/session/shared_config.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ const (
7070

7171
// sharedConfig represents the configuration fields of the SDK config files.
7272
type sharedConfig struct {
73+
Profile string
74+
7375
// Credentials values from the config file. Both aws_access_key_id and
7476
// aws_secret_access_key must be provided together in the same file to be
7577
// considered valid. The values will be ignored if not a complete group.
@@ -201,6 +203,8 @@ func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
201203
}
202204

203205
func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile string, files []sharedConfigFile, exOpts bool) error {
206+
cfg.Profile = profile
207+
204208
// Trim files from the list that don't exist.
205209
var skippedFiles int
206210
var profileNotFoundErr error
@@ -365,10 +369,6 @@ func (cfg *sharedConfig) validateCredentialsConfig(profile string) error {
365369
return err
366370
}
367371

368-
if err := cfg.validateSSOConfiguration(profile); err != nil {
369-
return err
370-
}
371-
372372
return nil
373373
}
374374

@@ -409,7 +409,7 @@ func (cfg *sharedConfig) validateCredentialType() error {
409409
return nil
410410
}
411411

412-
func (cfg *sharedConfig) validateSSOConfiguration(profile string) error {
412+
func (cfg *sharedConfig) validateSSOConfiguration() error {
413413
if !cfg.hasSSOConfiguration() {
414414
return nil
415415
}
@@ -433,7 +433,7 @@ func (cfg *sharedConfig) validateSSOConfiguration(profile string) error {
433433

434434
if len(missing) > 0 {
435435
return fmt.Errorf("profile %q is configured to use SSO but is missing required configuration: %s",
436-
profile, strings.Join(missing, ", "))
436+
cfg.Profile, strings.Join(missing, ", "))
437437
}
438438

439439
return nil

aws/session/shared_config_test.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,23 @@ func TestLoadSharedConfig(t *testing.T) {
3030
{
3131
Filenames: []string{"file_not_exists"},
3232
Profile: "default",
33-
Expected: sharedConfig{},
33+
Expected: sharedConfig{
34+
Profile: "default",
35+
},
3436
},
3537
{
3638
Filenames: []string{testConfigFilename},
3739
Expected: sharedConfig{
38-
Region: "default_region",
40+
Profile: "default",
41+
Region: "default_region",
3942
},
4043
},
4144
{
4245
Filenames: []string{testConfigOtherFilename, testConfigFilename},
4346
Profile: "config_file_load_order",
4447
Expected: sharedConfig{
45-
Region: "shared_config_region",
48+
Profile: "config_file_load_order",
49+
Region: "shared_config_region",
4650
Creds: credentials.Value{
4751
AccessKeyID: "shared_config_akid",
4852
SecretAccessKey: "shared_config_secret",
@@ -54,7 +58,8 @@ func TestLoadSharedConfig(t *testing.T) {
5458
Filenames: []string{testConfigFilename, testConfigOtherFilename},
5559
Profile: "config_file_load_order",
5660
Expected: sharedConfig{
57-
Region: "shared_config_other_region",
61+
Profile: "config_file_load_order",
62+
Region: "shared_config_other_region",
5863
Creds: credentials.Value{
5964
AccessKeyID: "shared_config_other_akid",
6065
SecretAccessKey: "shared_config_other_secret",
@@ -66,9 +71,11 @@ func TestLoadSharedConfig(t *testing.T) {
6671
Filenames: []string{testConfigOtherFilename, testConfigFilename},
6772
Profile: "assume_role",
6873
Expected: sharedConfig{
74+
Profile: "assume_role",
6975
RoleARN: "assume_role_role_arn",
7076
SourceProfileName: "complete_creds",
7177
SourceProfile: &sharedConfig{
78+
Profile: "complete_creds",
7279
Creds: credentials.Value{
7380
AccessKeyID: "complete_creds_akid",
7481
SecretAccessKey: "complete_creds_secret",
@@ -81,6 +88,7 @@ func TestLoadSharedConfig(t *testing.T) {
8188
Filenames: []string{testConfigOtherFilename, testConfigFilename},
8289
Profile: "assume_role_invalid_source_profile",
8390
Expected: sharedConfig{
91+
Profile: "assume_role_invalid_source_profile",
8492
RoleARN: "assume_role_invalid_source_profile_role_arn",
8593
SourceProfileName: "profile_not_exists",
8694
},
@@ -93,11 +101,13 @@ func TestLoadSharedConfig(t *testing.T) {
93101
Filenames: []string{testConfigOtherFilename, testConfigFilename},
94102
Profile: "assume_role_w_creds",
95103
Expected: sharedConfig{
104+
Profile: "assume_role_w_creds",
96105
RoleARN: "assume_role_w_creds_role_arn",
97106
ExternalID: "1234",
98107
RoleSessionName: "assume_role_w_creds_session_name",
99108
SourceProfileName: "assume_role_w_creds",
100109
SourceProfile: &sharedConfig{
110+
Profile: "assume_role_w_creds",
101111
Creds: credentials.Value{
102112
AccessKeyID: "assume_role_w_creds_akid",
103113
SecretAccessKey: "assume_role_w_creds_secret",
@@ -110,6 +120,7 @@ func TestLoadSharedConfig(t *testing.T) {
110120
Filenames: []string{testConfigOtherFilename, testConfigFilename},
111121
Profile: "assume_role_wo_creds",
112122
Expected: sharedConfig{
123+
Profile: "assume_role_wo_creds",
113124
RoleARN: "assume_role_wo_creds_role_arn",
114125
SourceProfileName: "assume_role_wo_creds",
115126
},
@@ -127,6 +138,7 @@ func TestLoadSharedConfig(t *testing.T) {
127138
Filenames: []string{testConfigOtherFilename, testConfigFilename},
128139
Profile: "assume_role_with_credential_source",
129140
Expected: sharedConfig{
141+
Profile: "assume_role_with_credential_source",
130142
RoleARN: "assume_role_with_credential_source_role_arn",
131143
CredentialSource: credSourceEc2Metadata,
132144
},
@@ -135,12 +147,15 @@ func TestLoadSharedConfig(t *testing.T) {
135147
Filenames: []string{testConfigOtherFilename, testConfigFilename},
136148
Profile: "multiple_assume_role",
137149
Expected: sharedConfig{
150+
Profile: "multiple_assume_role",
138151
RoleARN: "multiple_assume_role_role_arn",
139152
SourceProfileName: "assume_role",
140153
SourceProfile: &sharedConfig{
154+
Profile: "assume_role",
141155
RoleARN: "assume_role_role_arn",
142156
SourceProfileName: "complete_creds",
143157
SourceProfile: &sharedConfig{
158+
Profile: "complete_creds",
144159
Creds: credentials.Value{
145160
AccessKeyID: "complete_creds_akid",
146161
SecretAccessKey: "complete_creds_secret",
@@ -154,9 +169,11 @@ func TestLoadSharedConfig(t *testing.T) {
154169
Filenames: []string{testConfigOtherFilename, testConfigFilename},
155170
Profile: "multiple_assume_role_with_credential_source",
156171
Expected: sharedConfig{
172+
Profile: "multiple_assume_role_with_credential_source",
157173
RoleARN: "multiple_assume_role_with_credential_source_role_arn",
158174
SourceProfileName: "assume_role_with_credential_source",
159175
SourceProfile: &sharedConfig{
176+
Profile: "assume_role_with_credential_source",
160177
RoleARN: "assume_role_with_credential_source_role_arn",
161178
CredentialSource: credSourceEc2Metadata,
162179
},
@@ -166,12 +183,15 @@ func TestLoadSharedConfig(t *testing.T) {
166183
Filenames: []string{testConfigOtherFilename, testConfigFilename},
167184
Profile: "multiple_assume_role_with_credential_source2",
168185
Expected: sharedConfig{
186+
Profile: "multiple_assume_role_with_credential_source2",
169187
RoleARN: "multiple_assume_role_with_credential_source2_role_arn",
170188
SourceProfileName: "multiple_assume_role_with_credential_source",
171189
SourceProfile: &sharedConfig{
190+
Profile: "multiple_assume_role_with_credential_source",
172191
RoleARN: "multiple_assume_role_with_credential_source_role_arn",
173192
SourceProfileName: "assume_role_with_credential_source",
174193
SourceProfile: &sharedConfig{
194+
Profile: "assume_role_with_credential_source",
175195
RoleARN: "assume_role_with_credential_source_role_arn",
176196
CredentialSource: credSourceEc2Metadata,
177197
},
@@ -182,20 +202,23 @@ func TestLoadSharedConfig(t *testing.T) {
182202
Filenames: []string{testConfigFilename},
183203
Profile: "with_sts_regional",
184204
Expected: sharedConfig{
205+
Profile: "with_sts_regional",
185206
STSRegionalEndpoint: endpoints.RegionalSTSEndpoint,
186207
},
187208
},
188209
{
189210
Filenames: []string{testConfigFilename},
190211
Profile: "with_s3_us_east_1_regional",
191212
Expected: sharedConfig{
213+
Profile: "with_s3_us_east_1_regional",
192214
S3UsEast1RegionalEndpoint: endpoints.RegionalS3UsEast1Endpoint,
193215
},
194216
},
195217
{
196218
Filenames: []string{testConfigFilename},
197219
Profile: "sso_creds",
198220
Expected: sharedConfig{
221+
Profile: "sso_creds",
199222
SSOAccountID: "012345678901",
200223
SSORegion: "us-west-2",
201224
SSORoleName: "TestRole",
@@ -206,25 +229,23 @@ func TestLoadSharedConfig(t *testing.T) {
206229
Filenames: []string{testConfigFilename},
207230
Profile: "source_sso_creds",
208231
Expected: sharedConfig{
232+
Profile: "source_sso_creds",
209233
RoleARN: "source_sso_creds_arn",
210234
SourceProfileName: "sso_creds",
211235
SourceProfile: &sharedConfig{
236+
Profile: "sso_creds",
212237
SSOAccountID: "012345678901",
213238
SSORegion: "us-west-2",
214239
SSORoleName: "TestRole",
215240
SSOStartURL: "https://127.0.0.1/start",
216241
},
217242
},
218243
},
219-
{
220-
Filenames: []string{testConfigFilename},
221-
Profile: "invalid_sso_creds",
222-
Err: fmt.Errorf("profile \"invalid_sso_creds\" is configured to use SSO but is missing required configuration: sso_region, sso_role_name, sso_start_url"),
223-
},
224244
{
225245
Filenames: []string{testConfigFilename},
226246
Profile: "sso_and_static",
227247
Expected: sharedConfig{
248+
Profile: "sso_and_static",
228249
Creds: credentials.Value{
229250
AccessKeyID: "sso_and_static_akid",
230251
SecretAccessKey: "sso_and_static_secret",

aws/session/testdata/credential_source_config

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,8 @@ sso_account_id = 012345678901
5252
sso_region = us-west-2
5353
sso_role_name = TestRole
5454
sso_start_url = https://THIS_SHOULD_NOT_BE_IN_TESTDATA_CACHE/start
55+
56+
[profile sso_invalid]
57+
sso_account_id = 012345678901
58+
sso_role_name = TestRole
59+

0 commit comments

Comments
 (0)