In our previous post we learnt:
But we exposed :80 port to handle incoming requests. Traffic to port 80 is generally for unencrypted traffic. In this article
we will expose port :443, so that we can handle encrypted requests to our webserver (not the webserver but the lb in this case).
If you are asking why we need it, you have probably skipped some early stages of development. Checkout how to secure APIs, as a starting point
DNS
DNS translates human-friendly domain names (e.g., google.in) into machine-readable IP addresses. IP’s are how you connect to different machines which serves you the response to your requests. Like a phone book.
There are different types of records that can be added to a DNS server, like:
A records (mapping domain names to IP addresses)MX records (routing emails), andCNAME records (aliases pointing to other domains)DNS servers can be of multiple type, like:
TLD record is Top level domain server, like .com, .org etc.Authoritative Nameserver, which provides the recursive nameservers with the ip address incase its not cached.DNS Zones
DNS zone is something of namespacing, where a certain entity(organisation/individual) is responsible for maintaing their DNS servers.
When a web browser or other network device needs to find the IP address for a hostname such as “example.com”, it performs a DNS lookup - essentially a DNS zone check - and is taken to the DNS server that manages the DNS zone for that hostname. This server is called the Authoritative NS for the domain.
The authoritative name server then resolves the DNS lookup by providing the IP address, or other data, for the requested hostname.
Route53 is what AWS uses as its Domain Name service. And each Hosted Zone is a DNS zone.
When you create a hosted zone in Route 53, four NS records are automatically assigned. These records point to Route 53 servers, entrusted with resolving your domain name and directing traffic towards your website or application.
Here is an article which gives you an idea about DNS name resoultion works.
Inorder to enable HTTPS requests, we also need to generate SSL certificates. This is usually done with something like letsencrypt. Each SSL certificate also has an expiration date, and hence it needs to be renewed for your public domain name.
The loadbalancer or the fronting proxy would then take care of terminating the ssl connection, and sending the decrypted requests to the EC2 instances.
In AWS the certificate management is done using ACM. This is the easiest to do.
The LoadBalancer uses these certificate arn to terminate and decrypt requests.
Since we already have the gist, I will only be posting the code changes.
resource "aws_acm_certificate" "konoha_in" {
domain_name = "konoha.in"
subject_alternative_names = ["*.konoha.in"]
validation_method = "DNS"
tags = {
Environment = "prod"
}
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_zone" "konoha_in" {
name = "konoha.in"
}
resource "aws_route53_record" "konoha_acm_validation" {
for_each = {
for dvo in aws_acm_certificate.konoha_in.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
zone_id = aws_route53_zone.konoha_in.zone_id
name = each.value.name
type = each.value.type
ttl = 60
records = [
each.value.record,
]
allow_overwrite = true
}
resource "aws_acm_certificate_validation" "konoha_in" {
certificate_arn = aws_acm_certificate.konoha_in.arn
validation_record_fqdns = [for record in aws_route53_record.konoha_acm_validation : record.fqdn]
}
resource "aws_route53_record" "konoha_app_route_alias" {
zone_id = aws_route53_zone.konoha_in.zone_id
name = "api.${aws_route53_zone.konoha_in.name}"
type = "A"
alias {
name = aws_lb.app_lb.dns_name
zone_id = aws_lb.app_lb.zone_id
evaluate_target_health = true
}
}
resource "aws_lb_listener" "app_lb_listener" {
load_balancer_arn = aws_lb.app_lb.arn
- port = "80"
- protocol = "HTTP"
+ port = "443"
+ protocol = "HTTPS"
+ certificate_arn = aws_acm_certificate.konoha_in.arn
+ ssl_policy = "ELBSecurityPolicy-2016-08"
+
+ depends_on = [ aws_acm_certificate_validation.konoha_in ]
konoha.in in GoDaddy.Now we need a way to be able to associate and validate the issued certificate with the domain name. In order to validate we can either do:
We will use DNS Validation.
When you choose DNS validation, ACM provides you with one or more CNAME records that must be added to this database. These records contain a unique key-value pair that serves as proof that you control the domain.
The aws_route53_record block does just that. You can check this, by going to your ACM dashboard and Route53 dashboard.
After terraform apply inside the hosted zone in Route53 you can see the entry, and it should match the CNAME record key value provided in the ACM dasboard.
A (Alias) record, which points a subdomain api.konoha.in to the LoadBalancerPending to Success, and the certificate is ready to be used for that domain name.port to :443 and attach the certificate arn to use for terminating.
Final Piece
You now need to go to daddy and change the DNS entries. In your UI you should see Nameservers tab, apart from Records.
Replace the existing nameserver with the ones provided in the Route 53 hosted zone.
The other way of doing this, is by adding the ACM generated CNAME to the DNS Records instead of Nameservers, but for
some reason my certificate wouldn’t get validate. The disadvantage with this approach is you now need to configure MX records in AWS. You can check it here.
Maybe we will explore it at a later date.
This kindof marks the end of basic hosting using AWS. There is a separate gist with the above changes.