
AWS Certificate Manager is a service that lets you easily provision, manage, and deploy public and private Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificates for use with AWS services and your internal connected resources. SSL/TLS certificates are used to secure network communications and establish the identity of websites over the Internet as well as resources on private networks. AWS Certificate Manager removes the time-consuming manual process of purchasing, uploading, and renewing SSL/TLS certificates.
from AWS Certificate Manager Docs
AWS Certificate Manager Pricing
Public SSL/TLS certificates provisioned through AWS Certificate Manager are free.
Overview
This exercise will build an auto-scaling group (ASG) of web servers. It is using almost the exact same code as my previous exercise.
The critical difference in this exercise is that we will add Terraform instructions to change our domain settings in AWS Route 53 and create a valid AWS SSL certificate using AWS Certificate Manager to enable SSL traffic to our website (HTTPS).
Prerequisites
- You must have or purchase a domain for this exercise
- It can be a domain purchased from any domain service, or you can buy a domain with AWS route 53
- You must also ensure Route 53 is configured as your domain’s “Name Service” for the domain.
- Terraform Installed
- AWS account and AWS CLI installed and configured
The Code
Please clone or fork the code from my previous exercise from the GitHub repository.
Make a directory called Terraform, and be sure to change the directory to Terraform. On a Mac (cd ~/terraform). Then clone or fork my repository into the Terraform directory. You should now have a directory “ALB_ASG_Website_using_NAT_instances,” so let’s change directories into that directory.
Now we are going to add a file called “Route53.tf” using our favorite editor (in my case, “Visual Studio Code.”
provider "aws" {
alias = "account_route53" # Specific to your setup
}
# This creates an SSL certificate
resource "aws_acm_certificate" "cert" {
domain_name = "<your domain>"
validation_method = "DNS"
}
# Cert Validation
resource "aws_route53_record" "cert_validation" {
name = tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name
type = "CNAME"
zone_id = "aws_route53_record" "MyDomain"
records = [tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_value]
ttl = 60
}
# This is a DNS record for the ACM certificate validation to prove we own the domain
resource "aws_acm_certificate_validation" "cert_validation" {
certificate_arn = "${aws_acm_certificate.cert.arn}"
validation_record_fqdns = [tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name]
}
# Standard route53 DNS record for Domain pointing to an ALB
resource "aws_route53_record" "MyDomain" {
zone_id = "<zone id of your domain>"
name = "<your domain>"
type = "A"
alias {
name = aws_lb.website-alb.dns_name
zone_id = aws_lb.website-alb.zone_id
evaluate_target_health = true
}
}
Be sure to change <your domain> into the exact domain registered in Route 53, for example, “example.com.” If you want to use something like “www.example.com,” it must already be registered exactly as “www.example.com” in Route 53. Also, be sure to get the “Zone ID” of your domain from Route 53 and replace <zone id of your domain> within the above “route53.tf” code.
That is it; the above code will automatically create a certificate in AWS Certificate Manager, the code will automatically add the neccesary DNS entry for the certificate, and will automatically validate the certificate.
Well Ok, one more change to be made
While researching how to use Terraform to automate adding an SSL certificate for our Load Balancer, every example missed a critical component to get this working. I lost a few hours troubleshooting, then banged my head on the desk because of the apparent failure to change the ALB listener to accept HTTPS. I suppose the writers assumed that everyone knows an ALB listener has to change if we use HTTPS traffic instead of HTTP traffic. However, that tidbit of information wasn’t included in any articles I found on the internet. Oh well, onward and upwards!
Change the “alb_listener.tf file
Delete “alb_listener.tf” and we’ll add a new “alb_listener.tf”.
resource "aws_lb_listener" "website-alb-listener" {
load_balancer_arn = aws_lb.website-alb.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2015-05"
certificate_arn = aws_acm_certificate.cert.arn
default_action {
type = "forward"
forward {
target_group {
arn = aws_lb_target_group.website-target.arn
}
stickiness {
enabled = false
duration = 1
}
}
}
}
resource "aws_lb_listener" "redirect" {
load_balancer_arn = aws_lb.website-alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
Our new listener instructions will forward HTTPS traffic to our load balancer. The code will also automatically redirect any HTTP traffic to HTTPS, thus forcing all traffic to be protected by an SSL transport.
The resources are free only if you don’t leave them running! There is a limit of EC2 hours allowed per month!

This is not for production!
All public websites should have an application firewall between the Web Server and its internet connection, this exercise doesn’t create the application firewall. So do not use this configuration for production
All websites should have monitoring and a method to scrape log events to detect and alert for potential problems with the deployment.
This exercise uses resources compatible with the AWS Free Tier plan. It does not have sufficient compute sizing to support a production workload.
It is a good idea to remove All resources when you have completed this exercise so as not to incur costs