Repository navigation
fix(aws): pin the customer role to read-only actions, document auditing Maple in CloudTrail - #2528
Conversation
…ng Maple in CloudTrail A test fails if any module, or the role's self-read, grants a non-read action, attaches an AWS managed policy that is not read-only, or widens the trust past one connection's subject. The docs say what the role cannot read and how to audit and cut off Maple's access.
Maple review🟢 Confidence 8/10 · likely safe to merge. Held at 8 because a warning is open. Adds a test pinning the generated AWS setup plan to read-only actions, read-only managed policies and a single-connection trust policy, plus a docs section on auditing Maple in CloudTrail. Sound guards, but the trust-policy check inspects only
Findings🟠 Warning · F1 · Trust assertion ignores condition operators other than
|
|
Caution Review failedThe pull request is closed.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
| expect(statement.Condition?.StringEquals).toEqual({ | ||
| "api.maple.test/oidc/aws:aud": "sts.amazonaws.com", | ||
| "api.maple.test/oidc/aws:sub": awsOidcSubject(connectionId), | ||
| }) |
There was a problem hiding this comment.
Warning
Trust assertion ignores condition operators other than StringEquals
F1 · Warning · tests
expect(statement.Condition?.StringEquals).toEqual(...) reads one operator, so a StringLike clause added beside it — {"api.maple.test/oidc/aws:sub": "aws-connection:*"} — lets another connection's token assume this role and the test still passes. IamStatement.Condition (packages/domain/src/aws.ts:204) admits any operator map.
Assert the whole `Condition` object so any added operator fails.
| expect(statement.Condition?.StringEquals).toEqual({ | |
| "api.maple.test/oidc/aws:aud": "sts.amazonaws.com", | |
| "api.maple.test/oidc/aws:sub": awsOidcSubject(connectionId), | |
| }) | |
| expect(statement.Condition).toEqual({ | |
| StringEquals: { | |
| "api.maple.test/oidc/aws:aud": "sts.amazonaws.com", | |
| "api.maple.test/oidc/aws:sub": awsOidcSubject(connectionId), | |
| }, | |
| }) |
🤖 Prompt to fix with an AI agent
In `packages/backend/src/services/integrations/aws/permissions.test.ts:47-50`: Trust assertion ignores condition operators other than `StringEquals`.
`expect(statement.Condition?.StringEquals).toEqual(...)` reads one operator, so a `StringLike` clause added beside it — `{"api.maple.test/oidc/aws:sub": "aws-connection:*"}` — lets another connection's token assume this role and the test still passes. `IamStatement.Condition` (`packages/domain/src/aws.ts:204`) admits any operator map.
Replace those lines with:
expect(statement.Condition).toEqual({
StringEquals: {
"api.maple.test/oidc/aws:aud": "sts.amazonaws.com",
"api.maple.test/oidc/aws:sub": awsOidcSubject(connectionId),
},
})
Verify the problem exists at that location before changing it, and keep the fix to those lines.
The AWS role a customer deploys is meant to be read-only, and nothing enforced that. Adding a module action like
iam:PassRoleor attaching a broad AWS managed policy would have shipped silently, sinceAWS_MODULE_SPECSgenerates the CloudFormation and the Terraform.Changes
aws/permissions.test.tsbuilds the setup plan with every module on and asserts:Get,List,Describe,Search,BatchGet), and there are no wildcardsViewOnlyAccess,SecurityAudit,*ReadOnly*)AssumeRoleWithWebIdentityfrom Maple's provider, for this connection'saudandsubAssumeRoleWithWebIdentityCloudTrail event, themaple-<id>session name, the expected cadence, and how to cut Maple off.Verification
iam:PassRoleto the cost module makes it fail withexpected [ 'iam:PassRole' ] to deeply equal [].packages/backendtypecheck and the CI effect lint config both pass on the changed files.🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.