feat(iam): allow PassRole to ECS tasks and EventBridge Scheduler (#151)
Some checks are pending
Deploy / deploy-management (push) Waiting to run
Deploy / deploy-external-dev (push) Waiting to run
Deploy / deploy-security (push) Waiting to run
Deploy / deploy-dev (push) Waiting to run
Deploy / deploy-prod (push) Waiting to run

A first apply of Fargate and Scheduler targets cannot create those service-linked attachments while PassRole is Lambda-only.
This commit is contained in:
Adam Moussa 2026-09-21 18:59:08 +00:00 • committed by GitHub
parent 960e4619b4
commit 7e41625e4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 23 additions and 8 deletions

View file

@ -527,7 +527,10 @@ projects `seahaven-mgmt`, `seahaven-prod`, `seahaven-dev`).
`CreateRole` / `PutRolePolicy` / `AttachRolePolicy` / `CreateRole` / `PutRolePolicy` / `AttachRolePolicy` /
`PutRolePermissionsBoundary` on `tf-managed` roles require `PutRolePermissionsBoundary` on `tf-managed` roles require
`iam:PermissionsBoundary` `StringLike` `policy/tf-managed/*` or `iam:PermissionsBoundary` `StringLike` `policy/tf-managed/*` or
`policy/seahaven-lambda-execution-boundary*`. `Null` false is not enough: `policy/seahaven-lambda-execution-boundary*`. `PassRole` on `tf-managed`
roles is allowed to `lambda.amazonaws.com`, `ecs-tasks.amazonaws.com`,
and `scheduler.amazonaws.com` so a first apply can create Fargate tasks
and EventBridge Scheduler targets. `Null` false is not enough:
it would accept `AdministratorAccess` as the ceiling. Must not mutate it would accept `AdministratorAccess` as the ceiling. Must not mutate
`githubdeploy-*`, `github-cfn-execution-role`, `cdk-hnb659fds-*`, `githubdeploy-*`, `github-cfn-execution-role`, `cdk-hnb659fds-*`,
`OrganizationAccountAccessRole`, `seahaven-*`. SCP `OrganizationAccountAccessRole`, `seahaven-*`. SCP

View file

@ -140,14 +140,14 @@ data "aws_iam_policy_document" "hcptf_scoped_iam" {
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/${local.stack_prefix}*"] resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/${local.stack_prefix}*"]
} }
statement { statement {
sid = "PassExecRolesToLambda" sid = "PassExecRolesToCompute"
effect = "Allow" effect = "Allow"
actions = ["iam:PassRole"] actions = ["iam:PassRole"]
resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/${local.stack_prefix}*"] resources = ["arn:aws:iam::${local.account_id}:role/tf-managed/${local.stack_prefix}*"]
condition { condition {
test = "StringEquals" test = "StringEquals"
variable = "iam:PassedToService" variable = "iam:PassedToService"
values = ["lambda.amazonaws.com"] values = ["lambda.amazonaws.com", "ecs-tasks.amazonaws.com", "scheduler.amazonaws.com"]
} }
} }
statement { statement {

View file

@ -86,13 +86,17 @@
"Resource": "arn:aws:iam::__ACCOUNT_ID__:role/hcptf-*" "Resource": "arn:aws:iam::__ACCOUNT_ID__:role/hcptf-*"
}, },
{ {
"Sid": "PassTfManagedRolesToLambda", "Sid": "PassTfManagedRolesToCompute",
"Effect": "Allow", "Effect": "Allow",
"Action": "iam:PassRole", "Action": "iam:PassRole",
"Resource": "arn:aws:iam::__ACCOUNT_ID__:role/tf-managed/*", "Resource": "arn:aws:iam::__ACCOUNT_ID__:role/tf-managed/*",
"Condition": { "Condition": {
"StringEquals": { "StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com" "iam:PassedToService": [
"lambda.amazonaws.com",
"ecs-tasks.amazonaws.com",
"scheduler.amazonaws.com"
]
} }
} }
}, },

View file

@ -66,7 +66,11 @@
"Resource": "arn:aws:iam::__ACCOUNT_ID__:role/tf-managed/__STACK_PREFIX__*", "Resource": "arn:aws:iam::__ACCOUNT_ID__:role/tf-managed/__STACK_PREFIX__*",
"Condition": { "Condition": {
"StringEquals": { "StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com" "iam:PassedToService": [
"lambda.amazonaws.com",
"ecs-tasks.amazonaws.com",
"scheduler.amazonaws.com"
]
} }
} }
}, },

View file

@ -1837,8 +1837,12 @@ Resources:
Resource: "*" Resource: "*"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# meal-order-manager-prod (PLAT-70) — HttpApi + 7 Lambdas + layer + DynamoDB # meal-order-manager-prod (PLAT-70, imported to the app workspace in PLAT-146).
# + S3 form/reports/artifacts + CloudFront/ACM/WAF + EventBridge + alarms. # Live plan/apply IAM is terraform/hcp_iam.tf in meal-order-manager (ECS/ALB
# as of PLAT-215). Do not mutate these CFN role policies; they are Retain
# leftovers. githubdeploy-meal-order-manager OIDC lives in that app module.
# ---------------------------------------------------------------------------
# Original shape: HttpApi + Lambdas + DynamoDB + S3 + CloudFront.
# Plan role: ViewOnly + plan-refresh sidecar. Apply role: HcptfIamManagement # Plan role: ViewOnly + plan-refresh sidecar. Apply role: HcptfIamManagement
# + prefix-scoped service wildcards (no enumerated Get* lists). # + prefix-scoped service wildcards (no enumerated Get* lists).
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------