0

Following is my Kubernetes configuration. The API deployed using this config works as expected when SSL verification is disabled by the client or when HTTP is used instead of HTTPS. But on enabling, it throws SSL Error: Unable to verify the first certificate. The SSL certificate files are added as Kubernetes secret and the API is exposed on port 8080.

---
apiVersion: "v1"
kind: "ConfigMap"
metadata:
  name: "test-config"
  namespace: "default"
  labels:
    app: "test"
data:
  ENV: "DEV"
---
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
  name: "test"
  namespace: "default"
  labels:
    app: "test"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "test"
  template:
    metadata:
      labels:
        app: "test"
    spec:
      containers:
        - name: "test"
          image: "gcr.io/test-project/test:latest"
          env:
            - name: "ENV"
              valueFrom:
                configMapKeyRef:
                  key: "ENV"
                  name: "test-config"
---
apiVersion: "extensions/v1beta1"
kind: "Ingress"
metadata:
  name: "test-ingress"
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "test-static-ip"
  labels:
    app: "test"
spec:
  tls:
  - hosts:
      - "test.myhost.com"
    secretName: "test-ssl-certificate"
  backend:
    serviceName: "test-service-nodeport"
    servicePort: 8080
  rules:
  - host: "test.myhost.com"
    http:
      paths:
      - path: "/*"
        backend:
          serviceName: "test-service-nodeport"
          servicePort: 8080
---
kind: "Service"
apiVersion: "v1"
metadata:
  name: "test-service-nodeport"
spec:
  selector:
    app: "test"
  ports:
    - protocol: "TCP"
      port: 8080
      targetPort: 8080
  type: "NodePort"

Go server code

http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServeTLS(":8080", "server.crt", "server.key", nil)
if err != nil {
    log.Fatal("ListenAndServe: ", err)
}
sumit
  • 37
  • 4
  • 9
  • Have you checked that the order that the certs are presented complies with https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.2 ? – Nigel Savage Jul 30 '21 at 16:06
  • @NigelSavage I just added the code for my Go server. Is this the right way to send a Certificate message? – sumit Jul 30 '21 at 19:10
  • say we have a CA cert that we have used in a CSR to sign your 'server.crt' then the error message 'Unable to verify the first certificate' Could indicate we need to present the CA cert in a cert chain. So a client request would include the ca cert, but also the order the client presents its certs would be 1 server.crt, 2 CA cert, follows from the rfc5246 "The sender's certificate MUST come first in the list. Each following certificate MUST directly certify the one preceding it" I am not sure if this is your issue, it would only be an issue if your "server.crt" was signed by a ca – Nigel Savage Jul 30 '21 at 19:40
  • @NigelSavage When I try to open the URL in a browser, it works fine. The above error is thrown when other systems try to access it. – sumit Jul 30 '21 at 19:56
  • The browser has access to all the certs that exist in the operating system, for the mac thats the keychain https://www.amsys.co.uk/understanding-mac-os-x-keychain/. A good next step for debugging would be to use 'openssl s_client -connect -debug' see https://stackoverflow.com/questions/17742003/how-to-debug-ssl-handshake-using-curl – Nigel Savage Jul 30 '21 at 21:16
  • How did you create the certificate? Is it self-signed or issued by a CA (i.e. did you generate a CSR)? – Gari Singh Jul 31 '21 at 09:58
  • @GariSingh It is issued by CA – sumit Aug 02 '21 at 13:22
  • It means that the web server you are connecting to is misconfigured. Even if it works in your browser, it may not be including all the public certificates in the chain needed for a cache-empty client to verify. I recommend checking the site in the SSLlabs tool: https://www.ssllabs.com/ssltest/ and check whether you are getting this error : This server's certificate chain is incomplete. – Jyothi Kiranmayi Aug 02 '21 at 13:38
  • @JyothiKiranmayi I do see the above error. Could this be because my SSL certificate contains wildcard, *.myorg.mycompany.io? – sumit Aug 02 '21 at 15:04
  • No, your server needs to serve not just the certificate for your domain, but also the intermediate certificates too. Check this [stack post](https://stackoverflow.com/questions/31673587/error-unable-to-verify-the-first-certificate-in-nodejs) which discusses similar issue. – Jyothi Kiranmayi Aug 02 '21 at 15:22

1 Answers1

0

A potential cause for this could be intermediate certificates were not installed on the server properly which caused a breakdown in the certificate chain. Even if it works in your browser, it may not be including all the public certificates in the chain needed for a cache-empty client to verify. Here are some preliminary troubleshooting steps:

Verify that your certificate chain is complete [https://certificatechain.io/ ]

Verify your server’s configuration [https://www.ssllabs.com/ssltest/ or https://www.sslshopper.com/ssl-checker.html ]

Look for this error: This server's certificate chain is incomplete.
And this: Chain issues.........Incomplete

If you encounter these issues, it means that the web server you are connecting to is misconfigured and did omit the intermediate certificate in the certificate chain it sent to you. Your server needs to serve not just the certificate for your domain, but also the intermediate certificates too.

Intermediate certificate should be installed on the server, along with the server certificate. Root certificates are embedded into the software applications, browsers and operating systems. The application serving the certificate has to send the complete chain, this means the server certificate itself and all the intermediates.

Refer stack post and combine the server certificate and intermediate certificate into a chained certificate for information.

Jyothi Kiranmayi
  • 2,090
  • 5
  • 14