fix(infra): split hcptf apply policy and omit empty queue ARNs (PLAT-216) (#261)

The combined services inline policy exceeded 10KB, and an empty
checkcomponents ARN made CreatePolicy reject the Lambda boundary in dev.
This commit is contained in:
Adam Moussa 2026-09-21 19:46:36 +00:00 • committed by GitHub
parent 593cab66ef
commit d49c4bb4f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 59 additions and 35 deletions

View file

@ -562,6 +562,9 @@ data "aws_iam_policy_document" "hcptf_apply_services" {
resources = ["*"] resources = ["*"]
} }
}
data "aws_iam_policy_document" "hcptf_apply_ecs" {
statement { statement {
sid = "EcsWorkload" sid = "EcsWorkload"
effect = "Allow" effect = "Allow"
@ -1083,6 +1086,12 @@ resource "aws_iam_role_policy" "hcptf_apply_services" {
policy = data.aws_iam_policy_document.hcptf_apply_services.json policy = data.aws_iam_policy_document.hcptf_apply_services.json
} }
resource "aws_iam_role_policy" "hcptf_apply_ecs" {
name = "afterhours-shift-manager-ecs"
role = aws_iam_role.hcptf_apply.id
policy = data.aws_iam_policy_document.hcptf_apply_ecs.json
}
resource "aws_iam_role_policy" "hcptf_plan_refresh" { resource "aws_iam_role_policy" "hcptf_plan_refresh" {
name = "afterhours-shift-manager-plan-refresh" name = "afterhours-shift-manager-plan-refresh"
role = aws_iam_role.hcptf_plan.id role = aws_iam_role.hcptf_plan.id

View file

@ -96,11 +96,14 @@ data "aws_iam_policy_document" "ecs_task_boundary" {
resources = [aws_sqs_queue.jobs.arn] resources = [aws_sqs_queue.jobs.arn]
} }
statement { dynamic "statement" {
for_each = var.checkcomponents_queue_arn == "" ? [] : [1]
content {
sid = "CheckcomponentsSend" sid = "CheckcomponentsSend"
effect = "Allow" effect = "Allow"
actions = ["sqs:SendMessage"] actions = ["sqs:SendMessage"]
resources = compact([var.checkcomponents_queue_arn]) resources = [var.checkcomponents_queue_arn]
}
} }
statement { statement {

View file

@ -57,7 +57,8 @@ locals {
condition = null condition = null
}, },
] ]
weekly_post = [ weekly_post = concat(
[
{ {
sid = "DdbCrud" sid = "DdbCrud"
actions = ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", "dynamodb:DescribeTable", "dynamodb:ConditionCheckItem"] actions = ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", "dynamodb:DescribeTable", "dynamodb:ConditionCheckItem"]
@ -70,13 +71,16 @@ locals {
resources = ["arn:aws:secretsmanager:${var.aws_region}:${local.account_id}:secret:afterhours-shift-manager/slack-bot-token-*"] resources = ["arn:aws:secretsmanager:${var.aws_region}:${local.account_id}:secret:afterhours-shift-manager/slack-bot-token-*"]
condition = null condition = null
}, },
],
var.checkcomponents_queue_arn == "" ? [] : [
{ {
sid = "CheckcomponentsSend" sid = "CheckcomponentsSend"
actions = ["sqs:SendMessage"] actions = ["sqs:SendMessage"]
resources = [var.checkcomponents_queue_arn] resources = [var.checkcomponents_queue_arn]
condition = null condition = null
}, },
] ],
),
roster_sync = [ roster_sync = [
{ {
sid = "DdbCrud" sid = "DdbCrud"

View file

@ -121,7 +121,9 @@ data "aws_iam_policy_document" "lambda_boundary" {
] ]
} }
statement { dynamic "statement" {
for_each = var.checkcomponents_queue_arn == "" ? [] : [1]
content {
sid = "AfterhoursCheckcomponentsSend" sid = "AfterhoursCheckcomponentsSend"
effect = "Allow" effect = "Allow"
actions = [ actions = [
@ -132,6 +134,7 @@ data "aws_iam_policy_document" "lambda_boundary" {
] ]
} }
} }
}
resource "aws_iam_policy" "lambda_boundary" { resource "aws_iam_policy" "lambda_boundary" {
name = "afterhours-shift-manager-lambda-boundary" name = "afterhours-shift-manager-lambda-boundary"

View file

@ -12,7 +12,10 @@ resource "aws_vpc" "this" {
} }
# First apply updates the live hcptf apply role before CreateVpc. # First apply updates the live hcptf apply role before CreateVpc.
depends_on = [aws_iam_role_policy.hcptf_apply_services] depends_on = [
aws_iam_role_policy.hcptf_apply_services,
aws_iam_role_policy.hcptf_apply_ecs,
]
} }
resource "aws_internet_gateway" "this" { resource "aws_internet_gateway" "this" {

View file

@ -81,6 +81,8 @@ def test_stack_owns_a_vpc_instead_of_looking_up_default():
assert "aws_subnet.public[*].id" in ecs assert "aws_subnet.public[*].id" in ecs
assert "ec2:CreateVpc" in HCP_IAM assert "ec2:CreateVpc" in HCP_IAM
assert "sid = \"RefreshVpc\"" in HCP_IAM assert "sid = \"RefreshVpc\"" in HCP_IAM
assert "afterhours-shift-manager-ecs" in HCP_IAM
assert "hcptf_apply_ecs" in HCP_IAM
def test_deploy_api_workflow_exists(): def test_deploy_api_workflow_exists():