Let's Embark! Setting up Kubernetes (3 Part Series)
Today we secure our Ingress! Security is one of the most important parts of any modern software installation. Let's see how easy it is to get 'er done on Kubernetes.
It's that time of the day... You sit down at your computer to access your application you're running on Kubernetes. You navigate to your site, and what's this!? Someone has defaced it! Oh no, looks like you didn't have your ingress secured and someone has sniffed all your traffic and gotten your admin password. This of course, is what could happen, but we're smart SysAdmins - we're going to secure our ingress controllers using Let's Encrypt.
If you've read my Article on TLS (which you should), you know that securing a website is important because it allows each party to trust that they are the only ones participating in their conversation. A few years ago, the ability to provide encryption on a website was hampered by the fact all Certificate Authorities (CAs) issued SSL Certificates for cash. This meant that for most hobbyists or smaller websites, securing their stuff was expensive. Enter Let's Encrypt, a service run by the non-profit Internet Security Research Group. Let's Encrypt effectively has democratised access to secure communications by maintaining a CA that issues Certificates for free. That's right, free as in free beer. This means that you can setup TLS on your website for free, and anyone who access your site does so with the knowledge and comfort that your communication is secure. A vitally important, yet criminally underrated privilege that a lot of people take for granted.
This process for configuring Let's Encrypt is relatively straight forward thanks to
cert-manager, a project by Jetstack. We're going to use
cert-manager and Digital Ocean DNS to provision our certificates. Let's get started by jumping into
kubectl and installing our components.
# Creates Namespace kubectl create namespace cert-manager # Installs Custom Resource Definitions and the cert-manager Services kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml
This setups up the basic pods and configuration required to run
cert-manager. The main configuration items we need to take care of, is setting up our Digital Ocean API Key, and creating our Cluster Issuers. Before we creating our Digital Ocean Secret, we need to go to the Digital Ocean Control Panel and Generate an API Key (here's a referral link, although DNS is free with Digital Ocean). Once this is done, let's create the Secret:
# dns_secret.yaml apiVersion: v1 kind: Secret metadata: name: digitalocean-dns namespace: cert-manger-issuer data: access-token: <DIGITAL_OCEAN_API_KEY>
kubectl apply -f dns_secret.yaml
Now we've got all our configuration in place, we just need to tell
cert-manager how to issue certificates for our Cluster. We do this using ClusterIssuers which can issue Certificates across all Ingress in our Cluster. The cluster issuer consists of two pieces of configuration: your email address (for notifications) and solver configuration (so that Let's Encrypt can prove you own your domain). With these in place, we can get to the part where we actually secure our Ingress!
# production_do_dns_issuer.yaml apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: do-issuer-production namespace: cert-manger-issuer spec: acme: # The ACME server URL server: https://acme-v02.api.letsencrypt.org/directory # Email address used for ACME registration email: <YOUR_EMAIL_ADDRESS> # Name of a secret used to store the ACME account private key privateKeySecretRef: name: letsencrypt-production # Enable the DNS-01 challenge provider solvers: - dns01: digitalocean: tokenSecretRef: name: digitalocean-dns key: access-token
kubectl apply -f production_do_dns_issuer.yaml
We're finally on the home stretch! The final step is to apply our TLS configuration to our Ingress. This involves:
- Adding a
cert-manager.io/cluster-issuerannotation which tells
cert-managerthat we want a Certificate issued by the listed ClusterIssuer.
tlsblock under the spec that lists the host names we want the Certificate to provide TLS for, as well as the name of the Secret where the Certificate should be stored.
# production_ingress.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: [...] annotations: # Add our annotation cert-manager.io/cluster-issuer: letsencrypt-production spec: # Add our host and Secret configuration tls: - hosts: - www.example.com - example.com secretName: wp-example-com-tls-production [...]
kubectl apply -f production_ingress.yaml
Once this changes have been applied to the ingress, the following will occur:
- a TXT record will be placed into your DNS Zone by the dns01 solver.
- a secret will be created in the same namespace as the ingress with the name listed at
spec > tls > secretName.
Within about five minutes, your Certificate will be issued and if you refresh your site it will now be secured.
As you can see, it is very easy to setup TLS on our Ingress on Kubernetes. No one could possibly have any excuse to let their own and their customers private communications be snooped on by third party actors. I love TLS and this is probably my favourite article of the series. Security is really important, and it is easy to forget that given how ubiquitous and easy it is to use in our modern day. However, we can't let our guard down because threats and bad actors take a high baseline of security into account. Don't be easy pickings.
If you liked this article, consider giving Let's Encrypt a donation, or you could just follow me on Twitter @stophammotime. Thanks for reading, and see you for the next installment where we setup backups on our Cluster.