Files
seaweedfs/weed/iam/sts/claim_based_policy_test.go
T
Chris Lu 1d3454ca5c feat(iam): claim-based policy mode for AssumeRoleWithWebIdentity (Phase 3b) (#9322)
* feat(iam): claim-based policy mode for AssumeRoleWithWebIdentity

When the caller passes the sentinel RoleArn arn:aws:iam:::role/sts-claim-based
(or omits it entirely) and the matched OIDC provider has policyClaim set,
mint a session whose effective policies come from that JWT claim instead
of from a server-side role mapping. Accepts string, comma-separated
string, or array shapes — MinIO-compatible behaviour for IDPs that
already attach policies to the user.

Trust-policy validation is skipped in claim-mode: the IDP is the sole
authority for both authentication and authorization, mirroring the
contract MinIO documents for its DummyRoleARN flow. Concrete-role mode
is unchanged and still requires the role definition + trust policy.

* fix(iam): trim policy-claim array elements + clean up stale comments

Three medium-priority cleanups gemini flagged on the claim-based path:

- extractClaimPolicies's array branch was leaving whitespace on each
  element while the string/comma-separated branch trimmed via
  splitPolicyClaimString. An IDP that emits ["readonly", " billing "]
  would create a "billing" policy lookup that didn't match the stored
  name. Trim every array element, drop empties.
- The "synthetic ARN keyed on the session name" comment was wrong —
  effectiveRoleArn here is the literal sentinel; it's the assumed-role
  ARN generated downstream that's session-keyed. Reword.
- The empty if/else block at the start of
  validateAssumeRoleWithWebIdentityRequest existed only to host a
  comment about deferred validation; the comment now lives in the
  function godoc and the empty branch is gone.

Addresses three gemini medium reviews on PR #9322.
2026-05-05 12:21:55 -07:00

24 lines
566 B
Go

package sts
import "testing"
func TestIsClaimBasedPolicyRoleArn(t *testing.T) {
cases := []struct {
name string
arn string
want bool
}{
{"empty matches", "", true},
{"sentinel matches", ClaimBasedPolicyRoleArn, true},
{"concrete role does not", "arn:aws:iam::123:role/admin", false},
{"random ARN does not", "arn:aws:sts::123:assumed-role/X/Y", false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := IsClaimBasedPolicyRoleArn(tc.arn); got != tc.want {
t.Fatalf("got=%v want=%v", got, tc.want)
}
})
}
}