Repository: ringods/terraform-website-s3-cloudfront-route53 Branch: master Commit: 7fb9f0a37a5f Files: 22 Total size: 30.4 KB Directory structure: gitextract_4uz35so_/ ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── r53-alias/ │ ├── main.tf │ ├── variables.tf │ └── versions.tf ├── r53-cname/ │ ├── main.tf │ ├── variables.tf │ └── versions.tf ├── site-main/ │ ├── deployer_role_policy.json │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ ├── versions.tf │ └── website_bucket_policy.json └── site-redirect/ ├── deployer_role_policy.json ├── main.tf ├── outputs.tf ├── variables.tf ├── versions.tf └── website_redirect_bucket_policy.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Created by .ignore support plugin (hsz.mobi) ### Terraform template # Compiled files *.tfstate *.tfstate.backup .terraform/ ================================================ FILE: CHANGELOG.md ================================================ ## 3.0.1 (April 26, 2017) IMPROVEMENTS: * Support for `trusted_signers` on the CloudFront distribution of module `site-main`. ## 3.0.0 (April 19, 2017) IMPROVEMENTS: * `bucket_name` is a required variable for module `site-main`. Bumped the major version as this is a breaking change. ## 2.0.3 (April 18, 2017) IMPROVEMENTS: * Adding the main website bucket arn as an output. ## 2.0.2 (April 18, 2017) IMPROVEMENTS: * Adding the main website bucket id as an output. ## 2.0.1 (April 6, 2017) IMPROVEMENTS: * Added `project` and `environment` variables to `site-main` and `site-redirect` modules * Added a general `tags` variable to `site-main` and `site-redirect` modules ## 2.0.0 (October 16, 2016) IMPROVEMENTS: * Upgraded the modules to be compatible with Terraform 0.7.x ## 1.0.0 (October 16, 2016) FEATURES: * Last version compatible with Terraform up to 0.6.x ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 Ringo De Smet Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ > [!IMPORTANT] > DEPRECATION NOTICE. This repository is no longer maintained. # Terraform setup for S3 static site with CloudFront, Certificate Manager and Route53 This Git repository contains the required [Terraform](https://www.terraform.io/) scripts to setup a static website, hosted out of an S3 bucket. The site is fronted by a CloudFront distribution, uses AWS Certificate Manager for HTTPS and allows for configuring the required DNS entries in Route53. The scripts also take care of: * Preventing the origin bucket being indexed by search bots. * Redirect other domains to the main site with proper rewriting. * Access logging * Redirect HTTP to HTTPS These scripts suite my needs, but all evolution in the form of pull requests are welcome! To make this process fluent, create [an issue](https://github.com/skyscrapers/terraform-website-s3-cloudfront-route53/issues) first describing what you want to contribute, then fork and create a branch with a clear name. Submit your work as a pull request. ## Introduction This repository is split in 4 parts, each of which can be used as a separate module in your own root script. The split is done because of the lack of conditional logic in Terraform 0.6.x. I leave the composition of the required setup to you, the user. * *site-main*: setup of the main S3 bucket with a CloudFront distribution * *site-redirect*: setup of the redirect S3 bucket with a CloudFront distribution * *r53-cname*: configuration of a Route53 CNAME record pointing to a CloudFront distribution * *r53-alias*: configuration of a Route53 ALIAS record pointing to a CloudFront distribution. Required for naked domain (APEX) setups. With the above 4 modules, you can pick yourself what you need for setups like: * single site on [https://sub.domain.com](https://sub.domain.com) * single site on [https://domain.com](https://domain.com) * main site on [https://www.domain.com](https://www.domain.com) and redirecting the naked domain to the www version. * main site on [https://domain.com](https://domain.com) and redirecting the www version to the naked domain. Given the ease of setting up SSL secured sites with AWS Certificate Manager, the above modules do not offer the option to set up non-SSL sites. But since AWS Certificate Manager requires manual intervention to complete the certificate setup, you must create your certificates first before using the modules below. _Note:_ AWS Certificate Manager supports multiple regions. To use CloudFront with ACM certificates, the certificates must be requested in region us-east-1. ## Configuring Terraform The different modules do not define variables for the AWS provider. For ease of use, the configuration is done implicitly by setting the following environment variables: * `AWS_SECRET_ACCESS_KEY` * `AWS_ACCESS_KEY_ID` * `AWS_DEFAULT_REGION` These variables are inherited by any Terraform modules and prevents passing too much TF variables from parent to module. This info was found [here](https://groups.google.com/d/msg/terraform-tool/GM1QisZ95qc/Pt8JqPVePHAJ). ## Setting up the main site Creating all the resources for an S3 based static website, with a CloudFront distribution and using the appropriate SSL certificates is as easy as using the `site-main` module and passing the appropriate variables: module "site-main" { source = "github.com/skyscrapers/terraform-website-s3-cloudfront-route53//site-main" region = "eu-west-1" domain = "my.domain.com" bucket_name = "site_mydomain" duplicate-content-penalty-secret = "some-secret-password" deployer = "an-iam-username" acm-certificate-arn = "arn:aws:acm:us-east-1::certificate/" not-found-response-path = "/404.html" } Mention the double slash. This is to indicate to look into the subdirectory within the Github repository. See the [Terraform Modules documentation](https://www.terraform.io/docs/modules/sources.html#github) for more info. ### Inputs * `region`: the AWS region where the S3 bucket will be created. The source bucket can be created in any of the available regions. The default value is `us-east-1`. * `domain`: the domain name by which you want to make the website available on the Internet. While we are not at the point of setting up the DNS part, the CloudFront distribution needs to know for which domain it needs to accept requests. * `bucket_name`: the name of the bucket to create for the S3 based static website. * `duplicate-content-penalty-secret`: Value that will be used in a custom header for a CloudFront distribution to gain access to the origin S3 bucket. If you make an S3 bucket available as the source for a CloudFront distribution, you have the risk of search bots to index both this source bucket and the distribution. Google _punishes_ you for this as you can read in [this article](https://support.google.com/webmasters/answer/66359?hl=en). We need to protect access to the source bucket. There are 2 options to prevent this: using an Origin Access User between CloudFront distribution and the source S3 bucket, or using custom headers between the distribution and the bucket. The use of an Origin Access User prescribes accessing the source bucket in REST mode which results in bucket redirects not being followed. As a result, this module will use the custom header option. * `acm-certificate-arn`: the id of an certificate in AWS Certificate Manager. As this certificate will be used on a CloudFront distribution, Amazon's documentation states the certificate must be generated in the `us-east-1` region. * `deployer`: (Optional) the name of an existing IAM user that will be used to push contents to the S3 bucket. This user will get a role policy attached to it, configured to have read/write access to the bucket that will be created. * `default-root-object`: (Optional) default root object to be served by CloudFront. Defaults to `index.html`, but can be e.x. `v1.0.0/index.html` for versioned applications. * `not-found-response-path`: response path for the file that should be served on 404. Default to `/404.html`, but can be e.x. `/index.html` for single page applications. * `not-found-response-code`: response code when serving a 404 page. Defaults to `200`. * `trusted_signers`: (Optional) List of AWS account IDs that are allowed to create signed URLs for this distribution. May contain `self` to indicate the account where the distribution is created in. * `tags`: (Optional) Additional key/value pairs to set as tags. * `forward-query-string`: (Optional) Forward the query string to the origin. Default value = `false` * `price_class`: (Optional) The price class that corresponds with the maximum price that you want to pay for CloudFront service. Read [pricing page](https://aws.amazon.com/cloudfront/pricing/) for more details. Options: `PriceClass_100` | `PriceClass_200` | `PriceClass_All`. Default value = `PriceClass_200` * `ipv6`: (Optional) Enable IPv6 support on CloudFront distribution. Default value = `false` * `minimum_client_tls_protocol_version`: (Optional) Set the minimum protocol version of the CloudFront certificate. Read the docs on [Supported Protocols and Ciphers](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html#secure-connections-supported-ciphers) for supported values. Default value = `TLSv1` ### Outputs * `website_cdn_hostname`: the Amazon generated Cloudfront domain name. You can already test accessing your website content by this hostname. This hostname is needed later on to create a `CNAME` record in Route53. * `website_cdn_zone_id`: the Hosted Zone ID of the Cloudfront distribution. This zone ID is needed later on to create a Route53 `ALIAS` record. * `website_bucket_id`: The website bucket id * `website_bucket_arn`: The website bucket arn * `website_cdn_id`: The CDN ID of the Cloudfront distribution. * `website_cdn_arn`: The ARN of the CDN ## Setting up the redirect site module "site-redirect" { source = "github.com/skyscrapers/terraform-website-s3-cloudfront-route53//site-redirect" region = "eu-west-1" domain = "my.domain.com" target = "domain.com" duplicate-content-penalty-secret = "some-secret-password" deployer = "an-iam-username" acm-certificate-arn = "arn:aws:acm:us-east-1::certificate/" } ### Inputs * `tags`: (Optional) Additional key/value pairs to set as tags. * `default_root_object`: (Optional) The object that you want CloudFront to return (for example, index.html) when an end user requests the root URL. Default value = `index.html` * `price_class`: (Optional) The price class that corresponds with the maximum price that you want to pay for CloudFront service. Read [pricing page](https://aws.amazon.com/cloudfront/pricing/) for more details. Options: `PriceClass_100` | `PriceClass_200` | `PriceClass_All`. Default value = `PriceClass_200` * `ipv6`: (Optional) Enable IPv6 support on CloudFront distribution. Default value = `false` * `minimum_client_tls_protocol_version`: (Optional) Set the minimum protocol version of the CloudFront certificate. Read the docs on [Supported Protocols and Ciphers](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html#secure-connections-supported-ciphers) for supported values. Default value = `TLSv1` ### Outputs * `website_cdn_hostname`: the Amazon generated Cloudfront domain name. You can already test accessing your website content by this hostname. This hostname is needed later on to create a `CNAME` record in Route53. * `website_cdn_zone_id`: the Hosted Zone ID of the Cloudfront distribution. This zone ID is needed later on to create a Route53 `ALIAS` record. ## Setting up the Route 53 CNAME Whether it is a main site or a redirect site, a CNAME DNS record is needed for your site to be accessed on a non-root domain. module "dns-cname" { source = "github.com/skyscrapers/terraform-website-s3-cloudfront-route53//r53-cname" domain = "my.domain.com" target = "${module.site-main.website_cdn_hostname}" route53_zone_id = "" } ### Inputs * `domain`: the domain name you want to use to access your static website. This should match the domain name used in setting up either a main or a redirect site. * `target`: the domain name of the CloudFront distribution to which the domain name should point. You usually pass the `website_cdn_hostname` output variable from the main or redirect site here. * `route53_zone_id`: the Route53 Zone ID where the CNAME entry must be created. ## Setting up the Route 53 ALIAS Whether it is a main site or a redirect site, an ALIAS DNS record is needed for your site to be accessed on a root domain. module "dns-alias" { source = "github.com/skyscrapers/terraform-website-s3-cloudfront-route53//r53-alias" domain = "domain.com" target = "${module.site-main.website_cdn_hostname}" cdn_hosted_zone_id = "${module.site-main.website_cdn_zone_id}" route53_zone_id = "" } ### Inputs * `domain`: the domain name you want to use to access your static website. This should match the domain name used in setting up either a main or a redirect site. * `target`: the domain name of the CloudFront distribution to which the domain name should point. You usually pass the `website_cdn_hostname` output variable from the main or redirect site here. * `cdn_hosted_zone_id`: the Hosted Zone ID of the CloudFront distribution. You usually pass the `website_cdn_zone_id` output variable from the main or redirect site here. * `route53_zone_id`: the Route53 Zone ID where the CNAME entry must be created. ## Users If you are using the modules in this Git repository to set up your static site and you want some visibility, add your site and info below and submit a pull request: * [Skyscrapers](https://skyscrapers.eu) (Skyscrapers) **Enjoy!** ================================================ FILE: r53-alias/main.tf ================================================ ################################################################################################################ ## Create a Route53 ALIAS record to the Cloudfront website distribution ################################################################################################################ resource "aws_route53_record" "cdn-alias" { zone_id = var.route53_zone_id name = var.domain type = "A" alias { name = var.target zone_id = var.cdn_hosted_zone_id evaluate_target_health = false } } ================================================ FILE: r53-alias/variables.tf ================================================ variable "domain" { type = string } variable "target" { type = string } variable "route53_zone_id" { type = string } variable "cdn_hosted_zone_id" { type = string } ================================================ FILE: r53-alias/versions.tf ================================================ terraform { required_version = ">= 0.12" } ================================================ FILE: r53-cname/main.tf ================================================ ################################################################################################################ ## Create a Route53 CNAME record to the Cloudfront distribution ################################################################################################################ resource "aws_route53_record" "cdn-cname" { zone_id = var.route53_zone_id name = var.domain type = "CNAME" ttl = "300" records = [var.target] } ================================================ FILE: r53-cname/variables.tf ================================================ variable "domain" { type = string } variable "target" { type = string } variable "route53_zone_id" { type = string } ================================================ FILE: r53-cname/versions.tf ================================================ terraform { required_version = ">= 0.12" } ================================================ FILE: site-main/deployer_role_policy.json ================================================ { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket" ], "Effect": "Allow", "Resource": "arn:aws:s3:::${bucket}" }, { "Action": [ "s3:DeleteObject", "s3:GetObject", "s3:GetObjectAcl", "s3:ListBucket", "s3:PutObject", "s3:PutObjectAcl" ], "Effect": "Allow", "Resource": "arn:aws:s3:::${bucket}/*" } ] } ================================================ FILE: site-main/main.tf ================================================ ################################################################################################################ ## Creates a setup to serve a static website from an AWS S3 bucket, with a Cloudfront CDN and ## certificates from AWS Certificate Manager. ## ## Bucket name restrictions: ## http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html ## Duplicate Content Penalty protection: ## Description: https://support.google.com/webmasters/answer/66359?hl=en ## Solution: http://tuts.emrealadag.com/post/cloudfront-cdn-for-s3-static-web-hosting/ ## Section: Restricting S3 access to Cloudfront ## Deploy remark: ## Do not push files to the S3 bucket with an ACL giving public READ access, e.g s3-sync --acl-public ## ## 2016-05-16 ## AWS Certificate Manager supports multiple regions. To use CloudFront with ACM certificates, the ## certificates must be requested in region us-east-1 ################################################################################################################ locals { tags = merge( var.tags, { "domain" = replace(var.domain, "*", "--wildcard--") }, ) } ################################################################################################################ ## Configure the bucket and static website hosting ################################################################################################################ data "template_file" "bucket_policy" { template = file("${path.module}/website_bucket_policy.json") vars = { bucket = var.bucket_name secret = var.duplicate-content-penalty-secret } } resource "aws_s3_bucket" "website_bucket" { bucket = var.bucket_name policy = data.template_file.bucket_policy.rendered force_destroy = var.force_destroy website { index_document = "index.html" error_document = "404.html" routing_rules = var.routing_rules } // logging { // target_bucket = "${var.log_bucket}" // target_prefix = "${var.log_bucket_prefix}" // } tags = local.tags } ################################################################################################################ ## Configure the credentials and access to the bucket for a deployment user ################################################################################################################ data "template_file" "deployer_role_policy_file" { template = file("${path.module}/deployer_role_policy.json") vars = { bucket = var.bucket_name } } resource "aws_iam_policy" "site_deployer_policy" { count = var.deployer != null ? 1 : 0 name = "${var.bucket_name}.deployer" path = "/" description = "Policy allowing to publish a new version of the website to the S3 bucket" policy = data.template_file.deployer_role_policy_file.rendered } resource "aws_iam_policy_attachment" "site-deployer-attach-user-policy" { count = var.deployer != null ? 1 : 0 name = "${var.bucket_name}-deployer-policy-attachment" users = [var.deployer] policy_arn = aws_iam_policy.site_deployer_policy.0.arn } ################################################################################################################ ## Create a Cloudfront distribution for the static website ################################################################################################################ resource "aws_cloudfront_distribution" "website_cdn" { enabled = true is_ipv6_enabled = var.ipv6 price_class = var.price_class http_version = "http2" origin { origin_id = "origin-bucket-${aws_s3_bucket.website_bucket.id}" domain_name = aws_s3_bucket.website_bucket.website_endpoint custom_origin_config { origin_protocol_policy = "http-only" http_port = "80" https_port = "443" origin_ssl_protocols = ["TLSv1"] } custom_header { name = "User-Agent" value = var.duplicate-content-penalty-secret } } default_root_object = var.default-root-object custom_error_response { error_code = "404" error_caching_min_ttl = "360" response_code = var.not-found-response-code response_page_path = var.not-found-response-path } default_cache_behavior { allowed_methods = ["GET", "HEAD", "DELETE", "OPTIONS", "PATCH", "POST", "PUT"] cached_methods = ["GET", "HEAD"] forwarded_values { query_string = var.forward-query-string cookies { forward = "none" } } trusted_signers = var.trusted_signers min_ttl = "0" default_ttl = "300" //3600 max_ttl = "1200" //86400 target_origin_id = "origin-bucket-${aws_s3_bucket.website_bucket.id}" // This redirects any HTTP request to HTTPS. Security first! viewer_protocol_policy = "redirect-to-https" compress = true } restrictions { geo_restriction { restriction_type = "none" } } viewer_certificate { acm_certificate_arn = var.acm-certificate-arn ssl_support_method = "sni-only" minimum_protocol_version = var.minimum_client_tls_protocol_version } aliases = [var.domain] tags = local.tags } ================================================ FILE: site-main/outputs.tf ================================================ output "website_cdn_hostname" { value = aws_cloudfront_distribution.website_cdn.domain_name } output "website_cdn_id" { value = aws_cloudfront_distribution.website_cdn.id } output "website_cdn_arn" { value = aws_cloudfront_distribution.website_cdn.arn } output "website_cdn_zone_id" { value = aws_cloudfront_distribution.website_cdn.hosted_zone_id } output "website_bucket_id" { value = aws_s3_bucket.website_bucket.id } output "website_bucket_arn" { value = aws_s3_bucket.website_bucket.arn } ================================================ FILE: site-main/variables.tf ================================================ variable "region" { default = "us-east-1" } variable "domain" { type = string } variable "bucket_name" { type = string description = "The name of the S3 bucket to create." } variable "duplicate-content-penalty-secret" { type = string } variable "acm-certificate-arn" { type = string } variable "deployer" { type = string default = null } variable "routing_rules" { type = string default = "" } variable "default-root-object" { type = string default = "index.html" } variable "not-found-response-path" { type = string default = "/404.html" } variable "not-found-response-code" { type = string default = "200" } variable "tags" { type = map(string) description = "Optional Tags" default = {} } variable "trusted_signers" { type = list(string) default = [] } variable "forward-query-string" { type = bool description = "Forward the query string to the origin" default = false } variable "price_class" { type = string description = "CloudFront price class" default = "PriceClass_200" } variable "ipv6" { type = bool description = "Enable IPv6 on CloudFront distribution" default = false } variable "minimum_client_tls_protocol_version" { type = string description = "CloudFront viewer certificate minimum protocol version" default = "TLSv1" } variable "force_destroy" { type = bool description = "A boolean that indicates all objects (including any locked objects) should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable." default = false } ================================================ FILE: site-main/versions.tf ================================================ terraform { required_version = ">= 0.12" } ================================================ FILE: site-main/website_bucket_policy.json ================================================ { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadAccess", "Principal": { "AWS": "*" }, "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::${bucket}/*", "Condition": { "StringEquals": { "aws:UserAgent": "${secret}" } } } ] } ================================================ FILE: site-redirect/deployer_role_policy.json ================================================ { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket" ], "Effect": "Allow", "Resource": "arn:aws:s3:::${bucket}" }, { "Action": [ "s3:DeleteObject", "s3:GetObject", "s3:GetObjectAcl", "s3:ListBucket", "s3:PutObject", "s3:PutObjectAcl" ], "Effect": "Allow", "Resource": "arn:aws:s3:::${bucket}/*" } ] } ================================================ FILE: site-redirect/main.tf ================================================ ################################################################################################################ ## Creates a setup to serve a static website from an AWS S3 bucket, with a Cloudfront CDN and ## certificates from AWS Certificate Manager. ## ## Bucket name restrictions: ## http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html ## Duplicate Content Penalty protection: ## Description: https://support.google.com/webmasters/answer/66359?hl=en ## Solution: http://tuts.emrealadag.com/post/cloudfront-cdn-for-s3-static-web-hosting/ ## Section: Restricting S3 access to Cloudfront ## Deploy remark: ## Do not push files to the S3 bucket with an ACL giving public READ access, e.g s3-sync --acl-public ## ## 2016-05-16 ## AWS Certificate Manager supports multiple regions. To use CloudFront with ACM certificates, the ## certificates must be requested in region us-east-1 ################################################################################################################ locals { tags = merge( var.tags, { "domain" = replace(var.domain, "*", "star") }, ) } ################################################################################################################ ## Configure the bucket and static website hosting ################################################################################################################ data "template_file" "bucket_policy" { template = file("${path.module}/website_redirect_bucket_policy.json") vars = { bucket = "site.${replace(replace(var.domain, ".", "-"), "*", "star")}" secret = var.duplicate-content-penalty-secret } } resource "aws_s3_bucket" "website_bucket" { bucket = "site.${replace(replace(var.domain, ".", "-"), "*", "star")}" policy = data.template_file.bucket_policy.rendered website { redirect_all_requests_to = "https://${var.target}" } // logging { // target_bucket = "${var.log_bucket}" // target_prefix = "${var.log_bucket_prefix}" // } tags = local.tags } ################################################################################################################ ## Configure the credentials and access to the bucket for a deployment user ################################################################################################################ data "template_file" "deployer_role_policy_file" { template = file("${path.module}/deployer_role_policy.json") vars = { bucket = "site.${replace(replace(var.domain, ".", "-"), "*", "star")}" } } resource "aws_iam_policy" "site_deployer_policy" { count = var.deployer != null ? 1 : 0 name = "site.${replace(replace(var.domain, ".", "-"), "*", "star")}.deployer" path = "/" description = "Policy allowing to publish a new version of the website to the S3 bucket" policy = data.template_file.deployer_role_policy_file.rendered } resource "aws_iam_policy_attachment" "staging-site-deployer-attach-user-policy" { count = var.deployer != null ? 1 : 0 name = "site.${replace(replace(var.domain, ".", "-"), "*", "star")}-deployer-policy-attachment" users = [var.deployer] policy_arn = aws_iam_policy.site_deployer_policy.0.arn } ################################################################################################################ ## Create a Cloudfront distribution for the static website ################################################################################################################ resource "aws_cloudfront_distribution" "website_cdn" { enabled = true is_ipv6_enabled = var.ipv6 price_class = var.price_class http_version = "http2" origin { origin_id = "origin-bucket-${aws_s3_bucket.website_bucket.id}" domain_name = aws_s3_bucket.website_bucket.website_endpoint custom_origin_config { origin_protocol_policy = "http-only" http_port = "80" https_port = "443" origin_ssl_protocols = ["TLSv1"] } custom_header { name = "User-Agent" value = var.duplicate-content-penalty-secret } } default_root_object = var.default_root_object custom_error_response { error_code = "404" error_caching_min_ttl = "360" response_code = "200" response_page_path = "/404.html" } default_cache_behavior { allowed_methods = ["GET", "HEAD", "DELETE", "OPTIONS", "PATCH", "POST", "PUT"] cached_methods = ["GET", "HEAD"] forwarded_values { query_string = false cookies { forward = "none" } } min_ttl = "0" default_ttl = "300" //3600 max_ttl = "1200" //86400 target_origin_id = "origin-bucket-${aws_s3_bucket.website_bucket.id}" // This redirects any HTTP request to HTTPS. Security first! viewer_protocol_policy = "redirect-to-https" compress = true } restrictions { geo_restriction { restriction_type = "none" } } viewer_certificate { acm_certificate_arn = var.acm-certificate-arn ssl_support_method = "sni-only" minimum_protocol_version = var.minimum_client_tls_protocol_version } aliases = [var.domain] tags = local.tags } ================================================ FILE: site-redirect/outputs.tf ================================================ output "website_cdn_hostname" { value = aws_cloudfront_distribution.website_cdn.domain_name } output "website_cdn_zone_id" { value = aws_cloudfront_distribution.website_cdn.hosted_zone_id } ================================================ FILE: site-redirect/variables.tf ================================================ variable "region" { type = string default = "us-east-1" } variable "domain" { type = string } variable "target" { type = string } variable "duplicate-content-penalty-secret" { type = string } variable "acm-certificate-arn" { type = string } variable "deployer" { type = string default = null } variable "tags" { type = map(string) description = "Optional Tags" default = {} } variable "price_class" { type = string description = "CloudFront price class" default = "PriceClass_200" } variable "ipv6" { type = bool description = "Enable IPv6 on CloudFront distribution" default = false } variable "default_root_object" { type = string description = "CloudFront default root object" default = "index.html" } variable "minimum_client_tls_protocol_version" { type = string description = "CloudFront viewer certificate minimum protocol version" default = "TLSv1" } ================================================ FILE: site-redirect/versions.tf ================================================ terraform { required_version = ">= 0.12" } ================================================ FILE: site-redirect/website_redirect_bucket_policy.json ================================================ { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadAccess", "Principal": { "AWS": "*" }, "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::${bucket}/*" } ] }