Skip to content

Terraform module for redirecting a root/apex site with CloudFront with an SSL certificate (e.g., from ACM)

License

Notifications You must be signed in to change notification settings

riboseinc/terraform-aws-s3-cloudfront-redirect

Repository files navigation

Terraform module to setup a S3 redirection site with CloudFront, ACM

This module helps you create a S3 website that performs HTTPS redirection, assuming that:

  • it runs HTTPS via Amazon’s Certificate Manager ("ACM")

  • its domain is backed by a Route53 zone

  • and of course, your AWS account provides you access to all these resources necessary.

This module is available on the Terraform Registry.

This module is a pair with terraform-aws-s3-cloudfront-website, which handles hosting of a static S3 website with CloudFront and ACM.

Sample Usage

You can literally copy and paste the following example, change the following attributes, and you’re ready to go:

  • fqdn set to your static website’s hostname

  • redirect_target set to where you want the hostname to redirect to (e.g. example.com ⇒ (this one) www.example.com)

# AWS Region for S3 and other resources
provider "aws" {
  region = "us-west-2"
  alias = "main"
}

# AWS Region for Cloudfront (ACM certs only supports us-east-1)
provider "aws" {
  region = "us-east-1"
  alias = "cloudfront"
}

# Variables
variable "fqdn" {
  description = "The fully-qualified domain name root of the resulting S3 website."
  default     = "example.com"
}

variable "redirect_target" {
  description = "The fully-qualified domain name to redirect to."
  default     = "www.example.com"
}

# Using this module
module "main" {
  source = "github.com/riboseinc/terraform-aws-s3-cloudfront-redirect"

  fqdn = "${var.fqdn}"
  redirect_target = "${var.redirect_target}"
  ssl_certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}"

  refer_secret = "${base64sha512("REFER-SECRET-19265125-${var.fqdn}-52865926")}"
  force_destroy = "true"

  providers = {
    aws.main = aws.main
    aws.cloudfront = aws.cloudfront
  }

  # Optional WAF Web ACL ID, defaults to none.
  web_acl_id = "${data.terraform_remote_state.site.waf-web-acl-id}"
}

# ACM Certificate generation

resource "aws_acm_certificate" "cert" {
  provider          = "aws.cloudfront"
  domain_name       = "${var.fqdn}"
  validation_method = "DNS"
}

resource "aws_route53_record" "cert_validation" {
  provider = aws.cloudfront
  for_each = {
    for dvo in aws_acm_certificate.cert.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.main.zone_id
}

resource "aws_acm_certificate_validation" "cert" {
  provider                = aws.cloudfront
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}


# Route 53 record for the static site

data "aws_route53_zone" "main" {
  provider     = "aws.main"
  name         = "${var.fqdn}"
  private_zone = false
}

resource "aws_route53_record" "web" {
  provider = "aws.main"
  zone_id  = "${data.aws_route53_zone.main.zone_id}"
  name     = "${var.fqdn}"
  type     = "A"

  alias {
    name    = "${module.main.cf_domain_name}"
    zone_id = "${module.main.cf_hosted_zone_id}"
    evaluate_target_health = false
  }
}

# Outputs

output "s3_bucket_id" {
  value = "${module.main.s3_bucket_id}"
}

output "s3_domain" {
  value = "${module.main.s3_website_endpoint}"
}

output "s3_hosted_zone_id" {
  value = "${module.main.s3_hosted_zone_id}"
}

output "cloudfront_domain" {
  value = "${module.main.cf_domain_name}"
}

output "cloudfront_hosted_zone_id" {
  value = "${module.main.cf_hosted_zone_id}"
}

output "cloudfront_distribution_id" {
  value = "${module.main.cf_distribution_id}"
}

output "route53_fqdn" {
  value = "${aws_route53_record.web.fqdn}"
}

output "acm_certificate_arn" {
  value = "${aws_acm_certificate_validation.cert.certificate_arn}"
}

Upgrading instructions

Note
In this section you need to have tfenv installed.

Upgrading from Terraform 0.13/0.14 to 0.15

Remove the version restriction on the module:

module "site-root" {
  source = "github.com/riboseinc/terraform-aws-s3-cloudfront-redirect"
  # ...
}

Then:

tfenv use 0.15.4
terraform init -upgrade
terraform plan

When upgrading to 0.15.4, you need to update the ACM config from:

Original:

resource "aws_route53_record" "cert_validation" {
  provider = aws.cloudfront
  name     = aws_acm_certificate.cert.domain_validation_options[0].resource_record_name
  type     = aws_acm_certificate.cert.domain_validation_options[0].resource_record_type
  zone_id  = data.aws_route53_zone.main.id
  records  = [aws_acm_certificate.cert.domain_validation_options[0].resource_record_value]
  ttl      = 60
}

resource "aws_acm_certificate_validation" "cert" {
  provider                = aws.cloudfront
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [aws_route53_record.cert_validation.fqdn]
}

Now:

resource "aws_route53_record" "cert_validation" {
  provider = aws.cloudfront
  for_each = {
    for dvo in aws_acm_certificate.cert.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.main.zone_id
}

resource "aws_acm_certificate_validation" "cert" {
  provider                = aws.cloudfront
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

Upgrading from Terraform 0.12 to 0.13

First, link the module to a version that supported 0.13:

module "site-root" {
  source = "github.com/riboseinc/terraform-aws-s3-cloudfront-redirect?ref=b4ab4a1ec7f373484074b27c73d93ce4bbe60b14"
  # ...
}

Assume you are using Terraform 0.12, update module version and verify that you can run Terraform properly:

tfenv use 0.12.31
terraform init -upgrade

If all went well, you can use Terraform 0.13, and upgrade the providers:

tfenv use 0.13.7
terraform 0.13upgrade -yes
terraform init -upgrade
terraform state replace-provider -auto-approve registry.terraform.io/-/aws hashicorp/aws
terraform state replace-provider -auto-approve registry.terraform.io/-/null registry.terraform.io/hashicorp/null
terraform state replace-provider -auto-approve registry.terraform.io/-/archive registry.terraform.io/hashicorp/archive
terraform state replace-provider -auto-approve registry.terraform.io/-/local registry.terraform.io/hashicorp/local

Then this will succeed:

terraform plan
terraform apply -auto-approve

Upgrading to Terraform 0.12

This module now supports Terraform 0.12.

To upgrade to Terraform 0.12 using this module, do this:

terraform init -upgrade
terraform 0.12upgrade
terraform plan
terraform apply -auto-approve

About

Terraform module for redirecting a root/apex site with CloudFront with an SSL certificate (e.g., from ACM)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages