I am new to both terraform, and AWS. I am trying to set enable_execute_command=true
on an existing fargate service, with the role and cluster/service/task defined liked this:
data "aws_iam_policy_document" "ecs_task_execution_role_base" {
version = "2012-10-17"
statement {
sid = ""
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "ecs_exec_policy" {
name = "ecs_exec_policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
]
Effect = "Allow"
Resource = "*"
},
]
})
}
resource "aws_iam_role" "ecs_task_execution_role" {
name = var.ecs_task_execution_role_name
assume_role_policy = data.aws_iam_policy_document.ecs_task_execution_role_base.json
managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", aws_iam_policy.ecs_exec_policy.arn]
resource "aws_ecs_cluster" "main" {
name = "backendcluster"
}
data "template_file" "backendapp" {
template = file("./templates/ecs/backend_app.json.tpl")
vars = {
server_image = var.server_image
celery_image = var.celery_image
app_port = var.app_port
fargate_cpu = var.fargate_cpu
fargate_memory = var.fargate_memory
aws_region = var.aws_region
database_host = aws_db_instance.default.address
database_port = aws_db_instance.default.port
redis_host = aws_elasticache_cluster.default.cache_nodes.0.address
redis_port = aws_elasticache_cluster.default.cache_nodes.0.port
}
}
resource "aws_ecs_task_definition" "app" {
family = "backend-app-task"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = var.fargate_cpu
memory = var.fargate_memory
container_definitions = data.template_file.backendapp.rendered
}
resource "aws_ecs_service" "main" {
name = "backendservice"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = var.app_count
launch_type = "FARGATE"
enable_execute_command = true
network_configuration {
security_groups = [aws_security_group.ecs_tasks.id]
subnets = aws_subnet.private.*.id
assign_public_ip = true
}
load_balancer {
target_group_arn = aws_alb_target_group.app.id
container_name = "server"
container_port = var.app_port
}
depends_on = [aws_alb_listener.backend]
}
Running terraform apply
gives:
Error: error updating ECS Service (arn:aws:ecs:eu-west-2:00000000:service/backendcluster/backendservice): InvalidParameterException: The service couldn't be updated because a valid taskRoleArn is not being used. Specify a valid task role in your task definition and try again.
CodePudding user response:
In your resource "aws_ecs_task_definition" "app"
you have specified an execution_role_arn
, but you have not specified a task_role_arn
. That's really what the error is saying, that you need to provide a task role ARN.
The execution role gives the ECS service permission to do things like read an image from an ECR repository, and lookup secrets in SecretsManager that it needs to inject into the containers it creates.
The task role gives the software running inside the ECS task/container permission to access AWS resources. The command execution permissions need to be assigned to the task role, not the execution role.
At a minimum you could try adding:
task_role_arn = aws_iam_role.ecs_task_execution_role.arn
But following the principal of least privilege would dictate you separate those roles into separate IAM roles with distinct privileges.