为什么我的 Lambda 不允许在 ECS 资源上运行任务?

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

我刚刚创建了一个 AWS ECS 集群和任务定义,运行一切正常。我能够连接到服务器。任务在 Fargate 上 运行ning 和按需 运行s。我现在正在尝试创建一个 Lambda,它将 运行 RunTask 命令启动服务器。这是我在 Terraform 中的 Lambda 定义。

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}"
    }
  }
}

这是我的 Python 代码,位于 startup/lambda_handler.py 中,当我在 AWS 控制台中检查时,它作为函数代码正确显示。

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",
            },
        },
    )

当我 运行 使用空 JSON 对象作为参数在控制台中测试 Lambda 函数时,我希望看到我的 ECS 任务启动,但我得到了以下信息错误。

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"
  ]
}

请注意,在我的 Lambda 随附的 IAM 策略文档中,我的任务定义中确实有 ecs:RunTask 允许的声明。我不确定为什么这不给 Lambda 权限 运行 任务。

您传递给您的 lambda 容器的 TASK_ARN 是错误的。应该是 aws_ecs_task_definition.game.arn 而不是重复的 aws_ecs_cluster.game.arn.