Search code examples
javasslssl-certificatetomcat8sslhandshakeexception

SSLHandshakeException with valid certificate on Tomcat server


I have an Apache web server fronting a Tomcat 8 web server that is running my website, and I'm switching the top-level domain from my.website.ie to my.website.com. I have some code that runs in response to a particular request that generates a PDF. That code fetches an image (using a URL) which is served from the same web server e.g.

Image.getInstance(new URL("https://my.website.com/img/myimage.png"))

In addition to the domain change, I'm also changing my SSL certificate provider to LetsEncrypt (free SSL certs). My development website at the new .com domain is running and the certificate is valid and does not expire for a number of months.

I have another development server running on a separate machine that is still using the .ie domain. The Tomcat codebase running on both of these servers are identical right now. They are both trying to fetch the image at the URL shown above in that particular piece of code.

On the .ie server, the request that generates the PDF works correctly, without any problems fetching the image. On the .com server, the request fails with this error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

My understanding of this error is that the certificate at the target URL is not trusted (e.g. self-signed), but that is not true in this case. Also, both of the servers are hitting the same URL for the image, so why is one server trusting the certificate and the other not?

I haven't made any additional configuration changes on the .ie server that I haven't made on the .com server (with respect to setting up the new certificate), so is there some other (mis)configuration that I haven't considered?


Solution

  • Not trusted means the used CA is not trusted by the software. Self-signed certificates are never trusted.

    Java has it's own trust store (only on Linux the system trust store is used AFAIR?). If the CA certificate is newer than the used Java version it may happen that Java does not trust the CA. Conclusion: Update your Java.

    According to this Stackoverflow answer you need at least Java 8u101 for Let's Encrypt support:

    Does Java support Let's Encrypt certificates?