Skip to content

eyulf/terraform-module-website-aws-s3-cloudfront

Repository files navigation

Terraform AWS S3/CloudFront Website

Contents

Introduction

This module will create and configure a CloudFront Distribution and S3 bucket to allow a static website to be hosted. This is secured using a CloudFront Origin Access Control, as such this module will not configure the S3 bucket to be directly accessible, instead requests must go through the CloudFront Distribution.

There are some limitations with this configuration as it requires that Website hosting is not enabled on the S3 bucket. Additionally CloudFront only applies the default root object on the root of the website itself (eg example.com > example.com/index.html). This is not performed on any subdirectories (eg example.com/about/). To work around this limitation, A CloudFront Function is also deployed to append index.html to requests that don’t include a file name or extension in the URL.

For DNS hosting, you can supply a Route53 zone ID using var.route53_zone_id. DNS records will be created in when this is supplied. The zone itself is not created or managed by this module. When this is not supplied the relevent DNS records will be supplied in outputs.

The CloudFront distribution is configured with Cache Policies. The Cache policy is set to CachingOptimized, the Origin request policy is set to CORS-S3Origin. Additionally the Reponse headers policy is also set, the policy used is configurable and is set to Managed-CORS-with-preflight-and-SecurityHeadersPolicy by default.

WWW Redirect

If you want to redirect your website's www domain to the non-www domain (eg www.example.com to example.com), you can do this using by enabling the website_redirect_www variable. Enabling this will do a couple of things at once:

  1. Includes the www version of the website in the list of alias domains. This impacts the configuration of the ACM certificate and CloudFront Distribution.
  2. Include code in the CloudFront Function to perform a 302 redirect from www to non-www (eg this will redirect www.example.com to example.com).

Note: If you want to include the www domain but _ DO NOT_ want to redirect it, you will need to include it in the website_aliases variable instead.

OpenID Connect

This module prefers OpenID Connect for authenticating against AWS for deploying files to S3 and invalidating CloudFront cache. The intended use case for this is as part of a Github Action, or a Bitbucket Pipeline.

If you do not use any of the above to manage/deploy your code to S3, you can make use of the IAM Policy Document provided as the iam_policy_data_json output to configure your own IAM access.

Module Limitations

Intial Deployment

When first using this module, you will need to run a Terraform Apply twice. This is because of the ACM data resource that is used to ensure that the ACM certificate is issued before adding it to CloudFront regardless of how the DNS validation records are created.

The first Terraform Apply will create everything, the second Terraform Apply will add the domain/s and ACM certificate to the CloudFront Distribution.

ACM Certificate Replacement

If the ACM certicate needs to be replaced by Terraform, the Apply will fail with the following error:

multiple certificates for domain "example.com" found in this Region

This is caused by the ACM data resource finding multiple records. To resolve this take the following steps in the AWS Console (or via API).

  1. Update the CloudFront Distribution to remove the Aliases and ACM Certificate.
  2. Delete the old SSL Certificate that does not contain the new domain configuration.

After this is done you can then run another Terraform Apply to finalise the changes.

Note: The ACM Certificate will need to be replaced in the following situations:

  • Changing the website_redirect_www variable.
  • Updating the website_aliases variable.

If you need to do any of the above activities, you should treat this as a breaking change for the purposes of change/downtime management.

Upgrade Notes

In version 1.0 of this module, there was capability to create an IAM user to be used for uploading files. From version 2.0.0 onwards, this has been removed in favour of OpenID Connect. If this is not desired, this module will still output an IAM Policy Document that can be used for providing access.

Version 2.0.0 of this module also replaces the S3 bucket and CloudFront Distribution previously only used for redirecting www to non-www with a CloudFront Function that is associated with the primary CloudFront Distribution. This may cause an outage if the www version of a website is pointing to the CLoudFront Distribution that gets removed.

Usage

Default (External DNS)

module "website-aws-s3-cloudfront-cloudflare" {
  source  = "eyulf/website-aws-s3-cloudfront/module"
  version = "2.0.0"

  website_domain = "example.com"

  providers = {
    aws.virginia = aws.n_virginia
  }
}

Default (Route53)

module "website-aws-s3-cloudfront-route53" {
  source  = "eyulf/website-aws-s3-cloudfront/module"
  version = "2.0.0"

  website_domain  = "example.com"
  route53_zone_id = <ROUTE53 ZONE ID>

  providers = {
    aws.virginia = aws.n_virginia
  }
}

Create GitHub OpenId Connect

module "website-aws-s3-cloudfront-route53" {
  source  = "eyulf/website-aws-s3-cloudfront/module"
  version = "2.0.0"

  website_domain = "example.com"

  openid_provider_create = true
  github_repo            = "organisation/repo"

  providers = {
    aws.virginia = aws.n_virginia
  }
}

Existing GitHub OpenId Connect

module "website-aws-s3-cloudfront-route53" {
  source  = "eyulf/website-aws-s3-cloudfront/module"
  version = "2.0.0"

