Error creating API Gateway Integration Response: NotFoundException: Invalid Integration identifier specified - amazon-web-services

Objective
Solution or workaround for the problem.
Problem
The Terraform API Gateway integration with Firehose below works if Firehose is created separately in advance.
resource "aws_api_gateway_integration" "click_put" {
rest_api_id = data.aws_api_gateway_rest_api.mysfit.id
resource_id = aws_api_gateway_resource.click.id
type = "AWS"
uri = "arn:aws:apigateway:${var.REGION}:firehose:action/PutRecord"
credentials = aws_iam_role.api_click.arn
http_method = aws_api_gateway_method.click_put.http_method
integration_http_method = "POST"
request_parameters = {
"integration.request.header.Content-Type" = "'application/x-amz-json-1.1'"
}
passthrough_behavior = "NEVER"
request_templates = {
"application/json" = <<EOF
{
"DeliveryStreamName": "${local.firehose_name}",
"Record": {
"Data": "$util.base64Encode($input.json('$'))"
}
}
EOF
}
}
...
resource "aws_api_gateway_integration_response" "click_put" {
rest_api_id = data.aws_api_gateway_rest_api.mysfit.id
resource_id = aws_api_gateway_resource.click.id
http_method = aws_api_gateway_method.click_put.http_method
status_code = aws_api_gateway_method_response.click_put.status_code
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = "'*'"
}
}
However, if they are created in the same root module, it causes the error.
Error creating API Gateway Integration Response: NotFoundException: Invalid Integration identifier specified
on api_click.tf line 185, in resource "aws_api_gateway_integration_response" "click_put":
185: resource "aws_api_gateway_integration_response" "click_put" {

Workaround/Solution
Place a dependency on the aws_api_gateway_integration from the resource causing "NotFoundException: Invalid Integration identifier specified".
resource "aws_api_gateway_integration_response" "click_put" {
rest_api_id = data.aws_api_gateway_rest_api.mysfit.id
resource_id = aws_api_gateway_resource.click.id
http_method = aws_api_gateway_method.click_put.http_method
status_code = aws_api_gateway_method_response.click_put.status_code
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = "'*'"
}
depends_on = [
aws_api_gateway_integration.click_put
]
}
References
There are indications that depends_on aws_api_gateway_integration or placing a wait would be the way.
Probably waiting for the complete completion of the aws_api_gateway_integration resource would be a recommended practice.
aws_api_gateway_integration_response
Note: Depends on having aws_api_gateway_integration inside your rest api. To ensure this you might need to add an explicit depends_on for clean runs.
API gateway integration issue - Invalid Method identifier specified Error #4001
I'm using the following workaround to solve a similar issue. I'm getting the Invalid Method identifier error on the first run when all the resources are created during the same apply. A proxy API for Lambda is created:
resource "aws_api_gateway_resource" "proxy" {
rest_api_id = aws_api_gateway_rest_api.rest-api.id
parent_id = aws_api_gateway_rest_api.rest-api.root_resource_id
path_part = "{proxy+}"
}
resource "null_resource" "method-delay" {
provisioner "local-exec" {
command = "sleep 5"
}
triggers = {
response = aws_api_gateway_resource.proxy.id
}
}
resource "aws_api_gateway_method_response" "response" {
depends_on = [null_resource.method-delay]
http_method = "ANY"
resource_id = aws_api_gateway_resource.proxy.id
rest_api_id = aws_api_gateway_rest_api.rest-api.id
}

you can just add depends_on. Should be something like:
resource "aws_api_gateway_integration" "create-oauth-lambda" {
rest_api_id = aws_api_gateway_rest_api.create-oauth-token-api-gw.id
resource_id = aws_api_gateway_resource.auth-token-resource.id
http_method = aws_api_gateway_method.method.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "some URI"
}
resource "aws_api_gateway_method_response" "response-200" {
depends_on = [aws_api_gateway_integration.create-oauth-lambda]
rest_api_id = aws_api_gateway_rest_api.create-oauth-token-api-gw.id
resource_id = aws_api_gateway_resource.auth-token-resource.id
http_method = aws_api_gateway_method.method.http_method
status_code = "200"
response_models = {
"application/json" = "Empty"
}
}

Related

Build API Gateway on AWS using Terraform returning statusCode 200

