Terraform AWS module to provision CloudFront CDN and securely serve HTTPS requests to a static website hosted on Amazon S3.
The module creates:
- S3 bucket to host static website content
- S3 bucket to store CloudFront access log files in
- Block Public Access settings for both S3 buckets (all four settings set to
true
) - CloudFront origin access identity
- S3 bucket policy to ensure CloudFront OAI has permissions to read files in the S3 bucket, but users don't
- ACM public SSL/TLS certificate for your domain, using DNS validation
- Route 53 CNAME record for ACM validation
- CloudFront distribution with IPv6, TLS, SNI and HTTP/2 support targeting an S3 origin
- Lambda@Edge function to customize the content CloudFront delivers
- Route 53 A and AAAA alias records to the CloudFront distribution
The default Lambda@Edge function is used to add the following HTTP security response headers, triggered by the Origin Response CloudFront event:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self';
Feature-Policy: geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'self'; vibrate 'none'; fullscreen 'self'; payment 'none';
Scanning the website with HTTP Observatory results in:
Use the module input variables to specify a filename with custom function code (source_file
) and the CloudFront event to trigger it (event_type
).
Name | Description | Type | Default | Required |
---|---|---|---|---|
allowed_methods | Controls which HTTP methods CloudFront processes and forwards to your S3 bucket | list | <list> |
no |
aws_region | AWS region | string | "eu-west-1" |
no |
cached_methods | Controls whether CloudFront caches responses to requests using the specified HTTP methods | list | <list> |
no |
comment | Distribution comments | string | "Managed by Terraform" |
no |
compress | Compress content for web requests that include Accept-Encoding: gzip in the request header | string | "true" |
no |
default_root_object | An object CloudFront returns when the end user requests the root URL | string | "index.html" |
no |
default_ttl | Default amount of time (in seconds) an object is in a CloudFront cache | string | "3600" |
no |
domain_name | DNS domain name | string | n/a | yes |
enabled | Whether the distribution is enabled to accept end user requests for content | string | "true" |
no |
event_type | The specific event to trigger the function | string | "origin-response" |
no |
force_destroy | All objects should be deleted from the bucket so that the bucket can be destroyed without error | string | "true" |
no |
geo_restriction_locations | ISO 3166-1-alpha-2 country codes | list | <list> |
no |
geo_restriction_type | The method to restrict distribution of your content by country (none, whitelist, blacklist) | string | "none" |
no |
handler | The function entrypoint in your code | string | "index.handler" |
no |
include_body | Expose the request body to the Lambda function | string | "false" |
no |
is_ipv6_enabled | Whether IPv6 is enabled for the distribution | string | "true" |
no |
log_days | The number of days to keep the log files | string | "7" |
no |
max_ttl | Maximum amount of time an object is in a CloudFront cache | string | "86400" |
no |
min_ttl | Minimum amount of time you want objects to stay in CloudFront caches | string | "0" |
no |
minimum_protocol_version | The minimum TLS version that you want CloudFront to use for HTTPS connections | string | "TLSv1.2_2018" |
no |
origin_path | Causes CloudFront to request content from a directory in your S3 bucket | string | "" |
no |
price_class | The price class for this distribution (PriceClass_All, PriceClass_200, PriceClass_100) | string | "PriceClass_All" |
no |
runtime | Function runtime identifier | string | "nodejs10.x" |
no |
source_file | Package this file into the function archive (index.js local to the module path is used by default) | string | "" |
no |
tag_environment | Environment tag | string | "Prod" |
no |
tag_name | Name tag | string | "AWSLabs" |
no |
tags_shared | Other tags assigned to all resources | map | <map> |
no |
viewer_protocol_policy | The protocol users can use to access the origin files (allow-all, https-only, redirect-to-https) | string | "redirect-to-https" |
no |
wait_for_deployment | Wait for the distribution status to change from InProgress to Deployed | string | "false" |
no |
web_acl_id | AWS WAFv2 Web ACL ARN | string | "" |
no |
zone_id | Route 53 zone ID | string | n/a | yes |
Name | Description |
---|---|
alias_fqdn | DNS alias record FQDN |
bucket_id | S3 bucket name |
bucket_regional | S3 bucket region-specific domain name, also used as CloudFront Origin ID |
cert_arn | ACM certificate ARN |
dist_arn | CloudFront distribution ARN |
dist_domain | CloudFront distribution domain name |
dist_id | CloudFront distribution ID |
dist_zone_id | CloudFront zone ID that can be used to point Route 53 alias records to |
# S3, IAM, ACM, CloudFront
module "aws_cloudfront_s3" {
source = "github.com/ArtiomL/aws-cloudfront-s3"
aws_region = "eu-north-1"
domain_name = "artl.dev"
source_file = "custom.js"
zone_id = aws_route53_zone.main.zone_id
tag_name = "AWSLabs"
tag_environment = "Dev"
}