Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions static-site/acm.tf
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
resource "aws_acm_certificate" "cloudfront_cert" {
resource "aws_acm_certificate" "this" {
domain_name = local.primary_domain
subject_alternative_names = local.domains
subject_alternative_names = var.domains
validation_method = "DNS"
tags = var.tags
provider = aws.acm

lifecycle {
create_before_destroy = true
}
}

resource "aws_acm_certificate_validation" "cloudfront_cert_validation" {
certificate_arn = aws_acm_certificate.cloudfront_cert.arn
validation_record_fqdns = [for record in aws_route53_record.acm_records : record.fqdn]
provider = aws.acm
}
resource "aws_acm_certificate_validation" "this" {
certificate_arn = aws_acm_certificate.this.arn
validation_record_fqdns = [
for record in aws_route53_record.acm_records : record.fqdn
if contains(local.internal_domains, record.fqdn)
]
provider = aws.acm
}
36 changes: 22 additions & 14 deletions static-site/cloudfront.tf
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
locals {
origin_id = "S3-${aws_s3_bucket.static_site.bucket}"
origin_id = "s3-static-site"
origin_path = var.origin_path == "" ? "" : var.origin_path
bucket_regional_domain_name = var.create_bucket ? aws_s3_bucket.this[0].bucket_regional_domain_name : data.aws_s3_bucket.user_created[0].bucket_regional_domain_name
oac_name = replace(
replace("${local.bucket_name}-${replace(local.origin_path, "/", "-")}-oac", "--", "-"),
"/[^a-zA-Z0-9.-]/",
""
)
rhp_name = "${local.primary_domain_normalised}-cf-rhp"
}

resource "aws_cloudfront_distribution" "static_site" {
resource "aws_cloudfront_distribution" "this" {
comment = "Distribution for ${local.primary_domain}"
aliases = local.domains
aliases = var.domains
enabled = true
is_ipv6_enabled = true
default_root_object = "index.html"

viewer_certificate {
acm_certificate_arn = aws_acm_certificate.cloudfront_cert.arn
acm_certificate_arn = aws_acm_certificate.this.arn
ssl_support_method = "sni-only"
minimum_protocol_version = var.viewer_certificate.minimum_protocol_version
cloudfront_default_certificate = false
Expand All @@ -25,14 +33,14 @@ resource "aws_cloudfront_distribution" "static_site" {

origin {
origin_id = local.origin_id
origin_access_control_id = aws_cloudfront_origin_access_control.oac.id
domain_name = aws_s3_bucket.static_site.bucket_regional_domain_name
origin_path = var.origin_path != "" ? "/${var.origin_path}" : ""
origin_access_control_id = aws_cloudfront_origin_access_control.this.id
domain_name = local.bucket_regional_domain_name
origin_path = local.origin_path
}

default_cache_behavior {
target_origin_id = local.origin_id
response_headers_policy_id = aws_cloudfront_response_headers_policy.cloudfront.id
response_headers_policy_id = aws_cloudfront_response_headers_policy.this.id

allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
Expand Down Expand Up @@ -63,21 +71,21 @@ resource "aws_cloudfront_distribution" "static_site" {
}

tags = var.tags
depends_on = [aws_acm_certificate_validation.cloudfront_cert_validation]
depends_on = [aws_acm_certificate_validation.this]
provider = aws.default
}

resource "aws_cloudfront_origin_access_control" "oac" {
name = "oac-for-${aws_s3_bucket.static_site.bucket}"
description = "OAC for ${aws_s3_bucket.static_site.bucket}"
resource "aws_cloudfront_origin_access_control" "this" {
name = local.oac_name
description = "OAC for ${local.bucket_name}"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
provider = aws.default
}

resource "aws_cloudfront_response_headers_policy" "cloudfront" {
name = "cf-resp-hdrs-${local.primary_domain_normalised}"
resource "aws_cloudfront_response_headers_policy" "this" {
name = local.rhp_name
comment = "Response headers policy for ${local.primary_domain}"

cors_config {
Expand Down
17 changes: 13 additions & 4 deletions static-site/data.tf
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
locals {
custom_prefix = startswith(local.origin_path, "/") ? substr(local.origin_path, 1, length(local.origin_path)) : local.origin_path
bucket_prefix = local.origin_path == "" ? "*" : "${local.custom_prefix}/*"
}
data "aws_caller_identity" "current" {}

data "aws_route53_zone" "hosted_zone" {
data "aws_route53_zone" "this" {
count = local.create_hosted_zone ? 0 : 1
name = var.hosted_zone
private_zone = false
}

data "aws_s3_bucket" "user_created" {
count = !var.create_bucket ? 1 : 0
bucket = var.bucket_name
}

data "aws_iam_policy_document" "cloudfront_to_s3" {
statement {
sid = "AllowCloudFrontToAccessBucket"
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.static_site.arn}/*"]
resources = ["${local.bucket_arn}/${local.bucket_prefix}"]

principals {
type = "Service"
Expand All @@ -20,7 +29,7 @@ data "aws_iam_policy_document" "cloudfront_to_s3" {
condition {
test = "StringEquals"
variable = "AWS:SourceArn"
values = [aws_cloudfront_distribution.static_site.arn]
values = [aws_cloudfront_distribution.this.arn]
}

condition {
Expand All @@ -29,4 +38,4 @@ data "aws_iam_policy_document" "cloudfront_to_s3" {
values = [data.aws_caller_identity.current.account_id]
}
}
}
}
20 changes: 15 additions & 5 deletions static-site/locals.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
locals {
domains = distinct(var.domains)
primary_domain = local.domains[0]

primary_domain_normalised = replace(local.primary_domain, ".", "-")

create_hosted_zone = var.hosted_zone == ""
hosted_zone_domain = local.create_hosted_zone ? local.primary_domain : data.aws_route53_zone.this[0].name
primary_domain = var.domains[0]
primary_domain_normalised = replace(
replace(local.primary_domain, "/\\*\\./", ""), # remove wildcard prefix
"/[^a-zA-Z0-9-]/", "-" # replace anything else with -
)
internal_domains = [
for d in var.domains : d
if endswith(d, local.hosted_zone_domain)
]

bucket_name = var.bucket_name == "" ? local.primary_domain : var.bucket_name
bucket_arn = var.create_bucket ? aws_s3_bucket.this[0].arn : data.aws_s3_bucket.user_created[0].arn
}

output "internal_domains" {
value = local.internal_domains
}
24 changes: 18 additions & 6 deletions static-site/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
output "bucket" {
value = {
arn = aws_s3_bucket.static_site.arn
id = aws_s3_bucket.static_site.id
arn = var.create_bucket ? aws_s3_bucket.this[0].arn : data.aws_s3_bucket.user_created[0].arn
id = local.bucket_name
}
}

output "cloudfront" {
value = {
arn = aws_cloudfront_distribution.static_site.arn
id = aws_cloudfront_distribution.static_site.id
domain_name = aws_cloudfront_distribution.static_site.domain_name
aliases = aws_cloudfront_distribution.static_site.aliases
arn = aws_cloudfront_distribution.this.arn
id = aws_cloudfront_distribution.this.id
domain_name = aws_cloudfront_distribution.this.domain_name
aliases = aws_cloudfront_distribution.this.aliases
}
}

output "external_validation_records" {
value = {
for dvo in aws_acm_certificate.this.domain_validation_options :
dvo.domain_name => {
name = dvo.resource_record_name
value = dvo.resource_record_value
type = dvo.resource_record_type
}
if !contains(local.internal_domains, dvo.domain_name)
}
}
31 changes: 18 additions & 13 deletions static-site/route53.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
resource "aws_route53_zone" "hosted_zone" {
resource "aws_route53_zone" "this" {
count = local.create_hosted_zone ? 1 : 0
name = local.primary_domain
tags = var.tags
Expand All @@ -9,37 +9,42 @@ resource "aws_route53_zone" "hosted_zone" {
#############################################
resource "aws_route53_record" "acm_records" {
for_each = {
for dvo in aws_acm_certificate.cloudfront_cert.domain_validation_options : dvo.domain_name => {
for dvo in aws_acm_certificate.this.domain_validation_options :
dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}

zone_id = local.create_hosted_zone ? aws_route53_zone.hosted_zone[0].zone_id : data.aws_route53_zone.hosted_zone[0].zone_id
type = each.value.type
name = each.value.name
records = [each.value.record]
ttl = 60
zone_id = try(aws_route53_zone.this[0].zone_id, data.aws_route53_zone.this[0].zone_id)
type = each.value.type
name = each.value.name
records = [each.value.record]
ttl = 60

allow_overwrite = true
provider = aws.default

provider = aws.default
}

#############################################
# Setup the A record for your custom domain
#############################################
resource "aws_route53_record" "static_site_a_record" {
count = length(local.domains)
count = length(var.domains)

zone_id = local.create_hosted_zone ? aws_route53_zone.hosted_zone[0].zone_id : data.aws_route53_zone.hosted_zone[0].zone_id
zone_id = try(aws_route53_zone.this[0].zone_id, data.aws_route53_zone.this[0].zone_id)
type = "A"
name = local.domains[count.index]
name = var.domains[count.index]

alias {
name = aws_cloudfront_distribution.static_site.domain_name
zone_id = aws_cloudfront_distribution.static_site.hosted_zone_id
name = aws_cloudfront_distribution.this.domain_name
zone_id = aws_cloudfront_distribution.this.hosted_zone_id
evaluate_target_health = false
}

allow_overwrite = true

provider = aws.default
}
12 changes: 6 additions & 6 deletions static-site/s3.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
resource "aws_s3_bucket" "static_site" {
resource "aws_s3_bucket" "this" {
count = var.create_bucket ? 1 : 0

bucket = local.bucket_name
Expand All @@ -7,17 +7,17 @@ resource "aws_s3_bucket" "static_site" {
provider = aws.default
}

resource "aws_s3_bucket_public_access_block" "static_site" {
bucket = var.bucket_name != "" ? var.bucket_name : aws_s3_bucket.static_site[0].id
resource "aws_s3_bucket_public_access_block" "this" {
bucket = var.bucket_name != "" ? var.bucket_name : aws_s3_bucket.this[0].id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
provider = aws.default
}

resource "aws_s3_bucket_policy" "static_site" {
bucket = var.bucket_name != "" ? var.bucket_name : aws_s3_bucket.static_site[0].bucket
resource "aws_s3_bucket_policy" "this" {
bucket = var.bucket_name != "" ? var.bucket_name : aws_s3_bucket.this[0].bucket
policy = data.aws_iam_policy_document.cloudfront_to_s3.json
provider = aws.default
}
}
Loading