Create AWS API Gateway Custom Domain Route 53 with SSL certificate using Terraform
Hello readers this article is a continuation of the previous one where we created a AWS Lambda with Terraform API Gateway
So if you are on track with that resource, let get started
To set up a custom domain with terraform, we still need to follow the same workflow. First, we need to issue a TLS certificate.
terraform/7-certificate.tf
resource "aws_acm_certificate" "api" {
domain_name = "api.rose-tech.net"
validation_method = "DNS"
}
data "aws_route53_zone" "public" {
name = "rose-tech.net"
private_zone = false
}
resource "aws_route53_record" "api_validation" {
for_each = {
for dvo in aws_acm_certificate.api.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = data.aws_route53_zone.public.zone_id
}
resource "aws_acm_certificate_validation" "api" {
certificate_arn = aws_acm_certificate.api.arn
validation_record_fqdns = [for record in aws_route53_record.api_validation : record.fqdn]
}
The next step is to create a custom domain using terraform. Specify the domain name, which should match the certificate.
terraform/8-custom-domain-name.tf
resource "aws_apigatewayv2_domain_name" "api" {
domain_name = "api.rose-tech.net"
domain_name_configuration {
certificate_arn = aws_acm_certificate.api.arn
endpoint_type = "REGIONAL"
security_policy = "TLS_1_2"
}
depends_on = [aws_acm_certificate_validation.api]
}
resource "aws_route53_record" "api" {
name = aws_apigatewayv2_domain_name.api.domain_name
type = "A"
zone_id = data.aws_route53_zone.public.zone_id
alias {
name = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].target_domain_name
zone_id = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].hosted_zone_id
evaluate_target_health = false
}
}
In the last file, let's create API mapping. The first one is for the base path. And the second one is to map the staging stage with the v1 path.
terraform/9-api-mapping.tf
resource "aws_apigatewayv2_api_mapping" "api" {
api_id = aws_apigatewayv2_api.main.id
domain_name = aws_apigatewayv2_domain_name.api.id
stage = aws_apigatewayv2_stage.staging.id
}
resource "aws_apigatewayv2_api_mapping" "api_v1" {
api_id = aws_apigatewayv2_api.main.id
domain_name = aws_apigatewayv2_domain_name.api.id
stage = aws_apigatewayv2_stage.staging.id
api_mapping_key = "v1"
}
output "custom_domain_api" {
value = "https://${aws_apigatewayv2_api_mapping.api.domain_name}"
}
output "custom_domain_api_v1" {
value = "https://${aws_apigatewayv2_api_mapping.api_v1.domain_name}/${aws_apigatewayv2_api_mapping.api_v1.api_mapping_key}"
}
Run terraform
terraform init
terraform apply
Test with curl or with browser.
curl -X POST \
> -H "Content-Type: application/json" \
> -d '{"name":"Antoine"}' \
> "https://api.rose-tech.net/hello"
curl "https://api.rose-tech.net/hello?Name=Antoine"