I am a noob also doesn't know how to ask questions,
actually i want to create a API Gateway using TF that should returning statusCode 200, i tried offical TF examples to create one but the API Gateway return 500 instead of 200, i can't able to figure out what is the error, you can look at my code below , it doesn't using lambda or anything , i just tried with mock endpoint but still can't able to figure out
TF CODE
resource "aws_api_gateway_rest_api" "MyDemoAPI" {
name = "MyDemoAPI"
description = "This is my API for demonstration purposes"
}
resource "aws_api_gateway_resource" "MyDemoResource" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
parent_id = aws_api_gateway_rest_api.MyDemoAPI.root_resource_id
path_part = "mydemoresource"
}
resource "aws_api_gateway_method" "MyDemoMethod" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = "GET"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "MyDemoIntegration" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = aws_api_gateway_method.MyDemoMethod.http_method
type = "MOCK"
}
resource "aws_api_gateway_method_response" "response_200" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = aws_api_gateway_method.MyDemoMethod.http_method
status_code = "200"
}
resource "aws_api_gateway_integration_response" "MyDemoIntegrationResponse" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = aws_api_gateway_method.MyDemoMethod.http_method
status_code = aws_api_gateway_method_response.response_200.status_code
# 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
}
}
When i created one in AWS console it's working fine, but i can't able to do that using this TF code
You have't specified request_templates for your MyDemoIntegration:
resource "aws_api_gateway_integration" "MyDemoIntegration" {
rest_api_id = aws_api_gateway_rest_api.MyDemoAPI.id
resource_id = aws_api_gateway_resource.MyDemoResource.id
http_method = aws_api_gateway_method.MyDemoMethod.http_method
type = "MOCK"
request_templates = {
"application/json" = <<EOF
{
"statusCode": 200
}
EOF
}
}

AWS API Gateway and static HTML: "Execution failed due to configuration error: statusCode should be an integer which defined in request template"

