Skip to content

fix(iam): resolve attached AWS-managed policies for any account - #1663

Merged
hectorvent merged 4 commits into
floci-io:mainfrom
abanna:fix/iam-managed-policy-attachment-resolution
Jul 3, 2026
Merged

fix(iam): resolve attached AWS-managed policies for any account#1663
hectorvent merged 4 commits into
floci-io:mainfrom
abanna:fix/iam-managed-policy-attachment-resolution

Conversation

@abanna

@abanna abanna commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1573 (AWS-managed policies resolvable from any account context).

AWS-managed policies (arn:aws:iam::aws:policy/...) are global and live in the in-memory catalog, not the account-partitioned policy store. getPolicy already serves them from the catalog, but several IAM read paths resolved attached-policy ARNs straight from the account-scoped store (policies.get(arn) / the flatMap variants). As a result, a managed policy attached to a principal owned by a non-default account was silently dropped from the response.

This adds a catalog-aware resolvePolicy(arn) helper (modeled on getPolicy) and routes the affected reads through it:

  • listAttachedUserPolicies / listAttachedGroupPolicies / listAttachedRolePolicies
  • the user/role permissions-boundary document resolvers
  • collectUserPolicies / collectRolePolicies (the SimulatePrincipalPolicy / caller-context paths)

Customer-policy-only logic and attachment-count bookkeeping on detach are left untouched.

Type of change

  • Bug fix (fix:)

AWS Compatibility

For bug fixes: an AWS-managed policy attached to a user/group/role in a non-default account was not returned by the attached-policy read APIs (and not evaluated by SimulatePrincipalPolicy), because those paths only consulted the account-scoped customer-policy store. Managed policies are global, so they are now resolved from the catalog regardless of the caller's account.

Checklist

  • ./mvnw test passes locally (IamManagedPolicyAccountScopeTest: 6 tests; IamServiceTest: 57 tests — run in an eclipse-temurin:25-jdk container)
  • New or updated integration test added (IamManagedPolicyAccountScopeTest)
  • Commit messages follow Conventional Commits

AWS-managed policies (arn:aws:iam::aws:policy/...) are global and live in the
in-memory catalog, not the account-partitioned policy store; getPolicy already
serves them from the catalog. Several IAM read paths, however, resolved attached
policy ARNs straight from the account-scoped store (policies.get(arn) / the
flatMap variants), so a managed policy attached to a principal owned by a
non-default account was silently dropped.

Add a catalog-aware resolvePolicy(arn) helper modeled on getPolicy and route the
affected reads through it: listAttachedUser/Group/RolePolicies, the user/role
permissions-boundary document resolvers, and collectUser/RolePolicies (the
SimulatePrincipalPolicy / caller-context paths). Customer-policy-only logic and
attachment-count bookkeeping on detach are left untouched.
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown

Greptile Summary

Introduces a private resolvePolicy(arn) helper that routes AWS-managed policy ARNs to the global in-memory catalog and customer-managed ARNs to the account-partitioned store, then wires all attached-policy read paths through it. This fixes a silent drop of managed policies on principals owned by non-default accounts.

  • resolvePolicy is a non-throwing mirror of getPolicy, used by listAttachedUserPolicies, listAttachedGroupPolicies, listAttachedRolePolicies, the permissions-boundary document resolvers, and collectUserPolicies/collectRolePolicies.
  • Three new unit tests cover the fix for users, groups, and roles (including the permissions boundary path) in a non-default account context, with customer-policy account-isolation confirmed as a control.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to read paths, customer-policy isolation is untouched, and all affected code paths are covered by new tests.

The fix is minimal: one new private helper and seven mechanical call-site substitutions. The helper mirrors an already-correct method (getPolicy), the original policies.get fallback is preserved for customer-managed ARNs, and write/detach/count paths are explicitly left untouched. Three new tests exercise every changed code path — user, group, and role — including the permissions-boundary resolver and the SimulatePrincipalPolicy collection path.

No files require special attention.

Important Files Changed

Filename Overview
src/main/java/io/github/hectorvent/floci/services/iam/IamService.java Adds resolvePolicy(arn) helper and replaces 7 call sites that previously used policies.get(arn) directly; logic is correct and consistent with getPolicy.
src/test/java/io/github/hectorvent/floci/services/iam/IamManagedPolicyAccountScopeTest.java Adds three targeted tests covering user, group, and role managed-policy resolution in non-default accounts, including permissions boundary and SimulatePrincipalPolicy paths.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant IamService
    participant awsManagedPolicies as awsManagedPolicies (global catalog)
    participant policies as policies (account-partitioned store)

    Caller->>IamService: listAttachedUserPolicies / listAttachedGroupPolicies

    IamService->>IamService: resolvePolicy(arn)

    alt arn starts with arn:aws:iam::aws:policy/
        IamService->>awsManagedPolicies: get(arn)
        awsManagedPolicies-->>IamService: Optional IamPolicy (global, account-independent)
    else customer-managed ARN
        IamService->>policies: get(arn)
        policies-->>IamService: Optional IamPolicy (scoped to caller account)
    end

    IamService-->>Caller: resolved policy (or empty)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant IamService
    participant awsManagedPolicies as awsManagedPolicies (global catalog)
    participant policies as policies (account-partitioned store)

    Caller->>IamService: listAttachedUserPolicies / listAttachedGroupPolicies

    IamService->>IamService: resolvePolicy(arn)

    alt arn starts with arn:aws:iam::aws:policy/
        IamService->>awsManagedPolicies: get(arn)
        awsManagedPolicies-->>IamService: Optional IamPolicy (global, account-independent)
    else customer-managed ARN
        IamService->>policies: get(arn)
        policies-->>IamService: Optional IamPolicy (scoped to caller account)
    end

    IamService-->>Caller: resolved policy (or empty)
Loading

Reviews (4): Last reviewed commit: "Merge branch 'main' into fix/iam-managed..." | Re-trigger Greptile

@hectorvent hectorvent added bug Something isn't working iam AWS Identity and Access Management (IAM) labels Jul 1, 2026
abanna added 2 commits July 1, 2026 22:25
…non-default account

Adds the group analog of the existing user/role tests, exercising listAttachedGroupPolicies
(the resolvePolicy catalog fix) for a group owned by a non-default account, with a customer
policy attached to the same group as an account-scoping control.
@abanna

abanna commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Applied the Greptile P2 — added the group analog of the existing user/role tests: attachedManagedPolicyResolvesForGroupInNonDefaultAccount exercises listAttachedGroupPolicies (the resolvePolicy catalog lookup) for a group owned by a non-default account, with a customer policy attached to the same group as the account-scoping control. Branch is up to date with main (merge) and green.

@hectorvent hectorvent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @abanna

@hectorvent
hectorvent merged commit 952f302 into floci-io:main Jul 3, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working iam AWS Identity and Access Management (IAM)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants