Describe the bug
In awsutil (module github.com/hashicorp/go-secure-stdlib/awsutil/v2), the
non-web-identity AssumeRole path in generateAwsConfigOptions
(awsutil/generate_credentials.go) sets the STS external ID unconditionally:
options.ExternalID = aws.String(c.RoleExternalId)
When no external ID is configured, c.RoleExternalId is "", so
aws.String("") produces a non-nil pointer to an empty string. The AWS SDK
serializes that as ExternalId="" on the sts:AssumeRole request, and STS
rejects it:
ValidationError: 1 validation error detected: Value '' at 'externalId' failed
to satisfy constraint: Member must have length greater than or equal to 2
This breaks role assumption for any caller that does not supply an external ID.
Note the same field is already guarded elsewhere in the file (the validation
block that returns "role external ID specified without role ARN" only fires
if c.RoleExternalId != ""), so the unconditional assignment in the
AssumeRole option callback is an inconsistency.
The web-identity branches (WithWebIdentityRoleCredentialOptions) do not set
ExternalID, so only the plain (non-web-identity) AssumeRole path is affected.
To Reproduce
Steps to reproduce the behavior:
-
Build a credentials config that assumes a role without an external ID:
c, _ := awsutil.NewCredentialsConfig(
awsutil.WithRoleArn("arn:aws:iam::123456789012:role/example"),
)
_, err := c.GenerateCredentialChain(ctx)
// resolve credentials (e.g. via the returned aws.Config)
-
Trigger credential resolution so the SDK performs the sts:AssumeRole call.
-
See the STS ValidationError above.
A unit-level reproduction (no network) is that the generated
AssumeRoleOptions.ExternalID is aws.String("") (non-nil) instead of nil
when no external ID is provided.
Expected behavior
When no external ID is configured, AssumeRoleOptions.ExternalID should remain
nil and no ExternalId parameter should be sent to STS, so AssumeRole
succeeds for roles whose trust policy does not require an external ID.
Additional context
Describe the bug
In
awsutil(modulegithub.com/hashicorp/go-secure-stdlib/awsutil/v2), thenon-web-identity AssumeRole path in
generateAwsConfigOptions(
awsutil/generate_credentials.go) sets the STS external ID unconditionally:When no external ID is configured,
c.RoleExternalIdis"", soaws.String("")produces a non-nil pointer to an empty string. The AWS SDKserializes that as
ExternalId=""on thests:AssumeRolerequest, and STSrejects it:
This breaks role assumption for any caller that does not supply an external ID.
Note the same field is already guarded elsewhere in the file (the validation
block that returns
"role external ID specified without role ARN"only firesif c.RoleExternalId != ""), so the unconditional assignment in theAssumeRole option callback is an inconsistency.
The web-identity branches (
WithWebIdentityRoleCredentialOptions) do not setExternalID, so only the plain (non-web-identity) AssumeRole path is affected.To Reproduce
Steps to reproduce the behavior:
Build a credentials config that assumes a role without an external ID:
Trigger credential resolution so the SDK performs the
sts:AssumeRolecall.See the STS
ValidationErrorabove.A unit-level reproduction (no network) is that the generated
AssumeRoleOptions.ExternalIDisaws.String("")(non-nil) instead ofnilwhen no external ID is provided.
Expected behavior
When no external ID is configured,
AssumeRoleOptions.ExternalIDshould remainniland noExternalIdparameter should be sent to STS, so AssumeRolesucceeds for roles whose trust policy does not require an external ID.
Additional context
awsutil/v2 v2.1.2(latest at time of writing); theunconditional assignment is present on
main.terraform-provider-vault([Bug]: auth_login_aws assumes aws_role_arn twice, breaking any role that can't assume itself terraform-provider-vault#2922). The provider hits this whenever it
routes a non-web-identity role assumption through
WithRoleArn. The providerfix in fix(auth_login_aws): assume aws_role_arn only once for non-web-identity credentials terraform-provider-vault#2923 only stops exercising this
code path; the underlying library defect remains and affects other consumers.