Skip to content

Commit

Permalink
Merge pull request #1465 from alphagov/api-gateway-for-search
Browse files Browse the repository at this point in the history
Add API Gateway for Search-API
  • Loading branch information
sihugh authored Oct 16, 2024
2 parents 840244d + 34ba13d commit 09c9ad1
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
resource "aws_api_gateway_domain_name" "search_api_domain" {
domain_name = var.search_api_domain
certificate_arn = var.publishing_certificate_arn
}

# VPC Link to allow API Gateway to connect to the search load balancer
resource "aws_api_gateway_vpc_link" "search_vpc_link" {
name = "search_api_vpc_link"
target_arns = [
var.search_api_lb_arn
]
}

resource "aws_api_gateway_rest_api" "search_rest_api" {
name = "search_api"
description = "API Gateway for Search API"

endpoint_configuration {
types = ["EDGE"] # "Edge-optimized" routes traffic through CloudFront
}
}

resource "aws_api_gateway_resource" "search_resource" {
rest_api_id = aws_api_gateway_rest_api.search_rest_api.id
parent_id = aws_api_gateway_rest_api.search_rest_api.root_resource_id
path_part = "search.json"
}

resource "aws_api_gateway_method" "get_search_method" {
rest_api_id = aws_api_gateway_rest_api.search_rest_api.id
resource_id = aws_api_gateway_resource.search_resource.id
http_method = "GET"
authorization = "NONE" # We can add API keys or other auth options should we need them
}

# Connect to the Search-API-v2 load balancer
resource "aws_api_gateway_integration" "search_lb_integration" {
rest_api_id = aws_api_gateway_rest_api.search_rest_api.id
resource_id = aws_api_gateway_resource.search_resource.id
http_method = aws_api_gateway_method.get_search_method.http_method
integration_http_method = "GET"
type = "HTTP_PROXY"
connection_type = "VPC_LINK"
connection_id = aws_api_gateway_vpc_link.search_vpc_link.id
uri = var.search_api_lb_dns_name
}

# Create a deployment for the API Gateway
resource "aws_api_gateway_deployment" "search_deployment" {
rest_api_id = aws_api_gateway_rest_api.search_rest_api.id
stage_name = "v0.1" # Version embedded in the published URL
}

# Map API Gateway stages to custom domain
resource "aws_api_gateway_base_path_mapping" "search_api_mapping" {
domain_name = aws_api_gateway_domain_name.search_api_domain.domain_name
api_id = aws_api_gateway_rest_api.search_rest_api.id
}

# WAF settings
resource "aws_wafv2_web_acl" "search_api_waf" {
name = "search-api-waf"
description = "WAF for Search API with rate limiting"
scope = "CLOUDFRONT"

default_action {
allow {}
}

rule {
name = "rate-limit-rule"
priority = 1
action {
block {}
}

statement {
rate_based_statement {
limit = 100 # Limit 100 requests per IP in 5 minutes
aggregate_key_type = "IP"
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "search-api-rate-limit-rule"
sampled_requests_enabled = true
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "search-api-waf"
sampled_requests_enabled = true
}
}

resource "aws_wafv2_web_acl_association" "waf_association" {
resource_arn = aws_api_gateway_domain_name.search_api_domain.cloudfront_domain_name
web_acl_arn = aws_wafv2_web_acl.search_api_waf.arn
}

resource "aws_shield_protection" "search_api_shield" {
name = "search-api-shield"
resource_arn = aws_api_gateway_rest_api.search_rest_api.execution_arn
}


output "api_gateway_cname" {
value = aws_api_gateway_domain_name.search_api_domain.cloudfront_domain_name
description = "CNAME to use in your DNS settings"
}
20 changes: 20 additions & 0 deletions terraform/deployments/govuk-publishing-infrastructure/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,23 @@ variable "shared_documentdb_backup_retention_period" {
default = 5
description = "Number of days to keep shared DocumentDB backups for"
}

variable "search_api_lb_arn" {
type = string
description = "The ARN of the search-api-v2 load balancer"
}

variable "search_api_lb_dns_name" {
type = string
description = "The DNS name of the search-api-v2 load balancer"
}

variable "search_api_domain" {
type = string
description = "The domain name of the API gateway"
}

variable "publishing_certificate_arn" {
type = string
description = "The ARN of the publishing certificate"
}

0 comments on commit 09c9ad1

Please sign in to comment.