I am trying to serve a static content using AWS API Gateway.
When I attempt to invoke the URL, both from the test page and from curl, I get the error:
"Execution failed due to configuration error: statusCode should be an integer which defined in request template".
This is my configuration on Terraform:
resource "aws_api_gateway_rest_api" "raspberry_api" {
name = "raspberry_api"
}
resource "aws_acm_certificate" "raspberry_alexa_mirko_io" {
domain_name = "raspberry.alexa.mirko.io"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "raspberry_alexa_mirko_io_cert_validation" {
name = aws_acm_certificate.raspberry_alexa_mirko_io.domain_validation_options.0.resource_record_name
type = aws_acm_certificate.raspberry_alexa_mirko_io.domain_validation_options.0.resource_record_type
zone_id = var.route53_zone_id
records = [aws_acm_certificate.raspberry_alexa_mirko_io.domain_validation_options.0.resource_record_value]
ttl = 60
}
resource "aws_route53_record" "raspberry_alexa_mirko_io" {
zone_id = var.route53_zone_id
name = aws_acm_certificate.raspberry_alexa_mirko_io.domain_name
type = "A"
alias {
name = aws_api_gateway_domain_name.raspberry_alexa_mirko_io.cloudfront_domain_name
zone_id = aws_api_gateway_domain_name.raspberry_alexa_mirko_io.cloudfront_zone_id
evaluate_target_health = true
}
}
resource "aws_acm_certificate_validation" "raspberry_alexa_mirko_io" {
certificate_arn = aws_acm_certificate.raspberry_alexa_mirko_io.arn
validation_record_fqdns = [aws_route53_record.raspberry_alexa_mirko_io_cert_validation.fqdn]
provider = aws.useast1
}
resource "aws_api_gateway_domain_name" "raspberry_alexa_mirko_io" {
certificate_arn = aws_acm_certificate_validation.raspberry_alexa_mirko_io.certificate_arn
domain_name = aws_acm_certificate.raspberry_alexa_mirko_io.domain_name
}
resource "aws_api_gateway_base_path_mapping" "raspberry_alexa_mirko_io_base_path_mapping" {
api_id = aws_api_gateway_rest_api.raspberry_api.id
domain_name = aws_api_gateway_domain_name.raspberry_alexa_mirko_io.domain_name
}
resource "aws_api_gateway_resource" "home" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
parent_id = aws_api_gateway_rest_api.raspberry_api.root_resource_id
path_part = "login"
}
resource "aws_api_gateway_method" "login" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
resource_id = aws_api_gateway_resource.home.id
http_method = "GET"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "integration" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
resource_id = aws_api_gateway_resource.subscribe_raspberry.id
http_method = aws_api_gateway_method.subscribe.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.raspberry_lambda.invoke_arn
# This was just a failed attempt. It did not fix anything
request_templates = {
"text/html" = "{\"statusCode\": 200}"
}
}
resource "aws_api_gateway_integration" "login_page" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
resource_id = aws_api_gateway_resource.home.id
http_method = aws_api_gateway_method.login.http_method
type = "MOCK"
timeout_milliseconds = 29000
}
resource "aws_api_gateway_method_response" "response_200" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
resource_id = aws_api_gateway_resource.home.id
http_method = aws_api_gateway_method.login.http_method
status_code = "200"
}
resource "aws_api_gateway_integration_response" "login_page" {
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
resource_id = aws_api_gateway_resource.home.id
http_method = aws_api_gateway_method.login.http_method
status_code = aws_api_gateway_method_response.response_200.status_code
response_templates = {
"text/html" = data.template_file.login_page.rendered
}
}
resource "aws_api_gateway_deployment" "example" {
depends_on = [
aws_api_gateway_integration.login_page
]
rest_api_id = aws_api_gateway_rest_api.raspberry_api.id
stage_name = "production"
}
I have followed the instructions as in this blog, with no success.
"200" (with quotes) is considered a string, not an integer
try status_code = 200 (without quotes)
Just to repost the excellent answer of TheClassic here, the format seems to be:
request_templates = {
"application/json" = jsonencode(
{
statusCode = 200
}
)
}
I also had this same problem, but looks like this works.
I had the same error because my code looked like this beforehand - inspired by the terraform docs.
resource "aws_api_gateway_integration" "api_gateway" {
http_method = aws_api_gateway_method.api_gateway.http_method
resource_id = aws_api_gateway_resource.api_gateway.id
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
type = "MOCK"
}
After reading this thread it now works looking like this:
resource "aws_api_gateway_integration" "api_gateway" {
http_method = aws_api_gateway_method.api_gateway.http_method
resource_id = aws_api_gateway_resource.api_gateway.id
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
type = "MOCK"
request_templates = {
"application/json" = jsonencode(
{
statusCode = 200
}
)
}
}
As per Bernie comment, this status code needs to be explicitly provided in request_templates attribute in aws_api_gateway_integration terraform resource.
After adding it I finally got 200 for OPTIONS that are integrated via MOCK endpoint.
For others who might see this, this error can also be caused by a need to verify that when you use Mock as your Integration type, you confirm that your RequestTemplates contain statusCode and the value of statusCode is equal to one of your IntegrationResponses/ResponseTemplates/StatusCode
Something like:
requestTemplates: {
"application/json": "{\"statusCode\": 200}"
}

How to enable CORS on AWS with terraform

