从 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] 中引用了它。
我正在尝试部署一个基本的 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] 中引用了它。