Skip to main content

Ingress: TLS (Transport Layer Security)

To secure an Ingress (HTTPS) we can do it by specifying a Secret that contains a TLS private key and certificate.

For production server we should use valid TLS certificates from Certificate Authority like letsencrypt.org, Cloudflare, and many others.

Generate Self-Signed Certificate

For local setup we can generate self-signed certificate.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=simple-go.mine/O=simple-org"

Create kubernetes secret

There are two ways to create a TLS secret. First is by using yaml file like this.

apiVersion: v1
kind: Secret
metadata:
name: secret-tls
type: kubernetes.io/tls
data:
tls.crt: <base64-encoded certificate>
tls.key: <base64-encoded key>

Or by using kubectl, and I prefer the later because it's more convenient. So lets create a tls secret.

➜ kubectl create secret tls simple-tls --cert=tls.crt --key=tls.key
secret/simple-tls created

As usual check it using kubectl get command.

➜ kubectl get secret
NAME TYPE DATA AGE
postgres-secret Opaque 2 42h
simple-tls kubernetes.io/tls 2 7s

Setup Ingress TLS

Now that we already have our tls secret ready. We can update the previous ingress definition to use the TLS secret we just created. Add the following tls configuration inside the spec section.

tls:
- hosts:
- simple-go.mine
secretName: simple-tls

Lets apply and validate.

➜ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/simple-ingress configured
➜ kubectl describe ingress simple-ingress 
Name: simple-ingress
Labels: <none>
Namespace: default
Address: 192.168.49.2
Ingress Class: nginx
Default backend: <default>
TLS:
simple-tls terminates simple-go.mine
Rules:
Host Path Backends
---- ---- --------
simple-go.mine
/ simple-go:8080 (10.244.0.88:8080,10.244.0.89:8080,10.244.0.90:8080)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 15s (x3 over 7h1m) nginx-ingress-controller Scheduled for sync

After our ingress updated we can test it using same curl in previous page.

curl --resolve "simple-go.mine:80:127.0.0.1" -i http://simple-go.mine
HTTP/1.1 308 Permanent Redirect
Date: Fri, 31 Jan 2025 10:39:16 GMT
Content-Type: text/html
Content-Length: 164
Connection: keep-alive
Location: https://simple-go.mine

<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>

As you can see above the request is being redirected to https which is port 443.

Now lets try to curl using https to port 443. This time we add -k or --insecure to allow insecure connection because we are using self-signed certificate. If not we will get failed to verify certificate error.

curl --resolve "simple-go.mine:443:127.0.0.1" -i -k https://simple-go.mine
HTTP/2 200
date: Fri, 31 Jan 2025 10:42:35 GMT
content-type: text/plain; charset=utf-8
content-length: 65

[{"id":1,"content":"Hello!"},{"id":2,"content":"Good Morning!"}]

References