meal-order-manager/terraform/iam.tf
Adam Moussa cc506f3c1f
Some checks are pending
Deploy API / Deploy API to dev (push) Waiting to run
Deploy API / Deploy API to prod (push) Waiting to run
feat(menu): publish the weekly menu from the job worker (PLAT-229) (#219)
* feat(menu): publish the weekly menu from the job worker

Monday publish parses the catalog embedded in the Redefine menu page and runs on the Fargate worker, so the GitHub Actions scrape cron can go away.

* fix(menu): address review feedback

Use the form deadline in the Monday Slack post, and compare that message exactly so CodeQL does not treat the test as URL sanitization.
2026-09-25 22:10:24 +00:00

203 lines
5.2 KiB
HCL

# Execution, task, and EventBridge Scheduler roles for the Fargate API.
data "aws_iam_policy_document" "ecs_assume" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "scheduler_assume" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["scheduler.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "ecs_task_boundary" {
source_policy_documents = [
data.aws_iam_policy_document.dynamodb_crud.json,
data.aws_iam_policy_document.ssm_read.json,
data.aws_iam_policy_document.slack_bot_secret_read.json,
]
statement {
sid = "ReportsWrite"
effect = "Allow"
actions = ["s3:PutObject", "s3:GetObject"]
resources = ["${aws_s3_bucket.reports.arn}/*"]
}
statement {
sid = "FormObjects"
effect = "Allow"
actions = ["s3:PutObject"]
resources = [
"${aws_s3_bucket.form.arn}/index.html",
"${aws_s3_bucket.form.arn}/archive/*.html",
]
}
statement {
sid = "InvalidateForm"
effect = "Allow"
actions = ["cloudfront:CreateInvalidation"]
resources = [aws_cloudfront_distribution.form.arn]
}
statement {
sid = "JobsQueue"
effect = "Allow"
actions = ["sqs:SendMessage", "sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes"]
resources = [aws_sqs_queue.jobs.arn]
}
dynamic "statement" {
for_each = var.checkcomponents_queue_arn == "" ? [] : [1]
content {
sid = "CheckcomponentsSend"
effect = "Allow"
actions = ["sqs:SendMessage"]
resources = [var.checkcomponents_queue_arn]
}
}
statement {
sid = "EcrAuth"
effect = "Allow"
actions = ["ecr:GetAuthorizationToken"]
resources = ["*"]
}
statement {
sid = "EcrPull"
effect = "Allow"
actions = [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer",
]
resources = [aws_ecr_repository.api.arn]
}
statement {
sid = "TaskLogs"
effect = "Allow"
actions = [
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:CreateLogGroup",
]
resources = [
aws_cloudwatch_log_group.api.arn,
"${aws_cloudwatch_log_group.api.arn}:*",
]
}
}
resource "aws_iam_policy" "ecs_task_boundary" {
name = "${local.project}-ecs-task-boundary"
path = "/tf-managed/"
description = "Permissions boundary for the meal-order-manager ECS task role"
policy = data.aws_iam_policy_document.ecs_task_boundary.json
}
resource "aws_iam_role" "ecs_execution" {
name = "${local.project}-ecs-exec"
path = "/tf-managed/"
assume_role_policy = data.aws_iam_policy_document.ecs_assume.json
permissions_boundary = aws_iam_policy.ecs_task_boundary.arn
}
resource "aws_iam_role_policy_attachment" "ecs_execution" {
role = aws_iam_role.ecs_execution.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
data "aws_iam_policy_document" "dynamodb_crud" {
statement {
sid = "OrdersTableCrud"
effect = "Allow"
actions = [
"dynamodb:BatchGetItem",
"dynamodb:BatchWriteItem",
"dynamodb:ConditionCheckItem",
"dynamodb:DeleteItem",
"dynamodb:DescribeTable",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:UpdateItem",
]
resources = [
aws_dynamodb_table.orders.arn,
"${aws_dynamodb_table.orders.arn}/index/*",
]
}
}
data "aws_iam_policy_document" "ssm_read" {
statement {
sid = "ReadProjectParameters"
effect = "Allow"
actions = ["ssm:GetParameter"]
resources = [local.ssm_parameter_arn_wildcard]
}
}
data "aws_iam_policy_document" "slack_bot_secret_read" {
statement {
sid = "ReadSlackBotToken"
effect = "Allow"
actions = ["secretsmanager:GetSecretValue"]
resources = [var.slack_bot_secret_arn]
}
}
resource "aws_iam_role" "ecs_task" {
name = "${local.project}-api"
path = "/tf-managed/"
assume_role_policy = data.aws_iam_policy_document.ecs_assume.json
permissions_boundary = aws_iam_policy.ecs_task_boundary.arn
}
resource "aws_iam_role_policy" "ecs_task" {
name = "api-runtime"
role = aws_iam_role.ecs_task.id
policy = data.aws_iam_policy_document.ecs_task_boundary.json
}
resource "aws_iam_role" "scheduler" {
name = "${local.project}-scheduler"
path = "/tf-managed/"
assume_role_policy = data.aws_iam_policy_document.scheduler_assume.json
permissions_boundary = aws_iam_policy.ecs_task_boundary.arn
}
data "aws_iam_policy_document" "scheduler" {
statement {
sid = "SendJobs"
effect = "Allow"
actions = ["sqs:SendMessage"]
resources = [aws_sqs_queue.jobs.arn]
}
}
resource "aws_iam_role_policy" "scheduler" {
name = "enqueue-jobs"
role = aws_iam_role.scheduler.id
policy = data.aws_iam_policy_document.scheduler.json
}