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:*
I was able to replicate your behavior and resolved the issue with following
Resource
in IAM Policy.If you are planning to provide with revision then the resource should have
:*
in it or it has to exactly exactly match withtaskDefinition
.Let me know how it goes at your end!!.