If I manually add an Integration Request of type Lambda function, an Api Gateway trigger is automatically added to the lambda function.
If I do it via Terraform, everything looks correct but when I go look at the Lambda function it has no trigger.
If I then manually update the Integration Request (change to Mock and back to Lambda Function) the trigger is added to the Lambda function? Everything works after that.
What am I missing?
resource "aws_api_gateway_integration" "integration" {
count = var.lambda_definition.apigateway ? 1 : 0
rest_api_id = "${data.terraform_remote_state.apigateway.outputs.apigateway_id}"
resource_id = aws_api_gateway_resource.api_proxy_resource[count.index].id
http_method = "${aws_api_gateway_method.method[count.index].http_method}"
integration_http_method = "ANY"
type = "AWS_PROXY"
uri = aws_lambda_function.lambda.invoke_arn
}
Since you've not mentioned whether you specified proper permissions for your function, my guess is that you are missing aws_lambda_permission. This will explicitly give permissions for the api to invoke your function.
The resource would be (example only):
resource "aws_lambda_permission" "allow_api" {
statement_id = "AllowAPIgatewayInvokation"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda.invoke_arn
principal = "apigateway.amazonaws.com"
}
When you do it manually in console, the AWS setups all these permissions in the background.
Make sure that integration_http_method is set to POST and not to ANY as in your sample:
integration_http_method = "POST"
See AWS Docs - midway - red box that says '! Important':
For Lambda integrations, you must use the HTTP method of POST for the integration request, according to the specification of the Lambda service action for function invocations. The IAM role of apigAwsProxyRole must have policies allowing the apigateway service to invoke Lambda functions. For more information about IAM permissions, see API Gateway permissions model for invoking an API.
Related
The problem is pretty simple but hard to figure it out. I have a lambda function with versioning enabled deployed via terraform. The lambda allows the API Gateway to call into it via the below Terraform resource
resource "aws_lambda_permission" "my_lambda_permission" {
statement_id = "AllowExecutionFromAPIGatewayVersion${aws_lambda_function.mylambda.version}"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.mylambda.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.apigw.execution_arn}/*/POST/redacted/path/to/resource"
qualifier = aws_lambda_function.myfunction.version
}
This is all fun and games and works for the current version. If I make a change to the lambda code and try to redeploy, the newer version gets the above policy and the previous version - the one that just worked - doesn't have a resource policy anymore.
How can I retain lambda previous versions' Resource-based policy?
I am utilizing Eventbridge API Destination to call my lambda function's url and throttle it to my desired rate. This works when the lambda function's invoke-url auth type is set to None. When I set the function Url auth type to AWS_IAM and create a resource-based invoke function url policy, it doesn't work.
I've tried setting the policy's principal to
the account root
the eventbridge role arn
the eventBridgeApiDestinations service role arn (arn:aws:iam::xxxxxxxxx:role/aws-service-role/apidestinations.events.amazonaws.com/AWSServiceRoleForAmazonEventBridgeApiDestinations)
None of the above work. Not sure what I'm doing wrong here or if it's even possible to do this.
Policy statement details
Statement ID
invoke-from-event-bridge-rule
Principal
arn:aws:iam::xxxxxxx:role/< my eventBridge role >
Effect
Allow
Action
lambda:InvokeFunctionUrl
Conditions
{
"StringEquals": {
"lambda:FunctionUrlAuthType": "AWS_IAM"
}
}
From the documentation:
Amazon EventBridge API destinations are HTTP endpoints that you can
invoke as the target of a rule, similar to how you invoke an AWS
service or resource as a target.
When you have EventBridge invoke your Lambda in this way, EventBridge doesn't know it is invoking a Lambda function. It doesn't even know it is invoking an AWS service. It is treating it the same as it would a third-party "webhook" external to AWS. It is not going to sign the HTTP request with AWS IAM credentials.
I suggest using a standard AWS Lambda invocation from EventBridge, instead of an HTTP endpoint invocation.
I'm struggling to translate my API Gateway Integration request into Terraform code, I'm trying to pass a multipart/form-data request to a Lambda for storage.
I've been able to set up the API gateway manually from scratch, but when I try the terraform I recieve an Internal server error and Cloudwatch tells me the gateway has been unable to transform the request.
Execution failed due to configuration error: Unable to transform request
The problem seems to be in the Integration request, because if I do the terraform deployment I can get the whole thing to work by changing the Integration Type in the UI to Lambda Proxy, changing it back again and adding re-adding the Mapping Template.
Terraform block for the Integration;
resource "aws_api_gateway_integration" "docuemnt-api-method-integration" {
rest_api_id = aws_api_gateway_rest_api.document-api.id
resource_id = aws_api_gateway_resource.document-resource.id
http_method = aws_api_gateway_method.document-post-method.http_method
type = "AWS"
uri = aws_lambda_function.document_function.invoke_arn
integration_http_method = "POST"
passthrough_behavior = "WHEN_NO_TEMPLATES"
request_templates = {
"multipart/form-data" = file("${path.module}/mapping/mapping_template.json")
}
}
The Mapping template
{
"body":"$input.body",
"content-type": "$util.escapeJavaScript($input.params().header.get('Content-Type'))"
}
On the AWS console you are NOT able to set the Integration Request's content_handling and it is only an Optional parameter in terraform as well. When you are changing the Integration Type in the UI to Lambda Proxy, the integration request's content_handling will be set to CONVERT_TO_TEXT.
So you need to add this row to the aws_api_gateway_integration:
content_handling = "CONVERT_TO_TEXT"
And normally it will solve your problem.
Amazon released HTTP APIs for their api gateway product fairly recently, and I'd like to use Terraform to spin some up. I saw that Terraform has documentation for the aws_apigatewayv2_api resource, which will create the gateway itself, but I can't find documentation for routes, stages, or any other types of resources that I'll be needing in my gateway.
Are HTTP APIs just not fully supported by Terraform yet, or am I missing some documentation somewhere?
Update:
Per the closing comment on issue #11148, the AWS API Gateway HTTP API resources were first generally supported in terraform-aws-provider starting in v3.3.0. Later releases have already added new functionality.
Historical answer:
Indeed, it looks like the Terraform AWS provider does not yet support all of the resources necessary for an API Gateway HTTP API.
The aws_apigatewayv2_api resource was released on March 12, 2020 in terraform-provider-aws 2.53.0, but implementations of resources such as aws_apigatewayv2_route, aws_apigatewayv2_stage, and aws_apigatewayv2_integration have yet to be merged.
terraform-provider-aws issue #11148 has links to pending pull requests for the new resources.
Everything you need to use http v2 apis is now available in terraform. There is a good tutorial on creating them here.
Essentially, for a simple gateway+lambda combo you want something like this:
# Lambda function
resource "aws_lambda_function" "lambda" {
# ...
}
# HTTP API
resource "aws_apigatewayv2_api" "api" {
name = "api-${random_id.id.hex}"
protocol_type = "HTTP"
target = aws_lambda_function.lambda.arn
}
# Permission
resource "aws_lambda_permission" "apigw" {
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda.arn
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.api.execution_arn}/*/*"
}
I am relatively new to AWS and the beast. After working on API Gateway to Lambda proxy integration I am getting Execution failed due to configuration error: Invalid permissions on Lambda function
I followed below setup referred from really well documented terraform documentation and does exactly what was needed for me. But while testing on API Gateway console giving the above error.
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.resource_name.arn}"
principal = "apigateway.amazonaws.com"
# The /*/* portion grants access from any method on any resource
# within the API Gateway "REST API".
source_arn = "${aws_api_gateway_deployment.resource_name_of_deployment.execution_arn}/*/*"
}
Few learnings from API Gateway Lambda proxy integration
API Gateway is deployed in different stages and ARN for API gateway in stage vs on test console is somewhat different. (atleast thats what I got on terraform output)
As many documentations and fixes for the problem suggests to explicitly configure detailed path as "arn:aws:execute-api:region_name:account_id:${aws_api_gateway_rest_api.api_resource.id}/*/*"
The configured source with granted access permission
arn:aws:execute-api:region:accountid:fu349z93pa/*/*
From terraform documentation
For "${aws_api_gateway_deployment.deployment_rsc_name.execution_arn}"
The configured source with granted access permission is
arn:aws:execute-api:region:accountid:fu349z93pa/stage/*/*
If you test from API Gateway console you would end up with same error and have to manually add permission to lambda or reselect lambda function name on method integration console (which does the same thing). That configures 2 API gateways to access Lambda. (one with /stage deployed ARN and other /*/METHOD/* - used for test console)
But if you test API gateway from ARN of stage environment on postman it works just as fine without any manual updates to infrastructure built with terraform. And in most cases that is the one that would matter.
Even after fixing first error manually / not second challenge is Malformed response from lambda
This one is fairly easy and well documented. AWS Doc
All we have to do is update lambda to respond with a specified format.
for. e.g. add below
callback(null, { "statusCode": 200, "body" : JSON.stringify(sampleResponseJSON) }); on lambda `js`
Once it is working end to end we could always add error handling scenarios.
Hopefully, this should save some time for beginners like me.
So instead of using:
resource "aws_lambda_permission" "apigw" {
... ...
source_arn = "${aws_api_gateway_deployment.resource_name_of_deployment.execution_arn}/*/*"
}
I use the replace method to remove the stage_name from the execution_arn:
resource "aws_lambda_permission" "apigw" {
... ...
source_arn = "${replace(aws_api_gateway_deployment.resource_name_of_deployment.execution_arn, var.stage_name, "")}*/*"
}
And now everything works for me