Securing Your EKS Cluster: A Comprehensive Guide to Adding HTTPS SSL Encryption

Securing Your EKS Cluster: A Comprehensive Guide to Adding HTTPS SSL Encryption

ยท

6 min read

Hello again! In this short-ish article, I'm going to be going through how you can add SSL encryption to your AWS EKS cluster.

If you don't know what SSL stands for it's Secure Sockets Layer. It encrypts the information going through the internet which makes it safer to transfer data.

If you want a deep dive into how it works I recommend this YouTube video that simply explains it.

We're going to be using AWS ACM which is AWS's certificate manager to generate a certificate and let our EKS cluster know about it.

We'll also be using a domain we created in a previous article which was created using AWS Route53. We'll go step by step into how everything eventually connects.

Requirements

  1. Make sure you have an EKS cluster up and running. I wrote an article on how to start one up using Terraform here.

  2. Make sure you're using AWS elastic load balancer (mentioned in the article I just linked). This is because AWS Certificate Manager only integrates with AWS services.

  3. A domain registered on AWS Route53 (you can use any other registrar really it's easier using AWS services together though)

Linking the load balancer to our Route53 domain

Firstly, Since we have our EKS cluster up and running. We can describe our Ingress as follows; (I'm using the same conf as the EKS article here

kubectl get ingress -n temp-calculator

In the Address section, we should see something like this k8s-tempcalc-k8salb-y-x.eu-central-1.elb.amazonaws.com

This is our load balancer address. All we'll do is create a CNAME record for it using Route53 hosted zone and records.

A DNS CNAME record is simply an alias that forwards traffic to another domain name.

In our terraform config let's create the Route53 hosted zone and attach records to it.

# route53.tf
# create a route53 hosted zone
resource "aws_route53_zone" "main" {
  name = "your-domain"
}

# attach records to it
resource "aws_route53_record" "main" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "<your-domain>"
  type    = "CNAME"
  ttl     = "300"
  records = ["<your-load-balancer-address>"]
}

Before applying the above configuration, we need to make sure that our Kubernetes Ingress has the domain added in the route53 record configured and ready

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8s-alb
  namespace: temp-calculator
  labels:
    name: k8s-alb
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
  - host: <domain added in route53 record>
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: temperature-api
            port:
              number: 3000

Once applying the terraform configuration, There is one more step we need to do.

Configure the domain from the registrar to have the same Nameservers as the hosted zone

When you create a hosted zone, it will give you a couple of name servers which are servers that help in resolving the DNS to an IP address.

You'll need to configure the domain you purchased from the registrar (in our case Route53) to use the nameservers provided by the hosted zone.

When you set up a hosted zone in Route 53, you're telling Route 53 that you want it to manage the DNS records for a specific domain name. This is where you define the DNS records like A records (for mapping domain names to IPv4 addresses), AAAA records (for mapping domain names to IPv6 addresses), MX records (for email server configuration), and more.

From the AWS console head to Route53 > Registered Domains > <Your domain> and Add the hosted zone's name servers.

Wait 1-2 minutes till the domain propagates through the internet. You can check using this tool.

After doing this. We can hit our domain using HTTP and it should work.

Next, let's add HTTPS to our domain.

AWS Certificate Manager

AWS has a service that automatically manages and renews TLS Certificates for you.

All you need to do to issue a certificate is create one for a specific domain and prove that the domain is yours.

Public ACM certificates are used for securing domains that are publicly accessible on the internet. These certificates are typically used for websites, web applications, APIs, and other services that users access over the public internet.

  • Domain Validation (DV) Certificates: These certificates verify that you have control over the domain by sending an email to the domain owner or by checking DNS records.

  • Wildcard Certificates: These certificates cover a domain and all its subdomains using a wildcard character (). For example, a wildcard certificate for ".example.com" would cover "example.com," "api.example.com," etc.

  • Multi-Domain (SAN) Certificates: Also known as Subject Alternative Name (SAN) certificates, these certificates can secure multiple domain names and subdomains in a single certificate. They're useful when you want to secure different domain names under a single certificate.

resource "aws_acm_certificate" "cert" {
  domain_name       = "<your-domain>"
  validation_method = "DNS"
}

In the code above we create a certificate for the domain we want and we choose the validation method to be DNS. The validation method is because AWS needs proof that you're actually the owner of the domain and not someone else. There are multiple validation methods;

  1. Email Validation: With this method, ACM sends an email to one of the email addresses associated with the domain being validated. The email contains a validation link that the recipient must click to confirm ownership of the domain. ACM provides a list of approved email addresses (such as , , etc.) that you can use for validation.

  2. DNS Validation: DNS validation involves creating specific DNS records in your domain's DNS configuration. ACM provides you with a unique DNS record value that you need to add as a CNAME record to your domain's DNS settings. This demonstrates your control over the domain. Once the DNS record is correctly configured, ACM can query the DNS and confirm ownership of the domain.

We'll be using DNS validation here.

Let's add the certificate DNS records to our domain

resource "aws_route53_record" "cert_validation" {
  allow_overwrite = true
  zone_id = aws_route53_zone.main.zone_id
  name =  tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name
  records = [tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_value]
  type = tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_type
  ttl = "60"
}

This code above adds a CNAME certificate record to our domain.

resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [aws_route53_record.cert_validation.fqdn]
}

The aws_acm_certificate_validation resource is used to define the validation method and required information to validate ownership of the domain for which you've requested an ACM certificate. As mentioned earlier, ACM uses email or DNS validation methods to confirm domain ownership before issuing a certificate.

Terraform will use this information to ensure that the necessary DNS records are correctly configured for domain validation. Once the DNS records are properly set up, the ACM certificate will be validated, and once validated, it will be ready to be used for securing your resources.

When applying the above code. We'll need to edit our Ingress and make our load balancer listen to SSL port 443 so we can use HTTPS.

We add the following annotations:

alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'

Now any requests to port 80 will be redirected to 443 and we can make requests using HTTPS now ๐ŸŽ‰

After finishing make sure to terraform destroy to make sure you don't get charged unwillingly.

References

  1. https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html

  2. https://aws.amazon.com/route53/

  3. https://www.terraform.io

Did you find this article valuable?

Support Amr Elhewy by becoming a sponsor. Any amount is appreciated!

ย