  website_domain = "example.com"

  github_openid_arn = "<OPENID CONNECT PROVIDER ARN>"
  github_repo       = "organisation/repo"

  providers = {
    aws.virginia = aws.n_virginia
  }
}

Requirements

Name Version
terraform >= 1.0
aws >= 4.0

Providers

Name Version
aws >= 4.0
aws.virginia >= 4.0

Modules

No modules.

Resources

Name Type
aws_acm_certificate.this resource
aws_acm_certificate_validation.this resource
aws_cloudfront_distribution.this resource
aws_cloudfront_function.this resource
aws_cloudfront_origin_access_control.this resource
aws_iam_openid_connect_provider.bitbucket resource
aws_iam_openid_connect_provider.github resource
aws_iam_role.bitbucket resource
aws_iam_role.github resource
aws_iam_role_policy.bitbucket resource
aws_iam_role_policy.github resource
aws_route53_record.website resource
aws_route53_record.website_acm_validation resource
aws_route53_record.website_www resource
aws_s3_bucket.this resource
aws_s3_bucket_cors_configuration.this resource
aws_s3_bucket_lifecycle_configuration.this resource
aws_s3_bucket_policy.this resource
aws_s3_bucket_public_access_block.this resource
aws_s3_bucket_server_side_encryption_configuration.this resource
aws_s3_bucket_versioning.this resource
aws_acm_certificate.this data source
aws_cloudfront_cache_policy.this data source
aws_cloudfront_origin_request_policy.this data source
aws_cloudfront_response_headers_policy.this data source
aws_iam_policy_document.bitbucket_assume data source
aws_iam_policy_document.github_assume data source
aws_iam_policy_document.pipeline data source
aws_iam_policy_document.s3_bucket data source

Inputs

Name Description Type Default Required
bitbucket_openid_arn The ARN for an existing BitBucket OpenID Connect provider. string "" no
bitbucket_repo_uuid A list of Repo UUID's string "" no
bitbucket_workspace_name The name of the BitBucket workspace. string "" no
bitbucket_workspace_uuid BitBucket Workspace UUID. string "" no
cloudfront_default_cache_allowed_methods List of allowed methods for the CloudFront default cache behaviour configuration. list(string)
[
"GET",
"HEAD"
]
no
cloudfront_default_cache_cached_methods List of cached_methods for the CloudFront default cache behaviour configuration. list(string)
[
"GET",
"HEAD"
]
no
cloudfront_price_class The price class to use for CloudFront. Must be one of PriceClass_All, PriceClass_200 or PriceClass_100. string "PriceClass_All" no
cloudfront_response_headers_policy_name The Name of the Response headers policy to use. string "Managed-CORS-with-preflight-and-SecurityHeadersPolicy" no
cloudfront_ssl_minimum_protocol The minimum SSL protocol to use for the CloudFront viewer certificate configuration. string "TLSv1.2_2021" no
cloudfront_web_acl_arn The ARN of an AWS WAF web ACL to associate with CloudFront. string "" no
github_openid_arn The ARN for an existing GitHub OpenID Connect provider. string "" no
github_repo The name of the GitHub repo in the format of 'organisation/repo'. string "" no
openid_provider_create Create the OpenID Connect Provider. bool false no
route53_zone_id The Route53 Zone ID. If not set DNS records will be returned in outputs. string "" no
s3_cors_allowed_headers List of allowed headers for the S3 Bucket's CORS configuration. list(string) [] no
s3_cors_allowed_methods List of allowed methods for the S3 Bucket's CORS configuration. list(string)
[
"GET"
]
no
s3_cors_allowed_origins List of allowed origins for the S3 Bucket's CORS configuration. list(string)
[
"*"
]
no
s3_cors_expose_headers List of expose headers for the S3 Bucket's CORS configuration. list(string) [] no
s3_lifecycle_noncurrent_expiration The number of days after which a non current version of a S3 object will be expired. number 30 no
website_aliases Additional domain names to use for the website. list(string) [] no
website_domain The primary domain name to use for the website. string n/a yes
website_redirect_www Include www in the Cloudfront Alias and ACM Certificate as well as add code to redirect www to non-www in the Cloudfront Function. bool false no

Outputs

Name Description
acm_validation_dns_records The DNS records required to validate the ACM Certificate.
bitbucket_openid_connect_arn The ARN of the BitBucket OpenID Connect Provider.
bitbucket_openid_connect_role The name of the BitBucket OpenID Connect IAM Role.
cloudfront_arn The ARN of the Cloudfront Distribution.
cloudfront_url The name of the Cloudfront Distribution's URL.
github_openid_connect_arn The ARN of the GitHub OpenID Connect Provider.
github_openid_connect_role The name of the GitHub OpenID Connect IAM Role.
iam_policy_data_json IAM policy data that can be used for S3 uploads and CloudFront invalidation.
s3_bucket The name of the S3 Bucket.