I have obtained a cert from name.com.
➜ tree .
.
├── ca.crt
├── vpk.crt
├── vpk.csr
└── vpk.key
How I created the secrets
I added ca.crt content at the end of vpk.crt file.
(⎈ | vpk-dev-eks:argocd)
➜ k create secret tls tls-secret --cert=vpk.crt --key=vpk.key --dry-run -o yaml | kubectl apply -f -
(⎈ | vpk-dev-eks:argocd)
➜ kubectl create secret generic ca-secret --from-file=ca.crt=ca.crt --dry-run -o yaml | kubectl apply -f -
This is my ingress:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: websockets-ingress
namespace: development
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
# Enable client certificate authentication
nginx.ingress.kubernetes.io/auth-tls-verify-client: "optional_no_ca"
# Create the secret containing the trusted ca certificates
nginx.ingress.kubernetes.io/auth-tls-secret: "development/ca-secret"
# Specify the verification depth in the client certificates chain
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
# Specify if certificates are passed to upstream server
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
argocd.argoproj.io/sync-wave: "10"
spec:
tls:
- hosts:
- backend-dev.project.com
secretName: tls-secret
rules:
- host: backend-dev.project.com
http:
paths:
- path: /ws/
backend:
serviceName: websockets-service
servicePort: 443
The cert is properly validated, I can connect via various CLI WebSocket clients and https://www.ssllabs.com/ssltest gives me "A+"
However if I set
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
then everything stops working and I get 400 error on the nginx ingress controller side (POD logs).
I am confused from the official docs:
The optional_no_ca parameter (1.3.8, 1.2.5) requests the client certificate but does not require it to be signed by a trusted CA certificate. This is intended for the use in cases when a service that is external to nginx performs the actual certificate verification. The contents of the certificate is accessible through the $ssl_client_cert variable.
Optional_no_ca does the optional client certificate validation and it does not fail the request when the client certificate is not signed by the CAs from auth-tls-secret. Even after specifying the optional_no_ca parameter, it is necessary to provide the client certificate. As mentioned in the document 1, the actual certificate verification is done when the service is external to Nginx.
When you set nginx.ingress.kubernetes.io/auth-tls-verify-client:on, it requests a client certificate that must be signed by a certificate that is included in the secret key ca.crt of the secret specified by nginx.ingress.kubernetes.io/auth-tls-secret: secretName.
If not so, then certificate verification will fail and result in a status code 400 (Bad Request). Check this for further information.