I am trying to enable CORS on my aws project which consists of API Gateway and Lambda function.
I'm creating an API Gateway with GET and OPTIONS methods.
OPTIONS is meant to be a mock endpoint for enabling CORS as per aws documentation.
There is a lambda function (aws_lambda_function.app_lambda) which is invoked by GET method and in response headers has:
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
But still, I cannot pass CORS.
resource "aws_api_gateway_rest_api" "rest_api" {
name = "appAPIGateway"
description = "App App App"
}
resource "aws_api_gateway_resource" "rest_api_resource" {
depends_on = ["aws_api_gateway_rest_api.rest_api"]
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
parent_id = "${aws_api_gateway_rest_api.rest_api.root_resource_id}"
path_part = "playground"
}
resource "aws_api_gateway_method" "opt" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "OPTIONS"
authorization = "NONE"
api_key_required = true
}
resource "aws_api_gateway_integration" "opt" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "${aws_api_gateway_method.opt.http_method}"
type = "MOCK"
}
resource "aws_api_gateway_integration_response" "opt" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "${aws_api_gateway_method.opt.http_method}"
status_code = 200
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = "'*'",
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With'",
"method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'"
}
depends_on = ["aws_api_gateway_integration.opt", "aws_api_gateway_method_response.opt"]
}
resource "aws_api_gateway_method_response" "opt" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "${aws_api_gateway_method.opt.http_method}"
status_code = 200
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = true,
"method.response.header.Access-Control-Allow-Methods" = true,
"method.response.header.Access-Control-Allow-Headers" = true
}
response_models = {
"application/json" = "Empty"
}
depends_on = ["aws_api_gateway_method.opt"]
}
resource "aws_api_gateway_method" "app_api_gateway_method" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "GET"
authorization = "NONE"
api_key_required = true
}
resource "aws_api_gateway_method_response" "app_cors_method_response_200" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
status_code = "200"
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = true,
"method.response.header.Access-Control-Allow-Methods" = true,
"method.response.header.Access-Control-Allow-Headers" = true
}
depends_on = ["aws_api_gateway_method.app_api_gateway_method"]
}
resource "aws_api_gateway_integration" "app_api_gateway_integration" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_method.app_api_gateway_method.resource_id}"
http_method = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.app_lambda.invoke_arn}"
depends_on = [
"aws_api_gateway_method.app_api_gateway_method",
"aws_lambda_function.app_lambda"
]
}
resource "aws_api_gateway_integration_response" "app_api_gateway_integration_response" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
resource_id = "${aws_api_gateway_resource.rest_api_resource.id}"
http_method = "${aws_api_gateway_method.app_api_gateway_method.http_method}"
status_code = 200
response_parameters = {
"method.response.header.Access-Control-Allow-Origin" = "'*'",
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With'",
"method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'"
}
depends_on = [
"aws_api_gateway_integration.app_api_gateway_integration",
"aws_api_gateway_method_response.app_cors_method_response_200",
]
}
resource "aws_api_gateway_deployment" "app_api_gateway_deployment" {
rest_api_id = "${aws_api_gateway_rest_api.rest_api.id}"
stage_name = "app_stage"
depends_on = [
"aws_api_gateway_integration_response.app_api_gateway_integration_response",
"aws_api_gateway_integration_response.opt"
]
}
Any help would be appreceated.
For newer HTTP API (v2), you can use:
resource "aws_apigatewayv2_api" "lambda" {
name = "lambda_gw_api"
protocol_type = "HTTP"
cors_configuration {
allow_origins = ["https://www.mywebsite.fr"]
allow_methods = ["POST", "GET", "OPTIONS"]
allow_headers = ["content-type"]
max_age = 300
}
}
PS: you may also need to check your OPTIONS route has an "integration" and does not return 401.
You can use the terraform module to enable cors:
module "api-gateway-enable-cors" {
source = "squidfunk/api-gateway-enable-cors/aws"
version = "0.3.3"
api_id = "<your_api_id>"
api_resource_id = "<your_api_resource_id>"
}
Source : api-gateway-enable-cors
Found out a simple solution. The problem was that on applying newer changes to existing API Gateway, was NOT re-deploying those gateways. So I had to redeploy them by myself manually and think of how to do that in terraform too.
It is useful to check the API GW logs in Cloudwatch to see what is the status code. In my scenario, I had two routes configured with aws_apigatewayv2_route, one for POST and one for OPTIONS, for the same route key. The OPTIONS request was failing with statuscode 429 which is too many requests. This status code is usually returned by throttling settings when its over allowed limit.
Turns out, since the OPTIONS request was not passing CORS, it was because I did not specify throttling in default_route_settings in terraform, so the default throttling for "Default route throttling" was defaulting to 0 for burst and rate. So my OPTIONS request was not passing CORS because it was getting hit by this throttling defaulting to zero. The hint in AWS console is clear:
This throttling limit applies to each route in the stage except those
defined for specific routes.
Moral of the story - on your OPTIONS requests, really pay attention to the status code returned by API GW, and check the Cloudwatch logs for API GW.
So: all worked, when I added this in terraform, under my resource "aws_apigatewayv2_stage" "lambda":
default_route_settings {
throttling_burst_limit = 1000
throttling_rate_limit = 5000
}

How to use api_gateway_base_path_mapping with terraform?

