NGINX Ingress 控制器、SSL 和 optional_no_ca

5

我从name.com 获得了一张证书。

➜ tree .     
.
├── ca.crt
├── vpk.crt
├── vpk.csr
└── vpk.key

我如何创建了这些密码

我将ca.crt的内容添加到vpk.crt文件的末尾。

(⎈ | 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 -

这是我的入口:

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

证书已经进行了正确的验证,我可以通过各种CLI WebSocket客户端连接,并且https://www.ssllabs.com/ssltest显示我获得了"A+"。
然而,如果我设置 nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" 那么所有东西都停止工作,并且在nginx入口控制器侧(POD日志)会收到400错误。
我对官方文档感到困惑:
optional_no_ca参数(1.3.8,1.2.5)请求客户端证书,但不要求它由受信任的CA证书签名。这是为在外部于nginx执行实际证书验证的情况下使用的。证书的内容可以通过$ssl_client_cert变量访问。
因此,“optional_no_ca”到底在做什么,为什么“on”会导致请求失败?

你使用Cloudflare吗? 你可以尝试使用 nginx.ingress.kubernetes.io/auth-tls-secret: "ca-secret" 替换 nginx.ingress.kubernetes.io/auth-tls-secret: "development/ca-secret" 吗?这个问题在相关的 github issue 中有提到。 我对auth-tls-verify-client有点困惑,你使用的是 nginx.ingress.kubernetes.io/auth-tls-verify-client: "yes",但我认为应该是 nginx.ingress.kubernetes.io/auth-tls-verify-client: "on",因为auth-tls-verify-client中没有yes值,请尝试更改并重新测试一下。 - Jakub
@Jakub - 抱歉,我使用了“on”选项,而不是“yes”。因此,使用“on”时,我遇到了400错误。所以我的问题是想要了解当我们设置“optional_no_ca”时,背后具体发生了什么。 - DmitrySemenov
根据文档,它可以进行可选的客户端证书验证,但是当客户端证书未被来自auth-tls-secret的CA签名时,不会使请求失败。因此,如果使用了auth-tls-verify-client: "on",你收到了400错误,我认为auth-tls-secret可能有问题。你尝试过将其更改为nginx.ingress.kubernetes.io/auth-tls-secret: "ca-secret"并使用上述auth-tls-verify-client: "on"吗? - Jakub
@DmitrySemenov 你好,你还受到这个问题的影响吗?你已经解决了吗? - Dawid Kruk
1个回答

4
Optional_no_ca 是可选的客户端证书验证,当客户端证书未被 auth-tls-secret 中的CA签名时,该验证不会使请求失败。即使指定了optional_no_ca参数,在提供客户端证书时仍然是必需的。如文档1所述,实际的证书验证是在服务外部进行的,而不是在Nginx内进行的。
当设置nginx.ingress.kubernetes.io/auth-tls-verify-client:on时,它将请求一个客户端证书,并要求该证书必须由通过nginx.ingress.kubernetes.io/auth-tls-secret: secretName指定的secret keyca.crt中包含的证书进行签名。
如果不这样做,则证书验证将失败,并显示状态码400(错误的请求)。请参阅此处获取更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接