Home > Back-end >  IAM role to allow command execution on AWS ECS containers
IAM role to allow command execution on AWS ECS containers

Time:02-24

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.

  • Related