0

We are using clj-http with a keystore consisting of a keystore.pfx with a self-signed certificate:

(let [url (str url "api/fetch")
      opts {:keystore "keystore.pfx"
            :keystore-type "pkcs12"
            :keystore-pass "****"
            :body (json/encode {:method "yada"})
            :content-type :json
            :throw-entire-message? true
            :async? false}
      response (http/post url opts)]
  (-> response
      :body
      base64-decode))

The API calls with the keystore works locally to call the API with a client-side cert, but not in a Docker on Kubernetes.

Exception is:

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Any ideas how to fix? Do we need to add it to the JVM some way? If so, where and how to add the pfx?

user2609980
  • 10,264
  • 15
  • 74
  • 143
  • 2
    Most likely you lack the truststore? See e.g. https://github.com/dakrone/clj-http/blob/217393258e7863514debece4eb7b23a7a3fa8bd9/examples/kubernetes_pod.clj#L12-L19 – cfrick Dec 19 '19 at 15:08
  • Thanks @cfrick. The linked example is calling the Kubernetes API and using a trust store for that, we are calling an external API with a self signed certificate. I don't think adding the k8s trust store is relevant for this situation. – user2609980 Dec 19 '19 at 16:11
  • 1
    If you have self signed chains, then you have to put the ca.crt into the truststore and use that. I can reproduce that exact same error by removing `:trust-store` from my requests. The link there just shows how it is done. also relevant: https://github.com/dakrone/clj-http/blob/master/SSL.org – cfrick Dec 19 '19 at 18:03
  • 1
    @ErwinRooijakkers I think cfrick is correct. You're most likely confused by the difference between truststores and keystores - see https://www.baeldung.com/java-keystore-truststore-difference – Juraj Martinka Dec 20 '19 at 08:24
  • @cfrick how can we sign our request with our private key if we only have the public key part in the trust store? I think we need a keystore since we are using a client-side certificate (we have to proof our identity to the server). – user2609980 Dec 20 '19 at 10:23
  • 1
    yes, you need both - see my answer - this is from a project, that uses a client cert to connect to a server, which validates it; if i remove the trust-store from the request (and only use the keystore) i get the same error as you. – cfrick Dec 20 '19 at 11:14

1 Answers1

2

Your self signed client/server certs don't share the chain of trust (this is what the error message is telling you).

Put the CA cert(s) in a trust store, e.g.

keytool -importcert -noprompt -alias ca -file ca.crt -keystore truststore -storepass secret

and add the trust store to the request:

  ; ...
  :trust-store "truststore"  ; XXX
  :trust-store-pass "secret" ; XXX
  :keystore "keystore.pfx"
  :keystore-pass "****"
  ; ...
cfrick
  • 35,203
  • 6
  • 56
  • 68
  • This was it indeed! We added it to the JVM's trust-store, but idea is the same. Thanks a lot for thinking along. – user2609980 Dec 20 '19 at 14:30