Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is my Lambda not allowed to RunTask on ECS resource?

I just created an AWS ECS cluster and task definition and ran it all just fine. I was able to connect to the server. The task is running on Fargate and runs on demand. I am now attempting to create a Lambda that will run the RunTask command to start the server. Here is my Lambda definition in Terraform.

data "aws_iam_policy_document" "startup_lambda_assume_role" {
  statement {
    effect = "Allow"
    actions = ["sts:AssumeRole"]
    principals {
      type = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }   
  }
}

resource "aws_iam_role" "startup_lambda" {
  name = "report_lambda_role"
  assume_role_policy = data.aws_iam_policy_document.startup_lambda_assume_role.json
}

resource "aws_cloudwatch_log_group" "startup_lambda" {
  name = "/aws/lambda/${aws_lambda_function.startup.function_name}"
  retention_in_days = 14
}

data "aws_iam_policy_document" "startup_lambda" {
  statement {
    effect = "Allow"
    actions = [
      "logs:CreateLogStream",
      "logs:CreateLogGroup",
    ]
    resources = [aws_cloudwatch_log_group.startup_lambda.arn]
  }

  statement {
    effect = "Allow"
    actions = ["logs:PutLogEvents"]
    resources = ["${aws_cloudwatch_log_group.startup_lambda.arn}:*"]
  }

  statement {
    effect = "Allow"
    actions = [
      "ecs:RunTask",
    ]
    resources = [
      aws_ecs_task_definition.game.arn
    ]
  }

  statement {
    effect = "Allow"
    actions = [
      "iam:PassRole",
    ]
    resources = [
      aws_iam_role.ecs_task_execution.arn,
      aws_iam_role.game_task.arn
    ]
  }
}

resource "aws_iam_role_policy" "startup_lambda" {
  name = "startup_lambda_policy"
  policy = data.aws_iam_policy_document.startup_lambda.json
  role = aws_iam_role.startup_lambda.id
}

data "archive_file" "startup_lambda" {
  type = "zip"
  source_file = "${path.module}/startup/lambda_handler.py"
  output_path = "${path.module}/startup/lambda_handler.zip"
}

resource "aws_lambda_function" "startup" {
  function_name = "startup_lambda"
  filename = data.archive_file.startup_lambda.output_path
  handler = "lambda_handler.handler"
  source_code_hash =  data.archive_file.startup_lambda.output_base64sha256
  runtime = "python3.8"
  role = aws_iam_role.startup_lambda.arn
  environment {
    variables = {
      CLUSTER_ARN = aws_ecs_cluster.game.arn,
      TASK_ARN = aws_ecs_cluster.game.arn,
      SUBNET_IDS = "${aws_subnet.subnet_a.id},${aws_subnet.subnet_b.id},${aws_subnet.subnet_c.id}"
    }
  }
}

This is my Python code located in startup/lambda_handler.py which does appear properly as the code for the function when I checked in the AWS console.

import os
import boto3

def handler (event, callback):
    client = boto3.client("ecs")
    response = client.run_task(
        cluster = os.getenv("CLUSTER_ARN"),
        taskDefinition = os.getenv("TASK_ARN"),
        launchType = "FARGATE",
        count = 1,
        networkConfiguration = {
            "awsvpcConfiguration": {
                "subnets": os.getenv("SUBNET_IDS", "").split(","),
                "assignPublicIp": "ENABLED",
            },
        },
    )

When I run a test of the Lambda function in the console using an empty JSON object as an argument, I expect to see my ECS task spin up, but instead I get the following error.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Response
{
  "errorMessage": "An error occurred (AccessDeniedException) when calling the RunTask operation: User: arn:aws:sts::703606424838:assumed-role/report_lambda_role/startup_lambda is not authorized to perform: ecs:RunTask on resource: * because no identity-based policy allows the ecs:RunTask action",
  "errorType": "AccessDeniedException",
  "stackTrace": [
    "  File \"/var/task/lambda_handler.py\", line 6, in handler\n    response = client.run_task(\n",
    "  File \"/var/runtime/botocore/client.py\", line 386, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n",
    "  File \"/var/runtime/botocore/client.py\", line 705, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"
  ]
}

Notice that I do have a statement for ecs:RunTask allowed on my task defintion in the IAM policy document attached to my Lambda. I am not sure why this doesn’t give the Lambda permission to run the task.

>Solution :

The TASK_ARN you pass to your lambda container is wrong. Should probably be aws_ecs_task_definition.game.arn instead of a duplicate aws_ecs_cluster.game.arn.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading