So I have been trying to solve this issue for a couple of evenings by now, and I still feel that there is not really any progress.
所以我已经试着解决这个问题好几个晚上了,但我仍然觉得没有任何进展。
So what I'm trying to do, is to set up a lambda authorizer for my API gateway.
因此,我要做的是为我的API网关设置一个lambda授权器。
I have attached my authorizer both with Terraform and through the console without any luck. For my Terraform configuration, I have something like this:
我已经用Terraform和通过控制台附加了我的授权者,但没有任何运气。对于我的Terraform配置,我的配置如下所示:
resource "aws_apigatewayv2_authorizer" "lambda_authorizer" {
api_id = aws_apigatewayv2_api.api.id
authorizer_type = "REQUEST"
identity_sources = ["$request.header.Authorization"]
name = "lambda_authorizer-${var.app_name}-${var.environment}"
authorizer_payload_format_version = "2.0"
authorizer_result_ttl_in_seconds = 0
enable_simple_responses = true
authorizer_uri = aws_lambda_function.authorizer.invoke_arn
}
resource "aws_lambda_permission" "my_authorizer_lambda_permission" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.authorizer.function_name
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:${aws_apigatewayv2_api.api.id}/*/*/*"
}
resource "aws_apigatewayv2_integration" "integration" {
api_id = aws_apigatewayv2_api.api.id
integration_type = "HTTP_PROXY"
integration_uri = aws_service_discovery_service.ecs-discovery-service.arn
integration_method = "ANY"
connection_type = "VPC_LINK"
connection_id = aws_apigatewayv2_vpc_link.vpc_link.id
payload_format_version = "1.0"
}
resource "aws_apigatewayv2_route" "route" {
api_id = aws_apigatewayv2_api.api.id
route_key = "ANY /{proxy+}"
target = "integrations/${aws_apigatewayv2_integration.integration.id}"
authorization_type = "CUSTOM"
authorizer_id = aws_apigatewayv2_authorizer.lambda_authorizer.id
depends_on = [aws_apigatewayv2_authorizer.lambda_authorizer]
}
resource "aws_apigatewayv2_stage" "stage" {
api_id = aws_apigatewayv2_api.api.id
name = "${var.app_name}-${var.environment}"
auto_deploy = true
default_route_settings {
logging_level = "INFO"
detailed_metrics_enabled = true
data_trace_enabled = true
throttling_rate_limit = 20 #Amount of requests per second
throttling_burst_limit = 50 #Concurrent requests
}
access_log_settings {
destination_arn = aws_cloudwatch_log_group.api_gw_access_log_group.arn
format = jsonencode({
requestId = "$context.requestId"
sourceIp = "$context.identity.sourceIp"
requestTime = "$context.requestTime"
protocol = "$context.protocol"
httpMethod = "$context.httpMethod"
resourcePath = "$context.resourcePath"
routeKey = "$context.routeKey"
status = "$context.status"
responseLength = "$context.responseLength"
integrationErrorMessage = "$context.integrationErrorMessage"
}
)
}
}
Above, I left unnecessary stuff out. But the gist is, that the deployment deploys as it should and the authorizer gets attached to my API Gateway, however I encounter the following error for both creating with Terraform and AWS console: (this scr shot is for when i tried with the console with a different source_arn)
上面,我省略了不必要的东西。但要点是,部署按其应有的方式进行部署,授权程序连接到我的API Gateway,但是我在使用Terraform和AWS控制台创建时遇到了以下错误:(此SCR快照适用于我尝试使用不同SOURCE_ARN的控制台时)
I have a hard time understanding whats actually going on here, since there is a route with path /* .....
我很难理解这里到底发生了什么,因为有一个路径为/* 的路由。
I tried experimenting with this and figured out, that when I create a custom lambda based endpoint for the same function (not authorizer, but just an API endpoint), the error dissapears - but the problem obviously still persists... Super strange!
我尝试这样做,结果发现,当我为同一函数(不是授权器,而只是一个API端点)创建一个基于lambda的自定义端点时,错误消失了--但问题显然仍然存在……超级奇怪!
In continuation, I can see that the requests hits my API gateway, but nothing is printed in the Lambda logs - Which I guess is why im getting a 403 status code returned (e.g. default return if Lambda Authorizer doesn't return a policy)
接下来,我可以看到请求到达了我的API网关,但Lambda日志中没有打印任何内容--我猜这就是为什么我会得到返回403状态代码的原因(例如,如果Lambda Authorizer不返回策略,则默认返回)
Anyway, I'm stuck here without any further progress. Please help me out.
总之,我被困在这里没有任何进一步的进展。请帮帮我
Update
更新
I tried to change the source_arn to:
我尝试将SOURCE_ARN更改为:
source_arn = "${aws_apigatewayv2_api.api.execution_arn}/authorizers/${aws_apigatewayv2_authorizer.lambda_authorizer.id}"
SOURCE_ARN=“${aws_apigatewayv2_api.api.execution_arn}/authorizers/${aws_apigatewayv2_authorizer.lambda_authorizer.id}”
Still no luck.
还是不走运。
Update 9/9
更新9/9
So I tried changing the source_arn
to account for different lambda versions:
因此,我尝试更改SOURCE_ARN以适应不同的lambda版本:
source_arn = "${aws_apigatewayv2_api.api.execution_arn}/authorizers/${aws_apigatewayv2_authorizer.lambda_authorizer.id}/*/*"
SOURCE_ARN=“${aws_apigatewayv2_api.api.execution_arn}/authorizers/${aws_apigatewayv2_authorizer.lambda_authorizer.id}/*/*”
Additionally I tried:
此外,我还尝试了:
source_arn = "${aws_apigatewayv2_api.api.execution_arn}/*"
来源_arn =“${aws_apigatewayv2_api.api.execution_arn}/*”
Still looking at the same error, nor can I see that the request is hitting my lambda (only API gateway)
仍然在查看相同的错误,也看不到请求正在命中我的lambda(仅API网关)
更多回答
优秀答案推荐
I think one of the possible reasons is that your Lambda had many versions, but you added the resource-based policy only to the unversioned function and not to the versioned ones.
我认为可能的原因之一是您的Lambda有许多版本,但您只将基于资源的策略添加到未版本化的函数中,而不添加到版本化的函数中。
In the terraform resource aws_lambda_permission
, you have to specify the qualifier argument, use the Lambda version as the value for it.
在terraform资源aws_lambda_permission中,您必须指定限定符参数,并使用Lambda版本作为它的值。
Otherwise you can also try to add /*/*
at the end:
否则,您也可以尝试在结尾处添加/*/*:
source_arn = "source_arn = "${aws_apigatewayv2_api.api.execution_arn}/authorizers/${aws_apigatewayv2_authorizer.lambda_authorizer.id}/*/*"
When you add an authorizer to an existing API GW, it does not create a deployment, and the authorizer will not change until you do so which Terraform makes it hard to do. see here
当您向现有的API GW添加授权器时,它不会创建部署,并且授权器不会更改,直到您这样做,这使得Terraform很难做到这一点。看这里
I got it sorted!
I'm using terragrunt but it should work the same.
For using lambda as authorizer permissions you need to specify the following in your source_arn
field, otherwise, lambda would think your setting an integration (!=authorization).
我把它整理好了!我使用的是Terragrun,但它应该是一样的。要使用lambda作为授权者权限,您需要在SOURCE_ARN字段中指定以下内容,否则,lambda会认为您的设置是集成(!=授权)。
source_arn = "${dependency.api_gateway.outputs.apigatewayv2_api_execution_arn}/authorizers/*"
which corresponds to something like this:
这与下面的内容相对应:
arn:aws:execute-api:us-east-1:0123456789:abcdefg89/authorizers/*
End resulthttps://i.stack.imgur.com/zCy7p.png
最终结果https://i.stack.imgur.com/zCy7p.png
Update 13/09:
更新13/09:
So after lots of fails and error please discard my previous comment. This is the configuration I've ended up with:
因此,在经历了许多失败和错误之后,请放弃我之前的评论。这是我最终得到的配置:
Background: HTTP API Gateway w/ autoDeploy, Custom Lambda Authorizer (NON-JWT) w/ publish set to true (no versions, just $LATEST).
I declare my authorizer as such (terragrunt, but same inputs for terraform):
我宣布我的授权者是这样的(Terragrun,但对terraform的输入相同):
authorizers = {
"lambda" = {
authorizer_type = "REQUEST"
identity_sources = "$request.header.User-Agent"
name = "lambda-authorizer"
authorizer_credentials_arn = "arn:aws:iam::0123456789012:role/prod.invokelambda.role"
authorizer_uri = "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:0123456789012:function:test_apigw-auth_lambda/invocations"
authorizer_payload_format_version = "2.0"
enable_simple_responses = true
}
}
I've used a IAM role with the following permissions:
我使用的IAM角色具有以下权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeLamdbaAuth",
"Action": "lambda:InvokeFunction",
"Effect": "Allow",
"Resource": "arn:aws:lambda:us-east-1:0123456789012:function:test_apigw-auth_lambda"
}
]
}
And trust policy:
和信任策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["apigateway.amazonaws.com", "lambda.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}
]
}
This sets up the authorizer as follows:
Screenshot-authorizer-conf
这将按如下方式设置授权器:Screenshot-Authizer-conf
And that was enough to invoke lambda properly and all set up with IaC. No RBAC set on lambda, nor triggers.
no-f-triggers
这足以正确地调用lambda并使用IAC进行所有设置。没有在lambda上设置RBAC,也没有触发器。无f触发器
Quick notes:
快速说明:
- Lambda as assume trust policy - not quite sure if it's needed.
- If you're debugging - turn on both apigw & lambda cloudwatch logs. I recommend adding
'responseType':'$context.error.responseType', 'errorMessage':'$context.error.message', 'integrationErrorMessage':'$context.integrationErrorMessage'
to your apigw log format for better understanding.
- Use the simplest lambda auth you could work with, like the one describe in the docs, just add console.log for f sake.
更多回答
I did post an update, no luck :(
我确实发了一个更新,没有运气:(
Sorry to hear that, have you checked the first option I mentioned about adding qualifier
to terraform resource aws_lambda_permission ?
很抱歉听到这个消息,你有没有检查过我提到的第一个选项,关于向terraform资源aws_lambda_permission添加限定符?
Okay so apparently the UI sucks, you could have set the permissions successfully, and it still won't show as a valid trigger in the console.. Even following the docs and using the cli for permissions got me the same results. The only way I could have gotten the UI to look proper was to create a route in my api gateway, which corresponds to the lambda name, and integrates with it. That plus source being arn:aws:execute-api:us-east-1:0123456789:abcdefg89/*/*/my-lambda-authorizer-name
好的,显然用户界面很糟糕,您本可以成功地设置权限,但它仍然不会在控制台中显示为有效的触发器。即使遵循文档并使用用于权限的cli,我也得到了相同的结果。我能让UI看起来合适的唯一方法是在我的API网关中创建一个对应于lambda名称的路由,并与其集成。这个外加消息来源是arn:aws:execute-api:us-east-1:0123456789:abcdefg89/*/*/my-lambda-authorizer-name
我是一名优秀的程序员,十分优秀!