Skip to content

fix(model): honour role trust policy as resource policy for sts:AssumeRole#32

Open
xoverride wants to merge 1 commit into
ReversecLabs:mainfrom
xoverride:fix/sts-assumerole-trust
Open

fix(model): honour role trust policy as resource policy for sts:AssumeRole#32
xoverride wants to merge 1 commit into
ReversecLabs:mainfrom
xoverride:fix/sts-assumerole-trust

Conversation

@xoverride

Copy link
Copy Markdown

Summary

IAMSpy returns denied for sts:AssumeRole calls that AWS allows, for both same-account and cross-account assumes, whenever the target is an IAM role.

A role's trust policy (AssumeRolePolicyDocument) is the resource policy that governs sts:AssumeRole, but it lives in the GAAD rather than in the resource policies loaded via load_resource_policies. generate_solver only consulted resource_policies, so when a role was the target of an assume, add_resource found nothing and set resource_<target> == False. That makes z3.Bool("resource") unsatisfiable, and since the sts:assumerole rule requires resource to be true, every assume was denied.

This affected both an explicit Principal:{AWS:".../Caller"} trust and an account-root Principal:{AWS:"...:root"} trust — confirming the defect is in resource-side trust loading, not :root resolution.

Root cause

iamspy/model.pygenerate_solver resource loop only loaded explicitly-provided resource policies; a target role's trust doc was never loaded resource-side. A secondary instance in _check_viable_source_accounts pruned cross-account sources for trust-only roles, so who_can missed cross-account assumers.

Fix

  • Resolve a target role's trust policy from the loaded GAAD on demand when no explicit resource policy exists (new _get_role_trust_policy helper). Explicit resource policies still take precedence.
  • Apply the same fallback in _check_viable_source_accounts so cross-account assumers are evaluated.

Tests

First sts:AssumeRole integration tests in the suite:

  • explicit-principal trust -> allowed
  • :root delegation trust -> allowed
  • non-matching trust -> denied
  • :root trust but caller lacks sts:AssumeRole identity permission -> denied (delegation still requires identity)
  • who_can resolves only the identity-permitted caller

All 46 tests pass.

…eRole

A role's trust policy (AssumeRolePolicyDocument) is the resource policy
that governs sts:AssumeRole, but it is stored in the GAAD rather than in
the explicitly loaded resource policies. generate_solver only consulted
resource_policies, so when a role was the *target* of an assume its trust
constraint was set to False, making z3.Bool("resource") unsatisfiable and
denying every same-account and cross-account assume that AWS allows.

Resolve the target role's trust policy from the loaded GAAD on demand when
no explicit resource policy exists, for both can_i and the source-account
pruning in _check_viable_source_accounts (so who_can finds cross-account
assumers). Explicit resource policies still take precedence.

Add the first sts:AssumeRole integration tests: explicit-principal trust,
:root delegation trust, non-matching trust, :root without identity
permission, and who_can resolution.
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