aws / aws/aws-cdk

(aws-iam): Minimizing assume policies with conditions results in error

Open
#28,713 10 comments 9 reactions 0 assignees View on GitHub
@aws-cdk/aws-iam bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

When using the AWS CDK with the `"@aws-cdk/aws-iam:minimizePolicies": true` setting, an error is encountered when creating a `Role` with a `PrincipalWithConditions`. The error suggests that the principals in a `PolicyStatement` must have the same conditions, even though they do have the same conditions.

### Expected Behavior

The AWS CDK should successfully create a Role with a PrincipalWithConditions, even when the `"@aws-cdk/aws-iam:minimizePolicies"` setting is set to true. The conditions specified for the principals in the `PolicyStatement` should be correctly merged without causing an error.

### Current Behavior

The following error is throw:
```
Error: Resolution error: Resolution error: Resolution error: All principals in a PolicyStatement must have the same Conditions (got '{}' and '{"StringEquals":{"aws:SourceAccount":"${Token[AWS.AccountId.3]}"}}'). Use multiple statements instead..
Object creation stack:
at stack traces disabled..
at PolicyStatement.addPrincipalConditions (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:7201)
at PolicyStatement.addPrincipals (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:2407)
at new PolicyStatement (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:663)
at PolicyStatement.copy (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-statement.js:2:6086)
at mergeIfCombinable (.../node_modules/aws-cdk-lib/aws-iam/lib/private/merge-statements.js:1:1847)
at onePass (.../node_modules/aws-cdk-lib/aws-iam/lib/private/merge-statements.js:1:1032)
at mergeStatements (.../node_modules/aws-cdk-lib/aws-iam/lib/private/merge-statements.js:1:660)
at PolicyDocument._maybeMergeStatements (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-document.js:1:3033)
at PolicyDocument.resolve (.../node_modules/aws-cdk-lib/aws-iam/lib/policy-document.js:1:1755)
at RememberingTokenResolver.resolveToken (.../node_modules/aws-cdk-lib/core/lib/resolvable.js:1:1401)
```

### Reproduction Steps

```js
const principal = new PrincipalWithConditions(
new ServicePrincipal("scheduler.amazonaws.com"),
{
StringEquals: {
"aws:SourceAccount": Stack.of(this).account,
},
}
);

const role = new Role(this, "Role", {
assumedBy: principal,
});

role.assumeRolePolicy?.addStatements(
new PolicyStatement({
effect: Effect.ALLOW,
principals: [principal],
actions: ["sts:AssumeRole"],
})
);
```

### Possible Solution

I think the issue might originate from here [main/packages/aws-cdk-lib/aws-iam/lib/private/merge-statements.ts:54](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-iam/lib/private/merge-statements.ts#L54), but I can't pinpoint it exactly.

### Additional Information/Context

It's worth noting that this issue has downstream effects, impacting the functionality of `aws-scheduler-targets` when using the same lambda with two schedulers.
```js
const func = new Function(this, "Function", {
code: Code.fromInline("exports.handler = () => {}"),
handler: "index.handler",
runtime: Runtime.NODEJS_18_X,
});

new Schedule(this, "Schedule1", {
schedule: ScheduleExpression.cron({}),
target: new LambdaInvoke(func, {}),
});

new Schedule(this, "Schedule2", {
schedule: ScheduleExpression.cron({}),
target: new LambdaInvoke(func, {}),
});
```

### CDK CLI Version

2.121.1

### Framework Version

_No response_

### Node.js Version

18.19.0

### OS

macOS 14.2.1

### Language

TypeScript

### Language Version

_No response_

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Reproduce the failure with the provided PrincipalWithConditions and assume-role policy example, then inspect packages/aws-cdk-lib/aws-iam/lib/private/merge-statements.ts around line 54 and the PolicyStatement paths in the stack trace. Check how policy statements are copied and merged when minimizePolicies is enabled. Done means the Role synthesizes successfully with matching principal conditions and the scheduler scenario no longer triggers the resolution error.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
authorization, cloud, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.