Skip to content

Instantly share code, notes, and snippets.

@xonev
Created October 12, 2023 04:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xonev/00ae4117688537d30bc88f613a8609f4 to your computer and use it in GitHub Desktop.
Save xonev/00ae4117688537d30bc88f613a8609f4 to your computer and use it in GitHub Desktop.
Example static site with Cloudfront/S3
locals {
example_app_origin_id = "example-app-site-origin"
example_app_domain = "app.example.com"
}
data "aws_route53_zone" "example_com" {
name = "example.com"
private_zone = false
}
resource "aws_s3_bucket" "example_app_site" {
bucket = "example-app-site"
}
resource "aws_route53_record" "app_example_com" {
zone_id = data.aws_route53_zone.example_com.zone_id
name = local.example_app_domain
type = "A"
alias {
name = aws_cloudfront_distribution.example_app.domain_name
zone_id = aws_cloudfront_distribution.example_app.hosted_zone_id
evaluate_target_health = true
}
}
resource "aws_cloudfront_distribution" "example_app" {
origin {
domain_name = aws_s3_bucket.example_app_site.bucket_regional_domain_name
origin_id = local.example_app_origin_id
origin_access_control_id = aws_cloudfront_origin_access_control.example_app.id
}
aliases = [local.example_app_domain]
default_root_object = "index.html"
enabled = true
http_version = "http2and3"
is_ipv6_enabled = true
# North America and Europe only
price_class = "PriceClass_100"
restrictions {
geo_restriction {
locations = []
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.example_app.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = local.example_app_origin_id
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
}
}
resource "aws_acm_certificate" "example_app" {
provider = aws.use1
domain_name = "app.example.com"
validation_method = "DNS"
}
resource "aws_route53_record" "example_app_domain_validations" {
for_each = {
for dvo in aws_acm_certificate.example_app.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.example_com.zone_id
}
resource "aws_acm_certificate_validation" "example_app" {
provider = aws.use1
certificate_arn = aws_acm_certificate.example_app.arn
validation_record_fqdns = [for record in aws_route53_record.example_app_domain_validations : record.fqdn]
}
resource "aws_s3_bucket_policy" "example_app_cloudfront_access" {
bucket = aws_s3_bucket.example_app_site.id
policy = data.aws_iam_policy_document.allow_access_from_cloudfront.json
}
data "aws_iam_policy_document" "allow_access_from_cloudfront" {
policy_id = "PolicyForCloudFrontPrivateContent"
statement {
sid = "AllowCloudFrontServicePrincipal"
principals {
type = "Service"
identifiers = ["cloudfront.amazonaws.com"]
}
actions = ["s3:GetObject"]
resources = [
aws_s3_bucket.example_app_site.arn,
"${aws_s3_bucket.example_app_site.arn}/*"
]
condition {
test = "StringEquals"
variable = "AWS:SourceArn"
values = [aws_cloudfront_distribution.example_app.arn]
}
}
}
resource "aws_cloudfront_origin_access_control" "example_app" {
name = "example-app"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment