简体   繁体   中英

NGINX Ingress controller, SSL and optional_no_ca

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.

So what exactly "optional_no_ca" is doing and why "on" fails the requests?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM