We are using Kubernetes and we need to check the client cert. What we need is to configure the Nginx ingress controller in order to pass the client certificate (if present) to the back-end service. We successfully configured it in our test environment. Here we have the following version:
- Container runtimedocker://19.3.8
- Kubelet version v1.17.6
- nging 1.17
We used this ingress configuration:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: login-cns-produzione-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/configuration-snippet: "proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;"
nginx.ingress.kubernetes.io/server-snippet: "ssl_verify_client optional_no_ca ;"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- login-cns.it
rules:
- host: login-cns.it
http:
paths:
- path: /
backend:
serviceName: login-cns-produzione-service
servicePort: 443
In our production environment, something is newer than the test. These are the versions in production:
- Container runtimedocker://19.3.15
- Kubelet versionv1.18.15
- nging 1.19
The issue in production is that although we specify the directive optional_no_ca
the ingress controller asks for the client certificate and tries to validate it and it fails
Do you have any idea about why this happens?
Thank you
Angelo
EDIT
By reading here it seems I should use these annotations. But by adding them, the client certificate is not asked by Nginx
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: login-cns-test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
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: "wso2is-collaudo/iamcoll-it"
# 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"
nginx.ingress.kubernetes.io/auth-tls-error-page: "/cns/saml/dettagli-utente"
spec:
tls:
- hosts:
- login-cns-test.it
rules:
- host: login-cns-test.it
http:
paths:
- path: /
backend:
serviceName: login-cns-test-service
servicePort: 443
The very strange thing is that with the previous annotation, I have some X.509 authentications successful and others unsuccessful. I really can't explain the issue.
More info about the versions:
- nginx ingress controller version: nginx-ingress-controller:nginx-0.35.0-rancher2
- nginx version: 1.19.2
- openss version: OpenSSL 1.1.1g 21 Apr 2020
Any tips would be very appreciated... I'm fighting on this issue for several days
EDIT 2
If I use this configuration:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: login-cns-test-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
error_page 495 496 497 /cns/saml/dettagli-utente;
nginx.ingress.kubernetes.io/server-snippet: |
ssl_verify_client optional_no_ca;
if ($ssl_client_verify != SUCCESS) {
return 495;
}
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- login-cns-test.it
rules:
- host: login-cns-test.it
http:
paths:
- path: /
backend:
serviceName: login-cns-test-service
servicePort: 443
The client certificate is asked but, then, Nginx fails on certificate verification and it stops... It doesn't allow the request to be routed to the default backend where I have all the business logic to check and verify the certificate
EDIT 3
In my nginx ingress controller logs I see:
2021/06/14 19:17:29 [crit] 9793#9793: *89059516 SSL_do_handshake() failed (SSL: error:0407E068:rsa routines:RSA_verify_PKCS1_PSS_mgf1:bad signature error:1417B07B:SSL routines:tls_process_cert_verify:bad signature) while SSL handshaking, client: XXX.YY.ZZ.WW, server: 0.0.0.0:443
So far, so good... I want that my Java application checks the certificate. But all the flow stops here. It seems I can't correctly configure the Nginx ingress controller error_page
directive. Maybe should I configure the Nginx ingress controller ConfigMap (https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/configmap.md#custom-http-errors)?