Creating a Rest API in AWS API Gateway using Terraform and OpenAPI Swagger specification
Introduction
The AWS API Gateway makes developing, deploying and managing APIs a simple process. Combine that with Terraform and you have a reproducible and consistent approach to build and manage your environments using the Infrastructure-as-Code methodology.
In this article, I want to show you how easy it is to create an API in the AWS API Gateway using Terraform. The article assumes that:
1. You already have an AWS Account
2. Understand the basic concepts around the use of AWS
3. Have used and understand how Terraform works
4. Have a basic understanding of Rest API structure
For this article, we will use a Lambda function to implement the API logic. The API access is controlled using API Keys.
In the sections that follow, we will create:
1. The OpenAPI 3.0 specifications in Swagger.
2. The Terraform scripts
3. A Lambda function that responds to the API request.
Overview
Our aim in this article is to build a Rest API with a single GET operation that returns a greeting.
The operation is implemented using a Lambda function written in Python 3.7.
The API endpoint URI takes the form sayhello/{name} and returns back a response Hello {name}
The source code for the entire implementation is available in github at:
https://github.com/cliffdias/HelloworldAPI.git
So, let’s get cracking and write some code !!!
The Implementation
Open API 3.0.0 Specification
The creation of the API is driven from the OpenAPI 3 YAML. As part of the standard Rest API definition content, we add the AWS extensions allowing Terraform to create the infrastructure.
The specification for the HelloWorld API is provided below.
OpenAPI AWS extensions
The AWS extensions allow Terraform to create the required components in API Gateway.
x-amazon-apigateway-integration
This extension defines the details of the backend integration that implements the API. In our example we have the following:
x-amazon-apigateway-api-key-source
Specifies how the API receives the API Key. In our case this will be provided in the HEADER
Lambda Function
The Lambda function is written in Python 3 and returns a Greeting as a response.
Create a zip with the handler code and upload it to S3. The README provides instructions on how to do that.
Terraform Modules
Terraform provides modules to integrate AWS and create the infrastructure.
The Terraform code is available in the github repository. In this section we will look at the main modules that are used in the scripts.
To create our API we will follow the steps below:
Create a Role
The Terraform module aws_iam_role is used to create IAM Roles.
The role is assigned to the lambda function and provides permissions required to access any other AWS services like DynamoDB.
Create Lambda function
The module aws_lambda_function creates the lambda function sayhello using the lambda function deployment package we uploaded to the S3 bucket.
Grant Lambda function API Gateway Invoke permissions
This is an important step that is required to allow the API Gateway to invoke the lambda function
The script uses the module aws_lambda_permission
Create API Key
The API Key is created and assigned to the Usage Plan. The modules used are:
aws_api_gateway_api_key
aws_api_gateway_usage_plan_key
aws_api_gateway_usage_plan
The API Key allows us to manage access and rate limits on the API.
Create the API in API Gateway
The module aws_api_gateway_rest_api pulls all the module definitions together to create the API.
The Open API Specification YAML file is processed by the module and the API definition is used to create the required infrastructure.
Deploy the API
Once the API is created, the final step is to create the Stage(s) and the Deployment. This is done using the modules:
aws_api_gateway_stage
aws_api_gateway_deployment
Execution
To create the infrastructure follow the steps described in the README.
Wrap Up
If it all went according to plan and you received no errors, you should see something similar to the image below:
Calling the API like so
https://<yourapiendpoint>/stage1/hello/cliff
will result in a response
Status Code 200
{
“helloMessage”: “Hello cliff”
}