从 Terraform 中的 API 网关触发 Lambda

Trigger Lambda from API Gateway in Terraform

我正在尝试部署一个基本的 API,其中包含作为主要端点的 lambda 函数和作为此函数代理的 API 网关。通过以下配置我可以构建基础设施,但我无法设置通过 IaC 触发 lambda 函数,我必须转到 AWS 控制台才能手动设置触发器。

resource "aws_lambda_function" "main_endpoint_function" {
  function_name = "main_endpoint_function"


  s3_bucket = module.s3.function_bucket_name
  s3_key = "index.zip"


  handler = "index.handler"
  runtime = var.runtime_handler

  role = aws_iam_role.lambda_role.arn
}

resource "aws_iam_role" "lambda_role" {
  name = "role_lambda_test"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
//lambda has to be manually triggered from api gateway
resource "aws_api_gateway_rest_api" "apiLambda" {
  name        = "myAPI"
  description = "terraform test"
}

resource "aws_api_gateway_resource" "proxy" {
   rest_api_id = aws_api_gateway_rest_api.apiLambda.id
   parent_id   = aws_api_gateway_rest_api.apiLambda.root_resource_id
   path_part   = "{proxy+}"
}

resource "aws_api_gateway_method" "proxyMethod" {
   rest_api_id   = aws_api_gateway_rest_api.apiLambda.id
   resource_id   = aws_api_gateway_resource.proxy.id
   http_method   = "ANY"
   authorization = "NONE"
}

resource "aws_api_gateway_integration" "lambda" {
   rest_api_id = aws_api_gateway_rest_api.apiLambda.id
   resource_id = aws_api_gateway_method.proxyMethod.resource_id
   http_method = aws_api_gateway_method.proxyMethod.http_method

   integration_http_method = "POST"
   type                    = "AWS_PROXY"
   uri                     = aws_lambda_function.main_endpoint_function.invoke_arn
}

resource "aws_api_gateway_method" "proxy_root" {
   rest_api_id   = aws_api_gateway_rest_api.apiLambda.id
   resource_id   = aws_api_gateway_rest_api.apiLambda.root_resource_id
   http_method   = "ANY"
   authorization = "NONE"
}

resource "aws_api_gateway_integration" "lambda_root" {
   rest_api_id = aws_api_gateway_rest_api.apiLambda.id
   resource_id = aws_api_gateway_method.proxy_root.resource_id
   http_method = aws_api_gateway_method.proxy_root.http_method

   integration_http_method = "POST"
   type                    = "AWS_PROXY"
   uri                     = aws_lambda_function.main_endpoint_function.invoke_arn
}

resource "aws_api_gateway_deployment" "apideploy" {
   depends_on = [
     aws_api_gateway_integration.lambda,
     aws_api_gateway_integration.lambda_root,
   ]

   rest_api_id = aws_api_gateway_rest_api.apiLambda.id
   stage_name  = "test"
}


如果没有通过控制台手动设置触发器,我会收到内部服务器错误。具有正确的触发功能。也许我的配置有问题?

更新::

为 Lambda 和 API 网关添加权限资源后,我还创建了 aws_api_gateway_method_response 和 aws_api_gateway_integration_response。第一个 运行 错误,第二个 运行 完成。我尝试添加明确的暗示,但他们没有解决问题..

resource "aws_api_gateway_method_response" "response_200" {
  rest_api_id = aws_api_gateway_rest_api.apiLambda.id
  resource_id = aws_api_gateway_resource.proxy.id
  http_method = aws_api_gateway_method.proxy_root.http_method
  status_code = "200"
  depends_on = [
    aws_api_gateway_rest_api.apiLambda,
    aws_api_gateway_resource.proxy,
    aws_api_gateway_method.proxy_root
  ]
}

resource "aws_api_gateway_integration_response" "MyDemoIntegrationResponse" {
  rest_api_id = aws_api_gateway_rest_api.apiLambda.id
  resource_id = aws_api_gateway_resource.proxy.id
  http_method = aws_api_gateway_method.proxy_root.http_method
  status_code = aws_api_gateway_method_response.response_200.status_code
  depends_on = [
    aws_api_gateway_rest_api.apiLambda,
    aws_api_gateway_resource.proxy,
    aws_api_gateway_method.proxy_root,
    aws_api_gateway_method_response.response_200
  ]

  # Transforms the backend JSON response to XML
  response_templates = {
    "application/xml" = <<EOF
#set($inputRoot = $input.path('$'))
<?xml version="1.0" encoding="UTF-8"?>
<message>
    $inputRoot.body
</message>
EOF
  }
}

错误是: │ 错误:创建 API 网关方法响应时出错:NotFoundException:指定的方法标识符无效 │ │ aws_api_gateway_method_response.response_200, │ 在 main.tf 第 130 行,在资源“aws_api_gateway_method_response”“response_200”中: │ 130: 资源 "aws_api_gateway_method_response" "response_200" {

您似乎缺少 aws_lambda_permission 资源 [1]。在您的情况下,您需要添加以下内容(类似于参考中的示例):

resource "aws_lambda_permission" "apigw_lambda" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.main_endpoint_function.function_name
  principal     = "apigateway.amazonaws.com"

  source_arn = "arn:aws:execute-api:${var.myregion}:${var.accountId}:${aws_api_gateway_rest_api.apiLambda.id}/*/${aws_api_gateway_method.proxyMethod.http_method}${aws_api_gateway_resource.proxy.path}"
}

由于我不知道您使用的是哪个区域和帐户(我不需要知道),您只需将 var.myregion 替换为 API 网关区域,然后var.accountId 使用创建 API 网关的 AWS 帐户。您可以通过使用 data 来源来实现。从理论上讲,您也可以省略 source_arn 中的方法引用并使用类似的内容:

source_arn = "arn:aws:execute-api:${var.myregion}:${var.accountId}:${aws_api_gateway_rest_api.apiLambda.id}/*/*/*"

我已经从代码中删除了第二个引用,现在在 [2] 中引用了它。


[1] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_integration#lambda-integration

[2]http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html