We will be creating and managing an AWS rest api gateway using terraform
Table of Contents
- Introduction
- Prerequisites
- Rest Api
- Rest Api Body
- Open API server
- Open API paths
- Method response
- Method details
- Terraform File structure
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
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
}
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
}
}
Open API server
The servers section contains the custom domain name we would use to expose our api using.
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 first part of the url is the url of the underlying domain exposing the service i.e
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
}
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
}
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
}
}
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
}
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}
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)