21

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

knaak
  • 1,293
  • 1
  • 12
  • 18
  • 1
    I found the answer to my question here: http://stackoverflow.com/questions/39040739/in-terraform-how-do-you-specify-an-api-gateway-endpoint-with-a-variable-in-the – knaak Feb 06 '17 at 16:41
  • could you answer your own question with detail codes? I need to take a reference. – BMW Jul 13 '17 at 10:33
  • 1
    @BMW I added it below. Good luck. – knaak Jul 14 '17 at 14:30

1 Answers1

27

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}"
}
knaak
  • 1,293
  • 1
  • 12
  • 18
  • 1
    ${format(...)} is a terraform function: https://www.terraform.io/docs/configuration/functions/format.html – Christopher Thomas Mar 12 '19 at 17:00
  • 4
    Pointing out for others, one of the big keys here that is easy to miss is the `request_parameters` attribute on the `aws_api_gateway_method`. Without this, it won't recognize `proxy` as a parameter in the integration uri. – rayepps Dec 22 '20 at 20:08
  • 3
    Following up on @rayepps's comment, it'd be very helpful to see the variables used to populate ApiProxyIntegration.request_parameters. – pdoherty926 Aug 25 '21 at 13:58
  • For some reason this returns a 500 Internal Server Error when hit from real clients (such postman) – Facundo La Rocca Feb 23 '23 at 03:27