I'm trying to deploy a ReactJS project statically to s3 using Terraform
My s3 bucket terraform config to create the bucket with the policy:
resource "aws_s3_bucket" "site" {
bucket = var.domain
acl = "public-read"
policy = <<EOF
{
"Version":"2012-10-17",
"Statement":[{
"Sid":"PublicReadForGetBucketObjects",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::${var.domain}/*"]
}
]
}
EOF
website {
index_document = "index.html"
error_document = "404.html"
}
}
route53 config with the necessary dns:
resource "aws_route53_zone" "main" {
name = var.domain
}
resource "aws_route53_record" "root_domain" {
zone_id = aws_route53_zone.main.zone_id
name = var.domain
type = "A"
alias {
name = aws_cloudfront_distribution.cdn.domain_name
zone_id = aws_cloudfront_distribution.cdn.hosted_zone_id
evaluate_target_health = false
}
}
cloudfront config:
resource "aws_cloudfront_distribution" "cdn" {
origin {
origin_id = var.domain
domain_name = aws_s3_bucket.site.bucket_regional_domain_name
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "match-viewer"
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
}
aliases = [var.domain]
enabled = true
wait_for_deployment = false
default_root_object = "index.html"
custom_error_response {
error_caching_min_ttl = 0
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = var.domain
forwarded_values {
query_string = true
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
price_class = "PriceClass_100"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
Even though I'm trying to use cloudfront default certificate i keep getting the following error after running terraform apply
:
Error: error creating CloudFront Distribution: InvalidViewerCertificate: To add an alternate domain name (CNAME) to a CloudFront distribution, you must attach a trusted certificate that validates your authorization to use the domain name.
Launch EC2 instance. In this EC2 instance use the key and security group which we have created in step 1. Developer have uploded the code into github repo also the repo has some images. Create S3 bucket, and copy/deploy the images from github repo into the s3 bucket and change the permission to public readable.
If you want OPTIONS responses to be cached, do the following: Choose the options for default cache behavior settings that enable caching for OPTIONS responses. Configure CloudFront to forward the following headers: Origin , Access-Control-Request-Headers , and Access-Control-Request-Method .
Finally fixed it, if you want to use the default certificate you cannot add alternate domain names to the CloudFront distribution, you will need to generate an SSL certificate using Amazon certificate manager. In other words, to make this work you need to comment out aliases = [var.domain]
in the CloudFront config part
This problem is of course not related to Terraform.
As mentoied in How do I resolve the "InvalidViewerCertificate" error exception while creating or updating a CloudFront distribution:
This error message:
To add an alternate domain name (CNAME) to a CloudFront distribution, you must attach a trusted certificate that validates your authorization to use the domain name.
Indicates that the alternate domain names (CNAMEs) on the distribution aren't covered by the Subject Alternative Name (SAN) of the certificate that you provided.
You can request a public certificate with ACM, or you can contact your certificate authority (CA) for an updated certificate that covers the alternate domain names on the distribution.
(*) Regarding the provided answer above - Notice that you are not forced to use Amazon certificate manager - you can use external provider (for example the free LetsEncrypt) as long as you follow the mentioned rules.
Terraform version of the @RtmY reply could look something like this. In order to get a certificate and validate it you have to do it in us-east-1 region, therefore we need to introduce it in your settings:
provider "aws" {
version = "~> 2.46.0"
}
provider "aws" {
version = "~> 2.46.0"
region = "us-east-1"
alias = "us-east-1"
}
Then we have to create a certificate:
resource "aws_acm_certificate" "cert" {
provider = aws.us-east-1
domain_name = local.bucket_name
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
To validate a certificate we have to create a DNS entry using Route53:
resource "aws_route53_record" "cert_validation" {
name = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_name}"
type = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_type}"
zone_id = var.zone-id-of-your-route-53
records = ["${aws_acm_certificate.cert.domain_validation_options.0.resource_record_value}"]
ttl = 60
}
Last step, we have to validate newly created certificate, again in us-east-1 region:
resource "aws_acm_certificate_validation" "cert" {
provider = aws.us-east-1
certificate_arn = aws_acm_certificate.cert.arn
validation_record_fqdns = ["${aws_route53_record.cert_validation.fqdn}"]
}
Now, in our aws_cloudfront_distribution we keep aliases where they are, and have to add another configuration for the viewer certificate:
viewer_certificate {
acm_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
ssl_support_method = "sni-only"
}
I assume, such validation works for one alias only and not for many. In case of many aliases, the example from the docs might suit better: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation
The solution was borrowed from here:
Terraform AWS ACM certificates in us-east-1 for resources in eu-west-1
I had this issue too, found that I had accidentally created the cert through the ACM in the wrong region. The certificate must be in the same region as the distribution
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With