Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boto3 lambda call to run ECS task requires hardcoding in a revision number?

Long story short, I don't want to have to hardcode in ECS task definition revision numbers for tasks into my lambda source codes. It's essentially toil updating my source code each time I have an updated task definition. In the boto3 documentation for ECS run_task(), it clearly states

taskDefinition (string) -- [REQUIRED]

The family and revision (family:revision ) or full ARN of the task definition to run. If a revision is not specified, the latest ACTIVE revision is used.

However, I am finding that if I define the taskDefinition parameter in client.run_task() with no specific revision number, I get a permission error:

An error occurred (AccessDeniedException) when calling the RunTask operation: User: arn:aws:sts::MY_ACCOUNT_ID:assumed-role/my-lambda-role/trigger-ecs-task is not authorized to perform: ecs:RunTask on resource: arn:aws:ecs:MY_REGION:MY_ACCOUNT_ID:task-definition/an-important-task

If I switch my definition to an-important-task:LATEST or an-important-task:*, I get another error:

...is not authorized to perform: ecs:RunTask on resource: *

This is strange, because it appears contrary to what the documentation states- when I include a revision number, like an-important-task:5, the lambda triggers perfectly. In my lambda function, I simply invoke my ECS task:

def lambda_handler(event, context):
    client = boto3.client('ecs')
    print("Running task.")
    response = client.run_task(
        cluster='my-cluster', 
        launchType='FARGATE',
        taskDefinition='an-important-task',  # <-- notice no revision number
        count=1,
        platformVersion='LATEST',
        networkConfiguration={
            'awsvpcConfiguration': {
                'subnets': [
                    'subnet-1',
                    'subnet-2'
                ],
                'assignPublicIp': 'DISABLED'
            }
        })
    print("Finished invoking task.")

In my Terraform definition, I've attached the necessary policies to my role:

resource "aws_lambda_function" "trigger-ecs-task" {
  function_name = "trigger-ecs-task"
  handler = "my-lambda-function.lambda_handler"
  role = "${aws_iam_role.lambda.arn}"
  runtime = "python3.6"
  # other stuff related to how I store my source code for the lambda
}

My role definition, and attaching the permissions to run ECS tasks:

resource "aws_iam_role" "lambda" {
  name = "my-lambda-ecs-role"
  assume_role_policy = "${data.aws_iam_policy_document.lambda-assume-role.json}"
}

data "aws_iam_policy_document" "lambda-assume-role" {
  statement {
    actions = [
      "sts:AssumeRole"]

    principals {
      type = "Service"
      identifiers = [
        "lambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_policy" "run-ecs-policy" {
  name = "run-ecs-task-policy"
  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ecs:RunTask",
            "Resource": "arn:aws:ecs:MY_REGION:MY_ACCOUNT_ID:task-definition/an-important-task:*"
        },
        {
            "Sid": "Stmt1512361993201",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::************:role/${data.aws_iam_role.ecs-task-execution-role.name}"
            ]
        }
    ]
}
EOF
}

I attach the policy below:

resource "aws_iam_role_policy_attachment" "service-role-attach" {
  role = "${aws_iam_role.lambda.name}"
  policy_arn = "${aws_iam_policy.run-ecs-policy.arn}"
}

Why is AWS refusing to run my task if I don't specify a specific revision? In my policy definition, I am clearly giving permission to runTask on all revisions of the resource:

arn:aws:ecs:MY_REGION:MY_ACCOUNT_ID:task-definition/an-important-task:*
like image 974
Yu Chen Avatar asked Jan 20 '19 22:01

Yu Chen


People also ask

Can Lambda invoke ECS task?

"You can invoke Lambda functions directly with the Lambda console, the Lambda API, the AWS SDK, the AWS CLI, and AWS toolkits." So you'll have to decide which method is going to work best for your ECS tasks. You will need to set the correct permissions so that your ECS will be able to invoke the Lambda function.

What are the mandatory parameters in the task definition in ECS?

The family and container definitions are required in a task definition. In contrast, task role, network mode, volumes, task placement constraints, and launch type are optional. You can use these parameters in a JSON file to configure your task definition.

Can an ECS service have multiple task definitions?

Your application can span multiple task definitions. You can do this by combining related containers into their own task definitions, each representing a single component.


1 Answers

I was able to replicate your behavior and resolved the issue with following Resource in IAM Policy.

{
    "Sid": "VisualEditor1",
    "Effect": "Allow",
    "Action": "ecs:RunTask",
    "Resource": "arn:aws:ecs:MY_REGION:MY_ACCOUNT_ID:task-definition/an-important-task"
}

If you are planning to provide with revision then the resource should have :* in it or it has to exactly exactly match with taskDefinition.

Let me know how it goes at your end!!.

like image 166
Imran Avatar answered Sep 28 '22 04:09

Imran