Managing Ingress Controllers on Kubernetes: Part 3

Options for Managing SSL/TLS

Photo by Benjamin Voros on Unsplash

Security is an important concern when we’re talking about traffic reaching our cluster. Luckily, the Ingress API supports configuring Transport Layer Security (TLS) for services. In doing so you avoid that communication with a service happens in plaintext. Clients also gain more confidence that they are actually talking to the intended service. Let’s take a look at how to configure TLS in an Ingress resource.

Basic Configuration

The TLS artifacts (X.509 certificate and private key) for the hosts need to be stored in a Secret which is then referenced in the definition of the Ingress object:

apiVersion: v1 data: tls.crt: <base64 encoded string> tls.key: <base64 encoded string> kind: Secret metadata: name: acme.com.tls namespace: default type: kubernetes.io/tls --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: acme-app-ingress spec: tls: — hosts: - acme.com secretName: acme.com.tls rules: - host: acme.com http: paths: - path: /foo backend: serviceName: svc1 servicePort: 80

There are a couple of things to take account of for the simple, default configuration of TLS. Firstly, the Ingress implementation assumes that TLS is terminated at the point of Ingress, and that traffic is routed to the service backend using plain HTTP. More on this in a moment. Secondly, the Ingress API only supports TLS on port 443, and if multiple hosts are specified in the TLS component of the Ingress definition, traffic is multiplexed on the same port by virtue of the hostname specified with the Server Name Indication (SNI) TLS extension, which must be supported by the specific Ingress controller in question.

SSL/TLS Passthrough

The example above shows that TLS is terminated at the point of Ingress. Terminating TLS at the point of Ingress relieves the backend service pods from the costly task of decrypting traffic and the burden of certificate management. However, if needed, it is possible to have communication be encrypted all the way through to the service pod. Not all Ingress controllers support this feature, and they handle it in different ways.

For example, the Traefik Ingress controller checks the service port in the Ingress definition, and if the port is 443, it attempts to communicate with each pod endpoint using TLS. The k8s-ingress-nginx controller uses the nginx.ingress.kubernetes.io/ssl-passthrough (which must be set to “true”), in conjunction with it — enable-ssl-passthrough command line flag.

If it’s not a requirement, it’s more convenient and less troublesome to adopt the default behavior of the Ingress API and have TLS terminated at the point of Ingress.

Other SSL/TLS Considerations. Watch out for that HSTS Header!

By default, the k8s-ingress-nginx controller automatically applies the HTTP Strict Transport Security (HSTS) header in responses where TLS is configured on the relevant Ingress object. This instructs the client to communicate with the backend service for a default period of six months using only HTTPS.

Extreme care should be taken to ensure that there are no requirements for client access to resources using plain HTTP for the domain in question, otherwise client access to those resources may be rendered impossible for a six month duration!

Here’s an example; a website might make use of an asset, or a service, hosted by a third-party. A custom sub-domain might be used in conjunction with a DNS CNAME record, pointing to the hosted asset, but if the sub-domain has no TLS certificate, then the asset will be served using plain HTTP. With HSTS enabled as part of the Ingress definition, all HTTP requests will be upgraded to HTTPS by the client, resulting in content not being rendered as expected. Fixing the issue server-side will have no effect for the client in question for the duration of the HSTS max-age parameter. A sensible precaution might be to initially disable this feature (which is the default behavior for the Traefik Ingress controller), until the communication requirements associated with any backend services have been fully tested.

Finally, manually managing TLS certificates associated with Ingress objects represents a significant operational overhead. Jetstack’s cert-manager controller can be used to automate the process of obtaining and renewing TLS certificates from external certificate authorities, such as Let’s Encrypt.

Written by Puja Abbassi — Developer Advocate @ Giant Swarm

Ready to get your cloud native project into production? Simply request your free trial at https://giantswarm.io/