DEV Community

Cover image for AWS Networking with Terraform : Deploying a CloudFront with Primary and Failover Access Origin
Chinmay Tonape
Chinmay Tonape

Posted on

AWS Networking with Terraform : Deploying a CloudFront with Primary and Failover Access Origin

In our previous post, we integrated CloudFront distribution with website applications hosted on EC2 instances. Building upon that foundation, we now shift our focus to a critical aspect of cloud architecture: high availability origin failover.

In this blog post, we'll see how CloudFront can be used to fortify the resilience of your infrastructure, employing Terraform to prepare the setup seamlessly.

Architecture Overview:

Before diving into the implementation details, let's sketch out the architecture we'll be constructing:

S3 Failover Architecture

CloudFront Origin Failover

Step 1: Creating Primary and Failover S3 Buckets:

Firstly, we'll set up two distinct S3 buckets, each serving as a primary and failover origin respectively. These buckets will host the static website content.

####################################################
# Create S3 Static Website
####################################################
module "s3_primary" {
  source        = "./modules/s3-static-website"
  bucket_name   = var.bucket_name_primary
  source_files  = "webfiles"
  common_tags   = local.common_tags
  naming_prefix = local.naming_prefix
}


module "s3_failover" {
  source        = "./modules/s3-static-website"
  bucket_name   = var.bucket_name_failover
  source_files  = "webfiles_failover"
  common_tags   = local.common_tags
  naming_prefix = local.naming_prefix
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Configuring CloudFront Distribution:

Next, we'll craft a CloudFront distribution, integrating both the primary and failover S3 buckets as origins. This configuration helps CloudFront to dynamically switch to the failover origin in case of an outage or unavailability of the primary source.

####################################################
# Create AWS Cloudfront distribution
####################################################
resource "aws_cloudfront_origin_access_control" "cf-s3-oac" {
  name                              = "CloudFront S3 OAC"
  description                       = "CloudFront S3 OAC"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "cf-dist" {
  enabled             = true
  default_root_object = "index.html"

  origin_group {
    origin_id = "origin_group_id"
    failover_criteria {
      status_codes = [403, 404, 500, 502, 503, 504]
    }
    member {
      origin_id = "s3_primary"
    }
    member {
      origin_id = "s3_failover"
    }
  }

  origin {
    domain_name              = data.aws_s3_bucket.s3_primary.bucket_regional_domain_name
    origin_id                = "s3_primary"
    origin_access_control_id = aws_cloudfront_origin_access_control.cf-s3-oac.id
  }

  origin {
    domain_name              = data.aws_s3_bucket.s3_failover.bucket_regional_domain_name
    origin_id                = "s3_failover"
    origin_access_control_id = aws_cloudfront_origin_access_control.cf-s3-oac.id
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "origin_group_id"
    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }
    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 360
    max_ttl                = 86400
  }

  price_class = "PriceClass_All"

  restrictions {
    geo_restriction {
      restriction_type = "whitelist"
      locations        = ["IN", "US", "CA"]
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }

  tags = merge(var.common_tags, {
    Name = "${var.naming_prefix}-cloudfront"
  })
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Updating S3 Bucket Policies:

To facilitate seamless communication between CloudFront and the S3 buckets, we'll adjust the bucket policies accordingly.

####################################################
# S3 bucket policy to allow access from cloudfront
####################################################
data "aws_iam_policy_document" "s3_bucket_policy" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["${var.bucket_arn}/*"]
    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "AWS:SourceArn"
      values   = [var.cloudfront_distribution_arn]
    }
  }
}

resource "aws_s3_bucket_policy" "static_site_bucket_policy" {
  bucket = var.bucket_id
  policy = data.aws_iam_policy_document.s3_bucket_policy.json
}
Enter fullscreen mode Exit fullscreen mode

Steps to Run Terraform

Follow these steps to execute the Terraform configuration:

terraform init
terraform plan 
terraform apply -auto-approve
Enter fullscreen mode Exit fullscreen mode

Upon successful completion, Terraform will provide relevant outputs.

Apply complete! Resources: 9 added, 0 changed, 0 destroyed.

Outputs:

cloudfront_domain_name = "http://d1rwkmekbjnbkd.cloudfront.net"
Enter fullscreen mode Exit fullscreen mode

Testing the outcome

S3 Primary and Failover Buckets

S3 Bukcets

CloudFront Distribution:

CF Distribution

CloudFront Distribution Origin as S3 primary and failover and origin group

CF Origin

CF Origin

S3 Bucket Policy to allow access from cloudfront - primary and failover bucket

S3 Bucket Policy

S3 Bucket Policy

Using cloudfront domain name to access S3 static website

S3 Primary Origin

Failover to S3 failover bucket by removing s3 primary bucket policy manually from console (after TTL timeout)

S3 Failover Origin

Cleanup

Remember to stop AWS components to avoid large bills.

terraform destroy -auto-approve
Enter fullscreen mode Exit fullscreen mode

This how we can setup primary and failover access originas for CloudFront distribution for creating a robust high available architecture.

In our subsequent module, we'll embark on a journey into the realm of containerization with AWS, exploring how services like Amazon ECS can revolutionize application deployment and scalability.

Resources:

GitHub Repo: https://github.com/chinmayto/terraform-aws-cloudfront-s3-failover
AWS CloudFront: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html
AWS CloudFront Origin Failover: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/high_availability_origin_failover.html

Top comments (0)