Configure mutual TLS authentication for applications running on Amazon EKS - AWS Prescriptive Guidance

Configure mutual TLS authentication for applications running on Amazon EKS

Created by Mahendra Siddappa (AWS)

Environment: PoC or pilot

Technologies: DevOps; Security, identity, compliance

AWS services: Amazon EKS; Amazon Route 53

Summary

Certificate-based mutual Transport Layer Security (TLS) is an optional TLS component that provides two-way peer authentication between servers and clients. With mutual TLS, clients must provide an X.509 certificate during the session negotiation process. The server uses this certificate to identify and authenticate the client.

Mutual TLS is a common requirement for Internet of Things (IoT) applications and can be used for business-to-business applications or standards such as Open Banking.

This pattern describes how to configure mutual TLS for applications running on an Amazon Elastic Kubernetes Service (Amazon EKS) cluster by using an NGINX ingress controller. You can enable built-in mutual TLS features for the NGINX ingress controller by annotating the ingress resource. For more information about mutual TLS annotations on NGINX controllers, see Client certificate authentication in the Kubernetes documentation.

Important: This pattern uses self-signed certificates. We recommend that you use this pattern only with test clusters, and not in production environments. If you want to use this pattern in a production environment, you can use AWS Certificate Manager Private Certificate Authority or your existing public key infrastructure (PKI) standard to issue private certificates.

Prerequisites and limitations

Prerequisites 

  • An active Amazon Web Services (AWS) account.

  • An existing Amazon EKS cluster.

  • AWS Command Line Interface (AWS CLI) version 1.7 or later, installed and configured on macOS, Linux, or Windows.

  • The kubectl command line utility, installed and configured to access the Amazon EKS cluster. For more information about this, see Installing kubectl in the Amazon EKS documentation.

  • An existing Domain Name System (DNS) name to test the application.

Limitations 

  • This pattern uses self-signed certificates. We recommend that you use this pattern only with test clusters, and not in production environments.

Architecture

Technology stack

  • Amazon EKS

  • Amazon Route 53

  • Kubectl

Tools

  • Amazon EKS – Amazon Elastic Kubernetes Service (Amazon EKS) makes it easy for you to run Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane or nodes.

  • Amazon Route 53 – Route 53 is a highly available and scalable DNS web service.

  • Kubectlkubectl is a command line utility that you use to interact with an Amazon EKS cluster.

Epics

TaskDescriptionSkills required
Download and save the Kubernetes configuration.

Download the ingress.yaml and mtls.yaml files (attached) and save them to a local path on your computer.

DevOps engineer
TaskDescriptionSkills required
Generate the CA key and certificate.

Generate the certificate authority (CA) key and certificate by running the following command:

openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Test Cert Authority'

DevOps engineer
Generate the server key and certificate, and sign with the CA certificate.

Generate the server key and certificate, and sign with the CA certificate by running the following command:

openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN= <your_domain_name> ' && openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Important: Make sure sure that you replace <your_domain_name> with your existing domain name.

DevOps engineer
Generate the client key and certificate, and sign with the CA certificate.

Generate the client key and certificate, and sign with the CA certificate by running the following command:

openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Test' && openssl x509 -req -sha256 -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt

DevOps engineer
TaskDescriptionSkills required
Deploy the NGINX ingress controller in your Amazon EKS cluster.

Deploy the NGINX ingress controller by using the following command:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/aws/deploy.yaml

DevOps engineer
Verify that the NGINX ingress controller service is running.

Verify that the NGINX ingress controller service is running by using the following command:

kubectl get svc -n ingress-nginx

Important: Make sure that the field of service address contains the Network Load Balancer’s domain name.

DevOps engineer
TaskDescriptionSkills required
Create a namespace in the Amazon EKS cluster.

Run the kubectl create ns mtls command to create a namespace called mtls in your Amazon EKS cluster. This deploys the sample application to test mutual TLS.

DevOps engineer
TaskDescriptionSkills required
Create the Kubernetes deployment and service in the mtls namespace.

Create the Kubernetes deployment and service in the mtls namespace by running the kubectl create -f mtls.yaml -n mtls command.

DevOps engineer
Verify that the Kubernetes deployment is created.

Run the following command to verify that the deployment is created and has one pod in available status:

kubectl get deploy -n mtls

DevOps engineer
Verify that the Kubernetes service is created.

Verify that the Kubernetes service is created by running the following command:

kubectl get service -n mtls

DevOps engineer
TaskDescriptionSkills required
Create a secret for the ingress resource.

Run the folllowing command to create a secret for the NGINX ingress controller using the certificates that you created earlier:

kubectl create secret generic mtls-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt -n mtls 

Your secret has a server certificate for the client to identify the server and a CA certificate for the server to verify the client certificates.

DevOps engineer
TaskDescriptionSkills required
Create the ingress resource in the mtls namespace.

Open the ingress.yaml file and replace <your_domain_name> with your existing domain name.

Create the ingress resource in the mtls namespace  by running the following command:

kubectl create -f ingress.yaml -n mtls

This means that the NGINX ingress controller can route traffic to your sample application.

DevOps engineer
Verify that the ingress resource is created.

Verify that the ingress resource is created by running the following command:

kubectl get ing -n mtls

Important: Make sure that the address of the ingress resource shows the load balancer created for the NGINX ingress controller.

DevOps engineer
TaskDescriptionSkills required
Create CNAME record that points to the load balancer for the NGINX ingress controller.

Sign in to the AWS Management Console, open the Amazon Route 53 console, and create a Canonical Name (CNAME) record that points mtls.<your_domain_name> to the load balancer for the NGINX ingress controller.

For more information about this, see Creating records by using the Route 53 console in the Route 53 documentation.

DevOps engineer
TaskDescriptionSkills required
Test mutual TLS setup without certificates.

Run the curl -k https://mtls.<your_domain_name>  command. You should receive the "400 No required SSL certificate was sent" error response.

DevOps engineer
Test mutual TLS setup with certificates.

Run the curl -k https://mtls.<your_domain_name> --cert client.crt --key client.key command. You should receive the "mTLS is working" response.

DevOps engineer

Related resources

Attachments

To access additional content that is associated with this document, unzip the following file: attachment.zip