Skip to content

fix(iam): anchor policy wildcards and support ? (AUTHZ-X2) - #1439

Merged
NitinKumar004 merged 3 commits into
developmentfrom
fix/iam-wildcard-anchor
Oct 4, 2026
Merged

NitinKumar004 merged 3 commits into
developmentfrom
fix/iam-wildcard-anchor

Conversation

@NitinKumar004

Copy link
Copy Markdown
Collaborator

What

Fixes AUTHZ-X2. The IAM policy matcher (wildcardMatch) didn't anchor the end of the pattern, so an Allow on s3:*Bucket also matched s3:DeleteBucketPolicy, and dynamodb:*Table matched ListTables and DescribeTableReplicaAutoScaling. It also didn't support ?.

Changes

  • New providers/aws/iam/wildcard.go with one anchored glob (* = any run including empty, ? = exactly one character). Every AWS IAM matcher now goes through it:
    • Action / NotAction: case-insensitive, the way IAM treats action names.
    • Resource / NotResource: case-sensitive. * can still span colons (arn:aws:dynamodb:* keeps working).
    • Trust policy principal entries: anchored, case-sensitive.
    • StringLike / StringNotLike: anchored, case-sensitive, ? supported.
    • ArnLike / ArnEquals (and the Not forms): matched per ARN component. Each of the six components is checked on its own, so a * can't span a component boundary. The resource component keeps any colons it carries. A pattern with no colon at all (such as *) is still matched against the whole value.
  • Service-wide simulation (coversService, couldMatchService) is case-insensitive and handles ?. coversService only says yes when the pattern is a head followed by trailing *s and the head matches a prefix of svc:. It can say no to an unusual pattern that does cover the service, but never the reverse, so X1a's conservative property still holds.
  • Azure and GCP IAM had copies of the same matcher with the same missing end anchor. I fixed the anchor there too and kept them *-only and case-sensitive as before.

Tests

  • providers/aws/iam/wildcard_match_test.go was written first and failed on the old code. It covers s3:*Bucket vs s3:DeleteBucketPolicy, s3:Get?bject, * matching an empty string, arn:aws:s3:::b/*, the case rules for Action vs Resource, StringLike/StringNotLike, ArnLike per component, and trust principals.
  • New grid check TestConservativeModesNeverWiden: across */? patterns, Action/NotAction and Allow/Deny, the unknown-resource and service-wide modes never allow something a concrete evaluation denies, and never miss a Deny a concrete evaluation hits. The existing X1a tests in evaluate_modes_test.go still pass.
  • The existing TestWildcardMatch in providers/aws/iam/iam_test.go now calls globMatch, because wildcardMatch was removed. Its cases are unchanged. No existing test depended on the old unanchored behaviour.
  • Ran go test -race on providers/{aws,azure,gcp}/iam, services/iam/..., server/aws, server/aws/{iam,sts,eks}, features/chaos, services/cost and the root IAM tests. All pass. golangci-lint --new-from-rev=origin/development reports 0 issues.

E2E

Ran cloudemu serve --enforce-auth on port 64566 and used the aws CLI with the keys of a user whose only policy is Allow dynamodb:*Table on *:

  • DescribeTable: allowed
  • CreateTable: allowed
  • UpdateTimeToLive: AccessDeniedException
  • ListTables: AccessDeniedException (the old matcher allowed this)
  • DescribeTableReplicaAutoScaling: AccessDeniedException (the old matcher allowed this)

Behaviour changes to be aware of

  • Policies that only matched because the end wasn't anchored now stop matching. That is the fix.
  • ArnLike patterns with fewer than six components, such as arn:aws:iam::*, no longer match a full ARN. IAM compares ARNs component by component, so this follows AWS.
  • Action names now match regardless of case. For example, S3:getobject matches s3:GetObject.

@NitinKumar004
NitinKumar004 marked this pull request as ready for review October 4, 2026 11:04
@NitinKumar004
NitinKumar004 merged commit 9663b76 into development Oct 4, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant