DEV Community

Cover image for Creating & Managing Aws Rest Api Gateway Using Terraform
Cosmas Nyairo
Cosmas Nyairo

Posted on

Creating & Managing Aws Rest Api Gateway Using Terraform

We will be creating and managing an AWS rest api gateway using terraform

Table of Contents

Introduction

We can create resources on cloud either manually or using automation tools.

Lets take an example of the following api endpoint our service is exposing either through lambda or the vpc link:

 api/v1/test/get_tests -> an enpoint with POST AND GET requests
Enter fullscreen mode Exit fullscreen mode

If we were to create then above method manually; we would have to the following:

  • Create the rest api if one didnt exist
  • Create the api,v1, test then the get_tests resources
  • Create the GET method then and add the needed headers, add parameters the api may need, add authorization to the api and then repeat the same for the POST method.

This would be cumbersome if we had many api endpoints to create and managing the api endpoints would be very hard.

In this post:

  • We will focus on creating a simple AWS rest api which we will manage using terraform (an Infrastructure as Code tool).
  • We will be using the openapi specification for our apis
  • This approach can be inegrated with a CI/CD tool i.e jenkins or gitlab ci or github actions to enable further automation of our rest api endpoint

Prerequisites:

  • A postman collection containing our api endpoints (swagger api documentation would work as well)
  • An AWS account
  • Terraform (The version in use is Terraform v1.2.6)
  • We will focus on the rest apis where the underlying service is exposed using the vpc link

Rest api

For our rest api, we will need to provide the name, description and the endpoint type.

resource "aws_api_gateway_rest_api" "test_rest_api"{
  name = "<<REST API NAME>>"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
  description = "<<REST API DESCRIPTION>>"
  body        = data.template_file.testfile.rendered
}
Enter fullscreen mode Exit fullscreen mode

Rest api body

For the body we will use the code snippet below that utilizes terraform template files:

data "template_file" "testfile"{
  template = file("./test.yaml")
  vars = {
    methodresponses = var.methodresponses
    methoddetails   = var.methoddetails
  }
}
Enter fullscreen mode Exit fullscreen mode

Open API server

The servers section contains the custom domain name we would use to expose our api using.

Servers

Users would be able to access the service by sending api requests to the "{domainName}/{basePath}" endpoint

Open API paths

The paths section contains the paths for our api endpoints. We only need to specify the following:

  • Api endpoint e.g /api/v1/test/get_tests
  • The absolute path of the api endpoint being exposed via the vpc link ("https://$${stageVariables.url}/api/v1/test/get_tests")

    • The first part of the url is the url of the underlying domain exposing the service i.e "https://$${stageVariables.url}/.
    • The latter part is the actual path the service expects to expose the endpoint i.e "/api/v1/test/get_tests"
  • The type of the http method e.g POST

Method response

The method reponses contains a of method reponse e.g 200 and the response headers for the reponse.

variable "methodresponses"{
  default = <<EOT
responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Headers:
              schema:
                type: "string"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Empty"
EOT
}
Enter fullscreen mode Exit fullscreen mode

Method details

The method detail are as per the template below. We can add any headers the method needs under the response parameters section as shown.

variable "methoddetails"{
  default = <<EOT
responses:
  default:
    statusCode: "200"
    responseParameters:
      method.response.header.Access-Control-Allow-Origin: "<<VALUE>>"
passthroughBehavior: "when_no_match"
connectionType: "VPC_LINK"
type: "http_proxy"
EOT
}

Enter fullscreen mode Exit fullscreen mode

Terraform File structure

Terraform File structure

Our main.tf file will contain the following structure:

resource "aws_api_gateway_rest_api" "test_rest_api"{
  name = "<<REST API NAME>>"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
  description = "<<REST API DESCRIPTION>>"
  body        = data.template_file.testfile.rendered
} 

data "template_file" "testfile"{
  template = file("./test.yaml")
  vars = {
    methodresponses = var.methodresponses
    methoddetails   = var.methoddetails
  }
}
Enter fullscreen mode Exit fullscreen mode

Our locals.tf will contain the following structure:

variable "methodresponses"{
  default = <<EOT
responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Headers:
              schema:
                type: "string"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Empty"
EOT
}

variable "methoddetails"{
  default = <<EOT
responses:
  default:
    statusCode: "200"
    responseParameters:
      method.response.header.Access-Control-Allow-Origin: "<<VALUE>>"
passthroughBehavior: "when_no_match"
connectionType: "VPC_LINK"
type: "http_proxy"
EOT
}

Enter fullscreen mode Exit fullscreen mode

Our test.yaml file will contain the following openapi specification:

openapi: "3.0.1"
servers:
  - url: "{domainName}/{basePath}"
    variables:
      domainName:
        default: "https://test.com"
      basePath:
        default: "/testpath"
paths:
  /api/v1/test/get_tests:
    post:
      ${methodresponses}
      x-amazon-apigateway-integration:
        uri: "https://$${stageVariables.url}/api/v1/test/get_tests"
        connectionId: "$${stageVariables.vpcLink}"
        httpMethod: "POST"
        ${methoddetails}
    get:
      ${methodresponses}
      x-amazon-apigateway-integration:
        uri: "https://$${stageVariables.url}/api/v1/test/get_tests"
        connectionId: "$${stageVariables.vpcLink}"
        httpMethod: "GET"
        ${methoddetails}
  /api/v1/test/tests:
    get:
      ${methodresponses}
      x-amazon-apigateway-integration:
        uri: "https://$${stageVariables.url}//api/v1/test/tests"
        connectionId: "$${stageVariables.vpcLink}"
        httpMethod: "GET"
        ${methoddetails}
Enter fullscreen mode Exit fullscreen mode

To manage/add a new api endpoint we only need to update/change the test.yaml file.

We only need to do terraform plan and terraform apply for our api to be created.

Top comments (0)