From 3917f52ca025230f5a10c4a7b023311653701073 Mon Sep 17 00:00:00 2001 From: nomeelnoj <4316746+nomeelnoj@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:54:33 -0700 Subject: [PATCH] fix(awsutil): only set AssumeRole ExternalID when provided The non-web-identity AssumeRole path set options.ExternalID unconditionally via aws.String(c.RoleExternalId). When no external ID was configured this produced a non-nil pointer to an empty string, which the SDK serializes as ExternalId="" on the STS AssumeRole call. STS then rejects the request with a ValidationError ("Member must have length greater than or equal to 2"), breaking role assumption for any caller that does not use an external ID. Guard the assignment so ExternalID is only set when a non-empty value is provided, matching the existing empty-value handling for this field. Adds a regression test covering AssumeRole without an external ID. Signed-off-by: nomeelnoj <4316746+nomeelnoj@users.noreply.github.com> --- awsutil/generate_credentials.go | 4 +++- awsutil/generate_credentials_test.go | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/awsutil/generate_credentials.go b/awsutil/generate_credentials.go index 224f177..dc29b84 100644 --- a/awsutil/generate_credentials.go +++ b/awsutil/generate_credentials.go @@ -254,7 +254,9 @@ func (c *CredentialsConfig) generateAwsConfigOptions(ctx context.Context, opts o assumeRoleCred := config.WithAssumeRoleCredentialOptions(func(options *stscreds.AssumeRoleOptions) { options.RoleARN = c.RoleARN options.RoleSessionName = c.RoleSessionName - options.ExternalID = aws.String(c.RoleExternalId) + if c.RoleExternalId != "" { + options.ExternalID = aws.String(c.RoleExternalId) + } for k, v := range c.RoleTags { options.Tags = append(options.Tags, types.Tag{ Key: aws.String(k), diff --git a/awsutil/generate_credentials_test.go b/awsutil/generate_credentials_test.go index 145ca4d..af7128d 100644 --- a/awsutil/generate_credentials_test.go +++ b/awsutil/generate_credentials_test.go @@ -474,6 +474,25 @@ func TestGenerateAwsConfigOptions(t *testing.T) { }, }, }, + { + name: "assume role credential without external id", + cfg: func() *CredentialsConfig { + credCfg, err := NewCredentialsConfig( + WithRoleArn("foo"), + WithRoleSessionName("bar"), + ) + require.NoError(t, err) + return credCfg + }(), + expectedLoadOptions: config.LoadOptions{ + Region: "us-east-1", + }, + expectedAssumeRoleOptions: &stscreds.AssumeRoleOptions{ + RoleARN: "foo", + RoleSessionName: "bar", + ExternalID: nil, + }, + }, { name: "static credential", cfg: func() *CredentialsConfig {