Terraform-provider-aws: Root Proxy Issue

Created on 4 Feb 2018  ยท  5Comments  ยท  Source: hashicorp/terraform-provider-aws

Terraform Version

screen shot 2018-02-03 at 6 45 18 pm

Affected Resource(s)

  • aws_api_gateway_resource
  • aws_api_gateway_method
  • aws_api_gateway_integration

Terraform Configuration Files

resource "aws_api_gateway_rest_api" "api" {
  name        = "test-api"
  description = "test"
}

resource "aws_api_gateway_resource" "RootProxy" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part = "{proxy+}"
}

resource "aws_api_gateway_method" "RootResourceMethod" {
  api_key_required = "false"
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "ANY"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "ResourceMethodIntegration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "${aws_api_gateway_method.RootResourceMethod.http_method}"
  type = "HTTP_PROXY"
  integration_http_method  = "ANY"
  uri = "http://${MY_URL}/{proxy}"
  passthrough_behavior     = "WHEN_NO_MATCH"
}

Expected Behavior

When going through the console and creating a {proxy+} root resource, the console assigns the proxy to the integration request Paths as seen below:

  • After creating a resource on root (_arn redeacted_) :

screen shot 2018-02-03 at 7 05 46 pm

  • After finishing the integration request setup through the console (_arn redeacted_) :

screen shot 2018-02-03 at 7 07 52 pm

Actual Behavior

Using the Terraform code above, it produces an "ANY" method that does not forward the entire path of the request ( Paths on the integration request is missing)

screen shot 2018-02-03 at 6 58 41 pm

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. Create test project with above example and compare to manual process through AWS console

Most helpful comment

Figured this out after much pain. Non-issue, but documentation could be better around this!

This is the answer to get the above:

resource "aws_api_gateway_rest_api" "api" {
  name        = "test-api"
  description = "test"
}

resource "aws_api_gateway_resource" "RootProxy" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part = "{proxy+}"
}

resource "aws_api_gateway_method" "RootResourceMethod" {
  api_key_required = "false"
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "ANY"
  authorization = "NONE"
  request_parameters {
    "method.request.path.proxy" = true
  }
}

resource "aws_api_gateway_integration" "ResourceMethodIntegration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "${aws_api_gateway_method.RootResourceMethod.http_method}"
  type = "HTTP_PROXY"
  integration_http_method  = "ANY"
  uri = "http://${MY_URL}/{proxy}"
  passthrough_behavior     = "WHEN_NO_MATCH"
  request_parameters {
    "integration.request.path.proxy" = "method.request.path.proxy"
  }
}

All 5 comments

Figured this out after much pain. Non-issue, but documentation could be better around this!

This is the answer to get the above:

resource "aws_api_gateway_rest_api" "api" {
  name        = "test-api"
  description = "test"
}

resource "aws_api_gateway_resource" "RootProxy" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  parent_id = "${aws_api_gateway_rest_api.api.root_resource_id}"
  path_part = "{proxy+}"
}

resource "aws_api_gateway_method" "RootResourceMethod" {
  api_key_required = "false"
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "ANY"
  authorization = "NONE"
  request_parameters {
    "method.request.path.proxy" = true
  }
}

resource "aws_api_gateway_integration" "ResourceMethodIntegration" {
  rest_api_id = "${aws_api_gateway_rest_api.api.id}"
  resource_id = "${aws_api_gateway_resource.RootProxy.id}"
  http_method = "${aws_api_gateway_method.RootResourceMethod.http_method}"
  type = "HTTP_PROXY"
  integration_http_method  = "ANY"
  uri = "http://${MY_URL}/{proxy}"
  passthrough_behavior     = "WHEN_NO_MATCH"
  request_parameters {
    "integration.request.path.proxy" = "method.request.path.proxy"
  }
}

+5 Several hours looking for information on this. Definitely, docs should improve on this issue.

The key takeaway is: whenever you set request_parameters on aws_api_gateway_integration you also NEED request_parameters on aws_api_gateway_method set to true. This threat is the only information source I found that finally explains it.

Thanks @olingern

Thanks @olingern , I was able to make a test call from API gateway to my network load balancer by adding these two set of request parameters. But when I tried the API gateway's URL in browser, I'm still getting the same old 404 :-(

Sample URL https://<account-id>.execute-api.<region>.amazonaws.com/<stage>/api/v2/echo

Yeah my understanding is that you can declare a resource with {curly} {braces} and they become path parameters, the {proxy} and {proxy+} names are special though.

So once you've got an aws_api_gateway_resource with a path part {like} {this}. Then {like} and {this} become available as method request path parameters. You can declare them available for use in the integration.

In order for the integration to be able to use those path parameters, you whitelist them by in the
aws_api_gateway_method as request_parameters and each parameter you want, you need to set to the value = true. For Example:

resource "aws_api_gateway_method" "request_method" {
  (other things go here)

  request_parameters = {
    "method.request.path.like" = true
    "method.request.path.this" = true
    "method.request.path.proxy" = true
  }
}

and then in the integration, you set request_parameters. For Example:

resource "aws_api_gateway_integration" "request_method_integration" {
  (other things here)

  uri = "http://${aws_nlb.dns_name}/{like}/{this}/{proxy}"

  request_parameters = {
    "integration.request.path.like" = "method.request.path.like"
    "integration.request.path.this" = "method.request.path.this"
    "integration.request.path.proxy" = "method.request.path.proxy"
  }
}

I've left an example of how to set the integration endpoint using those parameters on purpose as a demonstration of how to use them.

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

Was this page helpful?
0 / 5 - 0 ratings