Working with Heroku for deploying apps (java, nodejs, etc..) is made very easy but while integrating one of the service hosted on AWS, I was getting SSLHandshakeException and could not figure it out initially how to resolve the issue.
Exception while making a request to the target system from the app hosted on Heroku:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX path building failedsun.security.provider.certpath.SunCertPathBuilderException: unable to find validcertification path to requested target
Heroku allows us to customise the JDK. To Add a custom trust store
1) Download the base keystore (cacert) from following link
download the base Heroku keystore
2) Rename downloaded file to cacerts (heroku_cacerts to cacerts)
3) Add the certificate (.pem) file of the target system by executing the following
keytool -import -keystore /Users/dsinghvi/Downloads/cacerts -file
/Users/dsinghvi/Downloads/target_system_certifacte.pem
4) Add the cacerts file file to you project as follows (in the folder <PROJET_DIR_PATH>/.jdk-overlay/jre/lib/security/)
|
5) Git add, commit and push to Heroku app
git add .jdk-overlay/jre/lib/security/cacertsgit commit -m "custom trust store for certificate issue"git push heroku master
5) Optionally verify if cacerts has been updated
Added cacerts would be overridden in the /app/.jdk/jre/lib/security (jdk1.8) and /app/.jdk/lib/security (JDK 1.9 and above)
This can be verified in the app deployed using:
heroku run bash --app <APP_NAME>
5) Optionally if you want to verify whether trust store has been updated or not
Before importing target system certificate
keytool -list -v -keystore /Users/dsinghvi/Downloads/cacerts > cert1.txt
After importing target system certificate
keytool -list -v -keystore /Users/dsinghvi/Downloads/cacerts > cert2.txt
You would find the difference between cert1.txt and cert2.txt as follows: