Setting Up the Ingress Controller

There are many ways of configuring Ingress-Nginx on your Kubernetes cluster. If you already have an Ingress-Nginx controller setup, then you can skip this step. However, note that this guide was written using Minikube version 0.30 with Ingress-Nginx version 0.19.

If you just wanna try this out for yourself in Minikube see my previous blog, “Getting Started with Kubernetes Ingress-Nginx on Minikube” , and comeback here once you’ve deployed the ingress controller.

and comeback here once you’ve deployed the ingress controller. For other ways of deploying the ingress controller, you can checkout the Ingress-Nginx deployment documentation.

Setting Up Mutual Authentication

In order to setup Mutual Authentication you will need to perform a couple of steps.

Creating the Certificates

For this example we will be creating self-signed certificates(just for test purposes, not to ever be done in production). As a simple introduction, here are a couple of terms it would be useful to know:

CommonName(CN) : Identifies the hostname or owner associated with the certificate.

: Identifies the hostname or owner associated with the certificate. Certificate Authority(CA) : A trusted 3rd party that issues Certificates. Usually you would obtain this from a trusted source, but for this example we will just create one. The CN is usually the name of the issuer.

: A trusted 3rd party that issues Certificates. Usually you would obtain this from a trusted source, but for this example we will just create one. The CN is usually the name of the issuer. Server Certificate : A Certificate used to identify the server. The CN here is the hostname of the server. The Server Certificate is valid only if it is installed on a server where the hostname matches the CN.

: A Certificate used to identify the server. The CN here is the hostname of the server. The Server Certificate is valid only if it is installed on a server where the hostname matches the CN. Client Certificate: A Certificate used to identify a client/user. The CN here is usually the name of the client/user.

# Generate the CA Key and Certificate

$ openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 356 -nodes -subj '/CN=Fern Cert Authority' # Generate the Server Key, and Certificate and Sign with the CA Certificate

$ openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=meow.com'

$ openssl x509 -req -sha256 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt # Generate the Client Key, and Certificate and Sign with the CA Certificate

$ openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Fern'

$ openssl x509 -req -sha256 -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt

Creating the Kubernetes Secrets

We must store the certificates generated above in a Kubernetes Secret in order to use them in our Ingress-NGINX controller.

In this example, for simplicity, our Secret will contain both our Server Certificate and our CA Certificate. The Ingress Controller will understand which certs to use and where to use them. They can also be Split into Separate Secrets. See here for detailed info.

$ kubectl create secret generic my-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt $ kubectl get secret my-certs

NAME TYPE DATA AGE

my-certs Opaque 3 1m

Deploying an Application with Mutual Authentication

Deploy our pods(containers), using deployments. A deployment, pretty much just manages the state of our pods, It’s out of the scope of this tutorial, but you can learn more here

$ echo "

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: meow

spec:

replicas: 2

selector:

matchLabels:

app: meow

template:

metadata:

labels:

app: meow

spec:

containers:

- name: meow

image: gcr.io/kubernetes-e2e-test-images/echoserver:2.1

ports:

- containerPort: 8080

" | kubectl apply -f - # wait a min for the deployment to be created

$ kubectl get deploy

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE

meow 2 2 2 2 # you should have 2 pods running

$ kubectl get pods

NAME READY STATUS

meow-5557bc7c54-cw2ck 1/1 Running

meow-5557bc7c54-kfzm5 1/1 Running

gcr.io/kubernetes-e2e-test-images/echoserver:2.1 just responds with information about the request.

2. Expose our pods using Services. More info about exposure here

$ echo "

apiVersion: v1

kind: Service

metadata:

name: meow-svc

spec:

ports:

- port: 80

targetPort: 8080

protocol: TCP

name: http

selector:

app: meow

" | kubectl apply -f - # wait a min for the service to be created

$ kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)

meow-svc ClusterIP 10.107.78.24 <none> 80/TCP

3. Setup the Ingress Rules, and add meow.com to /etc/hosts

$ echo "

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

annotations:

nginx.ingress.kubernetes.io/auth-tls-verify-client: \"on\"

nginx.ingress.kubernetes.io/auth-tls-secret: \"default/my-certs\"

name: meow-ingress

namespace: default

spec:

rules:

- host: meow.com

http:

paths:

- backend:

serviceName: meow-svc

servicePort: 80

path: /

tls:

- hosts:

- meow.com

secretName: my-certs

" | kubectl apply -f - $ kubectl get ing cat-nginx

NAME HOSTS ADDRESS PORTS AGE

meow-ingress meow.com 10.0.2.15 80, 443 1m # Add meow.com to /etc/hosts

$ sudo -- sh -c "echo $(minikube ip) meow.com >> /etc/hosts"

This allows us to access the service meow-svc via https://meow.com/.

TLS is enabled and it is using the tls.key and tls.crt provided in the my-certs secret.

The nginx.ingress.kubernetes.io/auth-tls-secret annotation uses ca.crt from the my-certs secret.

Testing it all out

Sending a request without the Client Certificate and Key, should give a 400 Error as follows:

$ curl https://meow.com/ -k

...

<center><h1>400 Bad Request</h1></center>

<center>No required SSL certificate was sent</center>

....

Sending a request with the Client Certificate and Key, should redirect you to the meow-svc:

$ curl https://meow.com/ --cert client.crt --key client.key -k

...

ssl-client-issuer-dn=CN=Fern Cert Authority

ssl-client-subject-dn=CN=Fern

ssl-client-verify=SUCCESS

user-agent=curl/7.54.0

...

If the above did not work for you, skip down to the troubleshooting section.