🐶
Terraform

Create AWS API Gateway Proxy with Terraform

By Filip on 11/17/2024

Learn how to efficiently create and manage API proxies on AWS API Gateway using Terraform for streamlined infrastructure provisioning and automated workflows.

Create AWS API Gateway Proxy with Terraform

Table of Contents

Introduction

This guide provides a step-by-step approach to building a basic API Gateway proxy using Terraform. We'll establish a simple API endpoint that leverages a Lambda function for backend logic. The process involves defining the API Gateway resource, creating a resource within it, defining a method for the resource, configuring the integration type, deploying the API Gateway changes, and finally, configuring a stage for the deployment.

Step-by-Step Guide

  1. Define the API Gateway resource:
resource "aws_api_gateway_rest_api" "example" {
  name = "example"
}
  1. Create a resource within the API Gateway:
resource "aws_api_gateway_resource" "example" {
  rest_api_id = aws_api_gateway_rest_api.example.id
  parent_id   = aws_api_gateway_rest_api.example.root_resource_id
  path_part   = "example"
}
  1. Define a method for the resource:
resource "aws_api_gateway_method" "example" {
  rest_api_id   = aws_api_gateway_rest_api.example.id
  resource_id   = aws_api_gateway_resource.example.id
  http_method   = "GET"
  authorization = "NONE"
}
  1. Configure the integration type (e.g., Lambda function):
resource "aws_api_gateway_integration" "example" {
  rest_api_id             = aws_api_gateway_rest_api.example.id
  resource_id             = aws_api_gateway_resource.example.id
  http_method             = aws_api_gateway_method.example.http_method
  integration_type        = "AWS_PROXY"
  integration_target_arn = aws_lambda_function.example.invoke_arn
}
  1. Deploy the API Gateway changes:
resource "aws_api_gateway_deployment" "example" {
  rest_api_id = aws_api_gateway_rest_api.example.id
  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_integration.example))
  }
}
  1. Configure a stage for the deployment:
resource "aws_api_gateway_stage" "example" {
  deployment_id = aws_api_gateway_deployment.example.id
  rest_api_id   = aws_api_gateway_rest_api.example.id
  stage_name    = "example"
}

This sets up a basic API Gateway proxy with a single GET method integrated with a Lambda function. You can customize it further by adding resources, methods, integrations, authorizers, and other features as needed.

Code Example

This Terraform code defines infrastructure on AWS. It sets up a simple Node.js Lambda function that returns "Hello from Lambda!" when invoked. An API Gateway is configured with a GET method on the "/example" resource, integrated with the Lambda function. This allows invoking the function through HTTP requests to the provided API Gateway endpoint URL. The code also sets up the necessary IAM roles and policies for the Lambda function to operate.

# Configure the AWS Provider
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

# Configure variables (replace with your values)
variable "region" {
  default = "us-east-1"
}

variable "lambda_function_name" {
  default = "example_function"
}

# Create a Lambda function (replace with your function code)
resource "aws_lambda_function" "example" {
  function_name = var.lambda_function_name
  runtime = "nodejs16.x"
  handler = "index.handler"
  role    = aws_iam_role.lambda_exec.arn

  # Replace with your actual function code
  code = <<EOF
exports.handler = async (event) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};
EOF
}

# Create an IAM role for the Lambda function
resource "aws_iam_role" "lambda_exec" {
  name = "lambda_exec_role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

# Attach the AWSLambdaBasicExecutionRole policy to the Lambda role
resource "aws_iam_role_policy_attachment" "lambda_policy" {
  role       = aws_iam_role.lambda_exec.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

# Create an API Gateway REST API
resource "aws_api_gateway_rest_api" "example" {
  name = "example_api"
}

# Create a resource within the API Gateway
resource "aws_api_gateway_resource" "example" {
  rest_api_id = aws_api_gateway_rest_api.example.id
  parent_id   = aws_api_gateway_rest_api.example.root_resource_id
  path_part   = "example"
}

# Define a GET method for the resource
resource "aws_api_gateway_method" "example" {
  rest_api_id   = aws_api_gateway_rest_api.example.id
  resource_id   = aws_api_gateway_resource.example.id
  http_method   = "GET"
  authorization = "NONE"
}

# Configure Lambda integration for the method
resource "aws_api_gateway_integration" "example" {
  rest_api_id             = aws_api_gateway_rest_api.example.id
  resource_id             = aws_api_gateway_resource.example.id
  http_method             = aws_api_gateway_method.example.http_method
  integration_type        = "AWS_PROXY"
  integration_target_arn = aws_lambda_function.example.invoke_arn
}

# Deploy the API Gateway changes
resource "aws_api_gateway_deployment" "example" {
  rest_api_id = aws_api_gateway_rest_api.example.id
  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_integration.example))
  }
}

# Configure a stage for the deployment
resource "aws_api_gateway_stage" "example" {
  deployment_id = aws_api_gateway_deployment.example.id
  rest_api_id   = aws_api_gateway_rest_api.example.id
  stage_name    = "example"
}

