Java not trusting Letsencrypt certificates

A while ago, I ran into an issue where REST calls triggered from within my Java application to a different Java Api running on another server failed, even though everything worked in my test environment. The stack trace showed the following exception:

sun.security.validator.ValidatorException: PKIX path 
building failed: sun.security.provider.certpath.
SunCertPathBuilderException: unable to find valid
certification path to requested target

The issue was easily spotted. The failed call was made to a server with a valid SSL certificate generated by Letsencrypt, while all my previous calls were made to an environment without one. It turned out that my version of Java (OpenJDK 1.8.0_161) does not support Letsencrypt as a certificate authority by default. It needs to be added.

The easiest way to do this is with the following command:

keytool -trustcacerts \ 
-keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit \
-noprompt -importcert -file chain.pem

The chain.pem referenced in the command is the pem-file generated by Letsencrypt which can be found in the certificate directory on the target server. In my case, it is found in /etc/letsencrypt/live/. Copy the chain.pem file inside the relevant certificate directory to the machine the call is made from, and run the above command. 

Restarting my Java application was sufficient for Letsencrypt to be registered as a valid CA.

 

Solution source:  https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/13