I'm trying to setup a custom domain name for an api in api gateway on aws. I have setup the api fine using terraform. However when I try to setup the custom domain it fails with the following error.
Error applying plan:
1 error(s) occurred:
module.BillingMetrics.aws_api_gateway_base_path_mapping.billing: 1 error(s) occurred:
aws_api_gateway_base_path_mapping.billing: Error creating Gateway base path mapping: Error creating Gateway base path mapping: BadRequestException: Invalid REST API identifier specified
status code: 400, request id: b14bbd4c-5823-11e7-a4ea-93525a34b321
I can see in the terraform log that it does get the correct api_id. But I don't understand why it's saying the rest api identifier is invalid.
Below is an excerpt of my terraform file showing how I'm configuring the api_gateway_base_path_mapping.
resource "aws_api_gateway_resource" "views_resource" {
provider = "aws.regional"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
parent_id = "${aws_api_gateway_rest_api.billing_api.root_resource_id}"
path_part = "views"
}
resource "aws_api_gateway_method" "views-get" {
provider = "aws.regional"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
resource_id = "${aws_api_gateway_resource.views_resource.id}"
http_method = "GET"
authorization = "NONE"
}
resource "aws_api_gateway_method_response" "views_200" {
provider = "aws.regional"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
resource_id = "${aws_api_gateway_resource.views_resource.id}"
http_method = "${aws_api_gateway_method.views-get.http_method}"
status_code = "200"
}
resource "aws_api_gateway_integration" "views-integration" {
provider = "aws.regional"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
resource_id = "${aws_api_gateway_resource.views_resource.id}"
http_method = "${aws_api_gateway_method.views-get.http_method}"
type = "AWS"
uri = "arn:aws:apigateway:${var.region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${var.region}:${var.account_id}:function:${aws_lambda_function.get_views.function_name}/invocations"
credentials = "${var.metrics_role_arn}"
http_method = "${aws_api_gateway_method.views-get.http_method}"
integration_http_method = "POST"
}
resource "aws_api_gateway_integration_response" "Views_Get_IntegrationResponse" {
provider = "aws.regional"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
resource_id = "${aws_api_gateway_resource.views_resource.id}"
http_method = "${aws_api_gateway_method.views-get.http_method}"
status_code = "${aws_api_gateway_method_response.views_200.status_code}"
}
/* Deploy api */
resource "aws_api_gateway_deployment" "metric_deploy" {
provider = "aws.regional"
depends_on = ["aws_api_gateway_integration.metrics-integration", "aws_api_gateway_integration.hours-integration"]
stage_name = "beta"
rest_api_id = "${aws_api_gateway_rest_api.billing_api.id}"
}
resource "aws_api_gateway_domain_name" "billing" {
domain_name = "billing.example.com"
certificate_arn = "arn:aws:acm:us-east-1:6--:certificate/5--"
}
resource "aws_api_gateway_base_path_mapping" "billing" {
api_id = "${aws_api_gateway_rest_api.billing_api.id}"
stage_name = "${aws_api_gateway_deployment.metric_deploy.stage_name}"
domain_name = "${aws_api_gateway_domain_name.billing.domain_name}"
}
resource "aws_route53_record" "billing" {
zone_id = "Z-------"
name = "${aws_api_gateway_domain_name.billing.domain_name}"
type = "A"
alias {
name = "${aws_api_gateway_domain_name.billing.cloudfront_domain_name}"
zone_id = "${aws_api_gateway_domain_name.billing.cloudfront_zone_id}"
evaluate_target_health = true
}
}
Are there any more elements that needed to be configured to have the base_path_mapping apply correctly? Any other hints what I might be doing wrong?
I should also mention I'm on terraform 0.9.7.

How do I create an API Proxy using Terraform and AWS API Gateway

