Configuring Certificate-Based Mutual Authentication with Kubernetes Ingress-Nginx

“two man doing shake hands” by rawpixel on Unsplash

What is Mutual Authentication?

Mutual SSL authentication or certificate based mutual authentication refers to two parties authenticating each other through verifying the provided digital certificate so that both parties are assured of the others’ identity.

Mutual Authentication flow from codeproject.com

Setting Up the Ingress Controller

Setting Up Mutual Authentication

# 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
$ 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
$ 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
$ 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
$ 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"
$ curl https://meow.com/ -k
...
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
....
$ 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
...
$ kubectl get pods -n kube-system | grep nginx-ingress-controller
nginx-ingress-controller-5984b97644-qbwtv 1/1 Running
$ kubectl exec -it -n kube-system nginx-ingress-controller-5984b97644-qbwtv cat /etc/nginx/nginx.conf | grep ssl_client_certificate -A 1ssl_client_certificate /etc/ingress-controller/ssl/default-my-certs.pem;
ssl_verify_client on;
$ kubectl get pods -n kube-system | grep nginx-ingress-controller
nginx-ingress-controller-5984b97644-qbwtv 1/1 Running
$ kubectl logs -n kube-system nginx-ingress-controller-5984b97644-qbwtv
....
I0831 21:45:34.090212 5 nginx.go:271] Starting NGINX process
....

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store