Implementing Domain-Level Redirects with AWS CloudFront and Terraform
When building modern web applications, you often need to handle domain redirects efficiently and securely. Whether you're migrating domains, implementing vanity URLs, or managing multiple environments, having a robust redirect system is crucial. In this post, we'll explore how to implement domain-level redirects using AWS CloudFront and Terraform.
Architecture Overview
The solution uses several AWS services working together:
- CloudFront
- Handles the request routing and executes the redirect logic
- ACM (AWS Certificate Manager)
- Provides SSL/TLS certificates for secure communication
- Route 53
- Manages DNS records and routes traffic to CloudFront
- CloudFront Functions
- Implements the redirect logic
How It Works
- When a user visits the domain, Route 53 routes the request to CloudFront
- CloudFront executes a CloudFront Function on the viewer-request event
- The function returns a 307 redirect response to the desired destination
- The browser follows the redirect to the new location
Implementation
Here's the complete Terraform configuration with detailed explanations:
1# CloudFront Distribution 2# This handles the request routing and executes the redirect logic 3resource "aws_cloudfront_distribution" "redirects" { 4 tags = { 5 Name = "${local.prefix}-redirects" 6 Environment = terraform.workspace 7 } 8 depends_on = [aws_acm_certificate.redirect_cert] 9 10 # Origin configuration (required by CloudFront but not used for redirects) 11 origin { 12 domain_name = "example.com" 13 origin_id = "noop" 14 custom_origin_config { 15 http_port = 80 16 https_port = 443 17 origin_protocol_policy = "http-only" 18 origin_ssl_protocols = ["TLSv1", "TLSv1.1"] 19 } 20 } 21 22 enabled = true 23 is_ipv6_enabled = true 24 comment = "${local.prefix}-redirects distribution" 25 26 # Associate the SSL certificate with the distribution 27 aliases = [aws_acm_certificate.redirect_cert.domain_name] 28 29 viewer_certificate { 30 acm_certificate_arn = aws_acm_certificate.redirect_cert.arn 31 ssl_support_method = "sni-only" 32 minimum_protocol_version = "TLSv1.2_2019" 33 } 34 35 # Configure the default behavior to handle all requests 36 default_cache_behavior { 37 allowed_methods = ["GET", "HEAD"] 38 cached_methods = ["GET", "HEAD"] 39 target_origin_id = "noop" 40 41 viewer_protocol_policy = "redirect-to-https" 42 min_ttl = 0 43 44 # Associate the redirect function with the distribution 45 function_association { 46 event_type = "viewer-request" 47 function_arn = aws_cloudfront_function.redirects.arn 48 } 49 50 forwarded_values { 51 query_string = false 52 cookies { 53 forward = "none" 54 } 55 } 56 57 compress = true 58 } 59 60 restrictions { 61 geo_restriction { 62 restriction_type = "none" 63 } 64 } 65} 66 67# Route 53 A record to point the domain to CloudFront 68resource "aws_route53_record" "redirect" { 69 zone_id = aws_route53_zone.primary.zone_id 70 name = "" 71 type = "A" 72 73 alias { 74 name = aws_cloudfront_distribution.redirects.domain_name 75 zone_id = aws_cloudfront_distribution.redirects.hosted_zone_id 76 evaluate_target_health = false 77 } 78} 79 80# SSL Certificate configuration 81resource "aws_acm_certificate" "redirect_cert" { 82 provider = aws.us-east-1 # Certificates for CloudFront must be in us-east-1 83 84 domain_name = "example.com" 85 validation_method = "DNS" 86 87 lifecycle { 88 create_before_destroy = true 89 } 90} 91 92# DNS records for certificate validation 93resource "aws_route53_record" "redirect_cert_validation" { 94 for_each = { 95 for dvo in aws_acm_certificate.redirect_cert.domain_validation_options : dvo.domain_name => { 96 name = dvo.resource_record_name 97 record = dvo.resource_record_value 98 type = dvo.resource_record_type 99 } 100 } 101 102 allow_overwrite = true 103 name = each.value.name 104 records = [each.value.record] 105 ttl = 60 106 type = each.value.type 107 zone_id = aws_route53_zone.primary.zone_id 108} 109 110# Certificate validation 111resource "aws_acm_certificate_validation" "redirect_cert_validation" { 112 provider = aws.us-east-1 113 114 certificate_arn = aws_acm_certificate.redirect_cert.arn 115 validation_record_fqdns = [for record in aws_route53_record.redirect_cert_validation : record.fqdn] 116} 117 118# CloudFront Function for implementing redirect logic 119resource "aws_cloudfront_function" "redirects" { 120 name = "oma-domain-redirects" 121 runtime = "cloudfront-js-2.0" 122 comment = "redirects" 123 publish = true 124 code = <<EOF 125function handler(event) { 126 // Implement a 307 temporary redirect to the target domain 127 var response = { 128 statusCode: 307, 129 statusDescription: "Temporary Redirect", 130 headers: { 131 location: { value: "https://stage.example.com" }, 132 }, 133 }; 134 return response; 135} 136EOF 137}
Key Benefits
- Cost-Effective: CloudFront Functions are extremely cost-effective compared to Lambda@Edge
- Low Latency: The redirect happens at the edge, providing minimal latency for users
- Secure: All traffic is encrypted using SSL/TLS certificates
- Scalable: CloudFront automatically handles scaling based on traffic
- Maintainable: Infrastructure as code makes it easy to version and maintain
Customisation Options
The CloudFront Function can be customised to implement various redirect patterns:
- Path-based redirects
- Query parameter handling
- Custom header management
- A/B testing scenarios
- Geographic routing
Conclusion
This Terraform configuration provides a robust foundation for implementing domain-level redirects using AWS CloudFront. The solution is scalable, secure, and cost-effective, making it suitable for both small and large-scale applications.
Remember to replace example.com
with your actual domain name and adjust the CloudFront Function logic to match your specific redirect requirements.