# Output the API Gateway endpoint URL
output "api_gateway_url" {
  value = "https://${aws_api_gateway_rest_api.example.id}.execute-api.${var.region}.amazonaws.com/${aws_api_gateway_stage.example.stage_name}/example"
}

Explanation:

  1. Provider and Variables:

    • Defines the AWS provider and sets up variables for the region and Lambda function name.
  2. Lambda Function:

    • Creates a simple Node.js Lambda function that returns "Hello from Lambda!"
    • Defines an IAM role for the function with necessary permissions.
  3. API Gateway Resources:

    • Creates an API Gateway REST API.
    • Defines a resource /example within the API.
    • Creates a GET method for the /example resource.
  4. API Gateway Integration:

    • Configures a Lambda proxy integration for the GET method, connecting it to the Lambda function.
  5. Deployment and Stage:

    • Deploys the API Gateway changes.
    • Creates a stage named "example" for the deployment.
  6. Output:

    • Outputs the API Gateway endpoint URL, which you can use to access your API.

To use this code:

  1. Replace placeholders:
    • Update variable "lambda_function_name" with your desired Lambda function name.
    • Replace the placeholder Lambda function code with your actual implementation.
  2. Run Terraform:
    • Initialize Terraform: terraform init
    • Apply the configuration: terraform apply
  3. Access your API:
    • The output will show the api_gateway_url. You can use this URL to make GET requests to your API.

Additional Notes

1. API Gateway Resource:

  • This is the root resource for your API.
  • The name attribute defines the friendly name for your API in the AWS console.
  • Consider adding a description attribute to document the purpose of your API.

2. API Gateway Resource:

  • This creates a sub-resource under the root path. In this case, the path will be /example.
  • You can create multiple resources with different path_part values to define your API's structure.
  • For complex APIs, consider organizing resources logically using nested structures.

3. API Gateway Method:

  • This defines an HTTP method (GET in this case) that can be used to access the resource.
  • You can define multiple methods (e.g., POST, PUT, DELETE) for a single resource.
  • The authorization attribute controls access to the method. NONE means no authorization is required. Consider using other options like AWS_IAM or custom authorizers for production APIs.

4. API Gateway Integration:

  • This specifies how API Gateway handles requests to the method.
  • AWS_PROXY means API Gateway forwards the entire request to the Lambda function and returns the function's response directly.
  • integration_target_arn points to the Lambda function that will handle the requests.
  • For non-Lambda integrations, you can specify other targets like HTTP endpoints or AWS services.

5. API Gateway Deployment:

  • This deploys the API changes you've made.
  • The triggers attribute ensures a new deployment occurs whenever the integration configuration changes.
  • You can add more triggers based on other resources if needed.

6. API Gateway Stage:

  • Stages represent different environments for your API (e.g., dev, test, prod).
  • Each stage can have its own configuration settings like throttling, caching, and logging.
  • The stage_name attribute defines the URL path for accessing this stage.

General Notes:

  • Error Handling: The provided code doesn't include error handling. Consider adding logic to your Lambda function and API Gateway configuration to handle errors gracefully and return appropriate responses to clients.
  • Security: For production APIs, implement robust authentication and authorization mechanisms. Explore API Gateway features like API keys, IAM authentication, Lambda authorizers, and Cognito user pools.
  • Monitoring and Logging: Set up monitoring and logging for your API Gateway and Lambda functions to track performance, troubleshoot issues, and gain insights into API usage.
  • Documentation: Document your API using OpenAPI specifications (formerly Swagger) to help developers understand and use your API effectively.
  • Terraform Best Practices: Follow Terraform best practices like using modules, managing state files securely, and implementing CI/CD pipelines for infrastructure deployments.

Summary

This code defines a simple REST API using AWS API Gateway and Terraform. Here's a breakdown:

  1. API Gateway Creation: An API Gateway instance named "example" is created.
  2. Resource Definition: A resource with path "/example" is added to the API Gateway.
  3. Method Configuration: The resource is configured to accept GET requests without authorization.
  4. Integration Setup: The GET method is integrated with a Lambda function, using the "AWS_PROXY" integration type to forward requests and responses directly.
  5. Deployment: The API Gateway configuration is deployed, triggering the creation of a deployable API version.
  6. Stage Creation: A stage named "example" is created for the deployment, making the API accessible.

In essence, this code sets up a basic API endpoint that, when called with a GET request, invokes a specified Lambda function.

Conclusion

This guide demonstrated how to create a basic API Gateway proxy integrated with a Lambda function using Terraform. By following these steps, you can establish a foundational understanding of leveraging Terraform to manage and automate your API Gateway infrastructure. Remember to explore additional API Gateway features and security best practices as you develop more complex and robust APIs.

References

Were You Able to Follow the Instructions?

😍Love it!
😊Yes
😐Meh-gical
😞No
🤮Clickbait