Nginx 控制器客户端身份验证 optional_no_ca 不起作用

Ang*_*ata 6 github nginx kubernetes-ingress configmap nginx-ingress

我们正在使用 Kubernetes,我们需要检查客户端证书。我们需要的是配置 Nginx 入口控制器,以便将客户端证书(如果存在)传递给后端服务。我们在我们的测试环境中成功配置了它。这里我们有以下版本:

  • 容器运行时docker://19.3.8
  • Kubelet 版本 v1.17.6
  • 1.17

我们使用了这个入口配置:

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
Run Code Online (Sandbox Code Playgroud)

在我们的生产环境中,有些东西比测试要新。这些是生产中的版本:

  • 容器运行时docker://19.3.15
  • Kubelet 版本v1.18.15
  • 1.19

生产中的问题是,虽然我们指定了指令,optional_no_ca但入口控制器要求客户端证书并尝试验证它,但它失败了你知道为什么会发生这种情况吗?

谢谢

安杰洛

编辑

通过阅读这里,我似乎应该使用这些注释。但是通过添加它们,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
Run Code Online (Sandbox Code Playgroud)

很奇怪的是,使用之前的注释,我有一些 X.509 身份验证成功,而另一些则不成功。我真的无法解释这个问题。

有关版本的更多信息:

  • nginx入口控制器版本:nginx-ingress-controller:nginx-0.35.0-rancher2
  • nginx 版本:1.19.2
  • openss 版本:OpenSSL 1.1.1g 2020 年 4 月 21 日

任何提示将不胜感激...我在这个问题上斗争了好几天

编辑 2

如果我使用这个配置:

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
Run Code Online (Sandbox Code Playgroud)

请求客户端证书,但是,Nginx 证书验证失败并停止......它不允许将请求路由到默认后端,在那里我拥有检查和验证证书的所有业务逻辑

编辑 3

在我的 nginx 入口控制器日志中,我看到:

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
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好...我希望我的 Java 应用程序检查证书。但所有的流动都到此为止。似乎我无法正确配置 Nginx 入口控制器error_page指令。也许我应该配置 Nginx 入口控制器 ConfigMap ( https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/configmap.md#custom-http-errors )?

小智 2

即使在指定该optional_no_ca参数之后,也需要提供客户端证书,并且由于使用该参数,不强制该证书由可信CA 1 2签名。