fix: when claim-based OIDC is configured, treat unknown roleArn as claim-based auth (#21512)

RoleARN is a required parameter in AssumeRoleWithWebIdentity, 
according to the standard AWS implementation, and the official 
AWS SDKs and CLI will not allow you to assume a role from a JWT 
without also specifying a RoleARN.  This meant that it was not 
possible to use the official SDKs for claim-based OIDC with Minio 
(minio/minio#21421), since Minio required you to _omit_ the RoleARN in this case.

minio/minio#21468 attempted to fix this by disabling the validation 
of the RoleARN when a claim-based provider was configured, but this had 
the side effect of making it impossible to have a mixture of claim-based 
and role-based OIDC providers configured at the same time - every 
authentication would be treated as claim-based, ignoring the RoleARN entirely.

This is an alternative fix, whereby:

- _if_ the `RoleARN` is one that Minio knows about, then use the associated role policy
- if the `RoleARN` is not recognised, but there is a claim-based provider configured, then ignore the role ARN and attempt authentication with the claim-based provider
- if the `RoleARN` is not recognised, and there is _no_ claim-based provider, then return an error.
This commit is contained in:
Ian Roberts 2025-08-08 18:51:23 +01:00 committed by GitHub
parent c7d6a9722d
commit b44b2a090c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 18 additions and 9 deletions

View File

@ -414,20 +414,29 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ
//
// Currently, we do not support multiple claim based IDPs, as there is no
// defined parameter to disambiguate the intended IDP in this STS request.
//
// Skip RoleArn existence check when policy mapping is based on a JWT claim.
// This is required to support clients (like the AWS CLI or SDKs) that enforce providing a RoleArn,
// even though it's not used in claim-based identity mode.
roleArn := openid.DummyRoleARN
roleArnStr := r.Form.Get(stsRoleArn)
if roleArnStr != "" && strings.TrimSpace(iamPolicyClaimNameOpenID()) == "" {
isRolePolicyProvider := roleArnStr != ""
if isRolePolicyProvider {
var err error
roleArn, _, err = globalIAMSys.GetRolePolicy(roleArnStr)
if err != nil {
// If there is no claim-based provider configured, then an
// unrecognized roleArn is an error
if strings.TrimSpace(iamPolicyClaimNameOpenID()) == "" {
writeSTSErrorResponse(ctx, w, ErrSTSInvalidParameterValue,
fmt.Errorf("Error processing %s parameter: %v", stsRoleArn, err))
return
}
// If there *is* a claim-based provider configured, then
// treat an unrecognized roleArn the same as no roleArn
// at all. This is to support clients like the AWS SDKs
// or CLI that will not allow an AssumeRoleWithWebIdentity
// call without a RoleARN parameter - for these cases the
// user can supply a dummy ARN, which Minio will ignore.
roleArn = openid.DummyRoleARN
isRolePolicyProvider = false
}
}
if !globalIAMSys.Initialized() {
@ -455,7 +464,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ
}
var policyName string
if roleArnStr != "" && globalIAMSys.HasRolePolicy() && strings.TrimSpace(iamPolicyClaimNameOpenID()) == "" {
if isRolePolicyProvider {
// If roleArn is used, we set it as a claim, and use the
// associated policy when credentials are used.
claims[roleArnClaim] = roleArn.String()