Background
The plugin auto-generates IAM execution role permissions based on the service-integration ARNs in a state machine's definition (see `lib/deploy/stepFunctions/iamStrategies/`). For most services this produces 1–3 statements of narrowly-scoped actions, which works well as a default.
For Athena specifically (added in #450), the auto-generated role mirrors AWS's documented template and includes ~30 actions across four statements (Athena + S3 + Glue + Lake Formation), with broad resources like `arn:aws:s3:::` and `glue:database/`. This is correct per AWS docs — Athena uses the caller's IAM identity for catalog and storage access — but the breadth makes scope-down harder than it should be.
The gap
There is currently no clean way for a user to subtract from the auto-generated permissions:
- `iamRoleStatements` adds statements alongside the auto-generated ones; it cannot narrow them.
- `role:` replaces the entire role (and turns off auto-generation), which is an all-or-nothing escape hatch — the user loses auto-generation for every service they use, not just Athena.
A user who wants Athena to work but needs `s3:GetObject` scoped to `arn:aws:s3:::my-data-lake/` instead of `arn:aws:s3:::` has to either copy the full role themselves (losing the plugin's value) or accept overpermissive grants.
Proposed solutions
A few shapes worth discussing:
A) Boolean opt-out per state machine
```yaml
stepFunctions:
stateMachines:
myMachine:
autoIamRole: false # default true; when false, no auto-generated statements at all
iamRoleStatements:
- Effect: Allow
Action: [athena:startQueryExecution, athena:getDataCatalog]
Resource: arn:aws:athena:us-east-1:123456789012:workgroup/analytics
# ...user-provided narrowly-scoped statements
```
Simplest. Combines with `iamRoleStatements` to give users a fully manual role without having to use `role:` (which also disables logging config defaults, etc.).
B) Per-service opt-out
```yaml
autoIamRole:
athena: false
s3: false
```
Finer control — the user keeps auto-IAM for Lambda invokes, Step Functions startExecution, etc., but takes manual control for Athena. More moving parts.
C) Override-mode `iamRoleStatements`
A flag that changes `iamRoleStatements` from additive to replacing the auto-generated set. Conceptually similar to (A) but reuses an existing field.
Recommendation
(A) feels right for v1: minimum surface area, addresses the actual user need, easy to layer (B) on later if demand exists. Default stays `true` — backwards-compatible.
Out of scope
- Narrowing the defaults themselves. AWS docs prescribe the broad set; we follow AWS docs.
- Changing the semantics of `iamRoleStatements`. Additive behaviour is established and changing it would be a breaking change.
Related: when to split rather than narrow
Scope-down is one mitigation; splitting the workload across multiple Serverless services with Serverless Compose is another. CloudFormation has hard limits on policy/template size, and a single state machine that touches Athena + Glue + DynamoDB + Lambda + S3 + Step Functions can drive the auto-generated role past those limits even with this opt-out.
When the issue is role too large rather than role too broad, the correct fix is often:
- One Serverless service per logical workload (each gets its own CF stack and its own state-machine role)
- An
osls-compose.yml orchestrating them so deploys stay coordinated
This issue's opt-out flag complements that pattern — use compose to split when you've outgrown a single stack, and autoIamRole: false to take manual control of any individual machine that still needs scope-down. The README should mention both options in the IAM section.
Background
The plugin auto-generates IAM execution role permissions based on the service-integration ARNs in a state machine's definition (see `lib/deploy/stepFunctions/iamStrategies/`). For most services this produces 1–3 statements of narrowly-scoped actions, which works well as a default.
For Athena specifically (added in #450), the auto-generated role mirrors AWS's documented template and includes ~30 actions across four statements (Athena + S3 + Glue + Lake Formation), with broad resources like `arn:aws:s3:::` and `glue:database/`. This is correct per AWS docs — Athena uses the caller's IAM identity for catalog and storage access — but the breadth makes scope-down harder than it should be.
The gap
There is currently no clean way for a user to subtract from the auto-generated permissions:
A user who wants Athena to work but needs `s3:GetObject` scoped to `arn:aws:s3:::my-data-lake/` instead of `arn:aws:s3:::` has to either copy the full role themselves (losing the plugin's value) or accept overpermissive grants.
Proposed solutions
A few shapes worth discussing:
A) Boolean opt-out per state machine
```yaml
stepFunctions:
stateMachines:
myMachine:
autoIamRole: false # default true; when false, no auto-generated statements at all
iamRoleStatements:
- Effect: Allow
Action: [athena:startQueryExecution, athena:getDataCatalog]
Resource: arn:aws:athena:us-east-1:123456789012:workgroup/analytics
# ...user-provided narrowly-scoped statements
```
Simplest. Combines with `iamRoleStatements` to give users a fully manual role without having to use `role:` (which also disables logging config defaults, etc.).
B) Per-service opt-out
```yaml
autoIamRole:
athena: false
s3: false
```
Finer control — the user keeps auto-IAM for Lambda invokes, Step Functions startExecution, etc., but takes manual control for Athena. More moving parts.
C) Override-mode `iamRoleStatements`
A flag that changes `iamRoleStatements` from additive to replacing the auto-generated set. Conceptually similar to (A) but reuses an existing field.
Recommendation
(A) feels right for v1: minimum surface area, addresses the actual user need, easy to layer (B) on later if demand exists. Default stays `true` — backwards-compatible.
Out of scope
Related: when to split rather than narrow
Scope-down is one mitigation; splitting the workload across multiple Serverless services with Serverless Compose is another. CloudFormation has hard limits on policy/template size, and a single state machine that touches Athena + Glue + DynamoDB + Lambda + S3 + Step Functions can drive the auto-generated role past those limits even with this opt-out.
When the issue is role too large rather than role too broad, the correct fix is often:
osls-compose.ymlorchestrating them so deploys stay coordinatedThis issue's opt-out flag complements that pattern — use compose to split when you've outgrown a single stack, and
autoIamRole: falseto take manual control of any individual machine that still needs scope-down. The README should mention both options in the IAM section.