Skip to content

feat(iam): PassRole trust-policy enforcement on Lambda + ECS#739

Merged
vieiralucas merged 4 commits intomainfrom
worktree-integrations-batch5-iam-passrole
Apr 24, 2026
Merged

feat(iam): PassRole trust-policy enforcement on Lambda + ECS#739
vieiralucas merged 4 commits intomainfrom
worktree-integrations-batch5-iam-passrole

Conversation

@vieiralucas
Copy link
Copy Markdown
Member

@vieiralucas vieiralucas commented Apr 24, 2026

Summary

  • Real AWS rejects CreateFunction / RegisterTaskDefinition / RunTask when the supplied role's AssumeRolePolicyDocument doesn't list the calling service principal — regardless of the caller's identity policy. fakecloud now does the same.
  • New RoleTrustValidator trait in fakecloud-core so service crates emit a wire-shaped error without depending on fakecloud-iam. IamRoleTrustValidator (in fakecloud-iam/src/pass_role.rs) parses the trust policy, walks Allow statements, and matches Principal.Service against the supplied service principal.
  • Lambda CreateFunction rejects roles that don't trust lambda.amazonaws.com. ECS RegisterTaskDefinition (taskRoleArn + executionRoleArn) and RunTask overrides reject roles that don't trust ecs-tasks.amazonaws.com. Both raise InvalidParameterValueException / InvalidParameterException.

Test plan

  • cargo test -p fakecloud-iam pass_role — 5 unit tests for trust-policy parsing
  • cargo test -p fakecloud-e2e --test iam_pass_role — 4 e2e tests (Lambda + ECS, accept + reject)
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo fmt --check clean

The identity-policy half of iam:PassRole (caller permission) lives in the existing IAM evaluator and runs at the IAM evaluator boundary; this PR covers the trust-policy half real AWS enforces unconditionally at the service boundary.


Summary by cubic

Enforces PassRole trust-policy checks in Lambda and ECS. Roles that don’t trust the service principal are rejected; malformed trust policies now fail, while non-role ARNs or missing roles/accounts remain allowed.

  • New Features

    • Lambda CreateFunction and ECS RegisterTaskDefinition / RunTask overrides reject roles whose AssumeRolePolicyDocument excludes lambda.amazonaws.com or ecs-tasks.amazonaws.com, returning InvalidParameterValueException / InvalidParameterException.
    • Added RoleTrustValidator in fakecloud-core and IamRoleTrustValidator in fakecloud-iam; wired into fakecloud-lambda, fakecloud-ecs, and server with unit + e2e tests.
  • Bug Fixes

    • Trust-policy parsing accepts wildcard principals ("*" / {"AWS":"*"} / {"Service":"*"}), matching AWS.
    • Malformed trust policy JSON now rejects PassRole; permissive only when the ARN isn’t an IAM role or the account/role isn’t in state. Docs clarify enforcement is on CreateFunction only.

Written for commit e591a5e. Summary will update on new commits.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="website/content/docs/guides/cross-service-integration.md">

<violation number="1" location="website/content/docs/guides/cross-service-integration.md:50">
P3: Drop `UpdateFunctionConfiguration` from this bullet; fakecloud only enforces the trust-policy check on `CreateFunction`, not on Lambda role updates.</violation>
</file>

<file name="crates/fakecloud-iam/src/pass_role.rs">

<violation number="1" location="crates/fakecloud-iam/src/pass_role.rs:123">
P1: `"Principal": "*"` (wildcard) is not handled — roles with a wildcard trust policy will be incorrectly rejected. When `principal` is a `Value::String("*")`, `.get("Service")` returns `None` and the function returns `false`. Add an early check for the wildcard string.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread crates/fakecloud-iam/src/pass_role.rs
Comment thread website/content/docs/guides/cross-service-integration.md Outdated
Real AWS rejects CreateFunction / RegisterTaskDefinition / RunTask
with InvalidParameterValueException when the supplied role's
AssumeRolePolicyDocument doesn't list the calling service principal,
regardless of the caller's identity policy. fakecloud now performs
the same check at the service boundary.

- New `RoleTrustValidator` trait in fakecloud-core/src/auth.rs so
  service crates surface a wire-shaped error without depending on
  fakecloud-iam directly.
- `IamRoleTrustValidator` impl in fakecloud-iam/src/pass_role.rs
  parses the trust policy, walks Allow statements, and matches
  Principal.Service against the supplied service principal.
- LambdaService.create_function rejects roles that don't trust
  lambda.amazonaws.com.
- EcsService.register_task_definition + run_task overrides reject
  roles that don't trust ecs-tasks.amazonaws.com.
- E2E coverage in iam_pass_role.rs (4 happy-path + negative tests)
  plus 5 unit tests for trust-policy parsing.

The identity-policy half of `iam:PassRole` (caller permission) lives
in the existing IAM evaluator and is invoked separately at the IAM
evaluator boundary.
Cubic flagged that `"Principal": "*"` and `{"AWS": "*"}` (wildcard
trust policies) were being rejected because `principal_service_includes`
only inspected the `Service` key. Match real AWS:
- bare `"Principal": "*"` allows any service principal,
- `{"AWS": "*"}` allows any service principal,
- `{"Service": "*"}` allows any service principal,
- existing exact-match behavior for explicit service principals
  is preserved.

Also dropped an inaccurate `UpdateFunctionConfiguration` mention
from the website docs — fakecloud only enforces the trust-policy
check on `CreateFunction` (the existing tests cover this).
@vieiralucas vieiralucas force-pushed the worktree-integrations-batch5-iam-passrole branch from 8c390b5 to d491b5c Compare April 24, 2026 22:42
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

The strict PassRole check broke long-standing fakecloud Lambda E2E
tests that pass arbitrary role ARNs without first creating the IAM
role. Real AWS does require the role to exist for CreateFunction,
but fakecloud's test culture has historically been more permissive.

Make `IamRoleTrustValidator` return `Ok(())` when:
- the ARN doesn't parse as an IAM role ARN, or
- the account isn't in IAM state, or
- the role doesn't exist, or
- the trust policy doesn't parse as JSON.

Only the high-signal failure mode — role exists with a trust policy
that explicitly excludes the calling service principal — still
produces `InvalidParameterValueException` / `InvalidParameterException`.

E2E coverage of both branches preserved:
- positive: role with matching trust policy is accepted,
- negative: role exists with mismatched trust policy is rejected.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/fakecloud-iam/src/pass_role.rs">

<violation number="1" location="crates/fakecloud-iam/src/pass_role.rs:79">
P1: Malformed trust policies are currently treated as allowed, which bypasses PassRole trust enforcement for existing roles with invalid JSON.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread crates/fakecloud-iam/src/pass_role.rs Outdated
Cubic flagged that the previous permissive change made roles with
malformed `AssumeRolePolicyDocument` JSON pass through silently. The
intent of permissive mode was only to skip the check when the role
itself doesn't exist (preserving fakecloud's test culture of arbitrary
role ARNs); existing roles with broken trust policies should still
fail validation so misconfigurations don't slip through.

Restore `InvalidTrustPolicy` as a hard error path on the parse step.
RoleNotFound / ARN-doesn't-parse / no IAM state for account remain
permissive.
@vieiralucas vieiralucas merged commit a7e18c5 into main Apr 24, 2026
48 of 49 checks passed
@vieiralucas vieiralucas deleted the worktree-integrations-batch5-iam-passrole branch April 24, 2026 23:19
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