# Ingress: TLS

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](https://letsencrypt.org/), [Cloudflare](https://www.cloudflare.com/en-gb/application-services/products/ssl/), and many others.

## Generate Self-Signed Certificate

For local setup we can generate self-signed certificate.

```bash
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.

```yaml
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.

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

As usual check it using `kubectl get` command.

```bash
➜ 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.

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

Lets apply and validate.

```bash
➜ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/simple-ingress configured
```

```bash
➜ 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.

```bash
➜ 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.

```bash
➜ 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

* [https://kubernetes.io/docs/concepts/services-networking/ingress/](https://kubernetes.io/docs/concepts/services-networking/ingress/)
* [https://kubernetes.io/docs/concepts/configuration/secret/](https://kubernetes.io/docs/concepts/configuration/secret/)