I am trying to use Terraform to be able to stand up a simple API Proxy in API Gateway on AWS. Basically, I want to wrap root and proxy the requests back to another end point. Its probably the simplest setup and I can't seem to get it to work in Terraform.
Below you will find the script. At this point I am able to create the REST API, define a Resource, create a method but there doesn't seem to be any way to define it the end-point.
provider "aws" {
region = "us-east-1"
}
resource "aws_api_gateway_rest_api" "TerraTest" {
name = "TerraTest"
description = "This is my API for demonstration purposes"
}
resource "aws_api_gateway_resource" "TerraProxyResource" {
rest_api_id = "${aws_api_gateway_rest_api.TerraTest.id}"
parent_id = "${aws_api_gateway_rest_api.TerraTest.root_resource_id}"
path_part = "{proxy+}"
}
resource "aws_api_gateway_integration" "integration" {
rest_api_id = "${aws_api_gateway_rest_api.TerraTest.id}"
resource_id = "${aws_api_gateway_resource.TerraProxyResource.id}"
http_method = "${aws_api_gateway_method.mymethod.http_method}"
type = "HTTP_PROXY"
uri = "http://api.endpoint.com/{proxy+}"
}
Here I set the type to proxy, but I don't think URI is the right property for setting the endpoint.
resource "aws_api_gateway_method" "mymethod" {
rest_api_id = "${aws_api_gateway_rest_api.TerraTest.id}"
resource_id = "${aws_api_gateway_resource.TerraProxyResource.id}"
http_method = "ANY"
authorization = "NONE"
}
I expect somewhere here to be able to create that mapping to some other endpoint, but there doesn't appear to be any properties for that. (https://github.com/hashicorp/terraform/blob/master/builtin/providers/aws/resource_aws_api_gateway_method.go)
resource "aws_api_gateway_api_key" "TerraTestKey" {
name = "Terra_Test_Key"
stage_key {
rest_api_id = "${aws_api_gateway_rest_api.TerraTest.id}"
stage_name = "${aws_api_gateway_deployment.TerraTestDeployment.stage_name}"
}
}
resource "aws_api_gateway_deployment" "TerraTestDeployment" {
rest_api_id = "${aws_api_gateway_rest_api.TerraTest.id}"
stage_name = "dev"
}
I scanned the source code and I didn't see any properties that I can set.
Can anyone share any advice/snipets?
Tim
Ps. If you want to try to run the script yourself, I put it here: http://textuploader.com/d14sx
This is the relevant module which shows a working solution. It doesn't stand alone since it relies on some variables defined elsewhere but it should be enough to help anyone struggling to get a AWS Proxy setup and also shows Lambda authorizer integration as a bonus.
provider "aws" {
region = "${var.region}"
profile = "${var.profile}"
}
data "aws_iam_role" "api_user" {
role_name = "api_user"
}
module "authorizer_lambda" {
source = "../lambda"
name = "${var.api_name}-authorizer_lambda"
filename = "authorizer_lambda"
runtime = "nodejs4.3"
role = "${data.aws_iam_role.api_user.arn}"
}
resource "aws_api_gateway_authorizer" "custom_authorizer" {
name = "${var.api_name}-custom_authorizer"
rest_api_id = "${aws_api_gateway_rest_api.ApiGateway.id}"
authorizer_uri = "${module.authorizer_lambda.uri}"
authorizer_credentials = "${data.aws_iam_role.api_user.arn}"
authorizer_result_ttl_in_seconds = 1
}
resource "aws_api_gateway_rest_api" "ApiGateway" {
name = "${var.api_name}"
description = "${var.api_description}"
}
resource "aws_api_gateway_resource" "ApiProxyResource" {
rest_api_id = "${aws_api_gateway_rest_api.ApiGateway.id}"
parent_id = "${aws_api_gateway_rest_api.ApiGateway.root_resource_id}"
path_part = "{proxy+}"
}
resource "aws_api_gateway_integration" "ApiProxyIntegration" {
rest_api_id = "${aws_api_gateway_rest_api.ApiGateway.id}"
resource_id = "${aws_api_gateway_resource.ApiProxyResource.id}"
http_method = "${aws_api_gateway_method.ApiProxyMethod.http_method}"
type = "HTTP_PROXY"
integration_http_method = "ANY"
uri = "${format("%s/{proxy}", "${var.base_url}")}"
passthrough_behavior = "WHEN_NO_MATCH"
request_parameters = "${var.aws_api_gateway_integration_request_parameters}"
}
resource "aws_api_gateway_method" "ApiProxyMethod" {
rest_api_id = "${aws_api_gateway_rest_api.ApiGateway.id}"
resource_id = "${aws_api_gateway_resource.ApiProxyResource.id}"
http_method = "ANY"
authorization = "CUSTOM"
authorizer_id = "${aws_api_gateway_authorizer.custom_authorizer.id}"
request_parameters = {"method.request.path.proxy" = true}
}
resource "aws_api_gateway_deployment" "ApiDeployment" {
depends_on = ["aws_api_gateway_method.ApiProxyMethod"]
rest_api_id = "${aws_api_gateway_rest_api.ApiGateway.id}"
stage_name = "${var.stage_name}"
}