How to Trust Custom SSL Certificates in HTTPS Connections

Goal

As a customer I want to establish a connection via "Custom Protocol (including http/https)" to my own server which has self-signed or CAcert certificate. 

Problem 

Already during connection setup there is an error message

and the following line within the application log file is seen.

Error message

java.lang.RuntimeException: Cannot create connection. Reason is sun.security.validator.ValidatorException: PKIX path building failed: 
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target, PKIX path building failed: 
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target, unable to find valid certification path to requested target

How to get custom certificate into JVM?

As it will be necessary to store the server certificate within the Java VM, how can I do this? 

Solution

Store the server certificate within the KeyStore file of the JVM. 

Pre-Requirement

Gather the root certificates of the particular authority and import them via keytool.

curl -k -o "cacert-root.crt"   "https://www.cacert.org/certs/root.crt"
curl -k -o "cacert-class3.crt" "https://www.cacert.org/certs/class3.crt"
echo $JAVA_HOME
sudo keytool -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -import -trustcacerts -v -alias cacertclass3 -file cacert-class3.crt
sudo keytool -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -import -trustcacerts -v -alias cacertclass1 -file cacert-root.crt

This step is only necessary if the RootCA is not trusted and which is the case for the in this example used CAcert

Step-by-Step

1.) Gather and import the server certificate.

openssl s_client -connect www.<youraddress>.de:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > <youraddress>.pem
sudo keytool -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -import -trustcacerts -v -alias <youraddress>cert -file <youraddress>.pem

2.) To make sure that JVM is using the correct store, include in etc/das-env.sh

export JAVA_OPTIONS="$JAVA_OPTIONS -Djavax.et.ssl.trustStore=${JAVA_HOME}/lib/security/cacerts"

Troubleshooting

Keep in mind that the JVM do not support all possible keysizes. In JVM 1.6 the maximum is 1024bit. It can lead you into an error.

java.lang.RuntimeException: Cannot create connection. Reason is java.lang.RuntimeException: Could not generate DH keypair, Could not generate DH keypair, Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
	at datameer.dap.sdk.datastore.FileDataStoreModel.testConnect(FileDataStoreModel.java:58)

This will be enhanced according JDK 8 Security Enhancements.

Quote: "Lifting of the keysize restriction from 1024 to 2048 for Diffie-Hellman (DH)"

Further Information

For more information, e.g where to find or how to set the KeyStore path, please have a look into Secure Socket Extension (JSSE)Reference Guide

Review also from Hadoop distributors available documentation like Creating Java Keystores and TruststoresUnderstanding the SSL Keystore Factory and Demystify LDAP, SSL, CA Cert integration.

Or if trying to connect to an specific service, vendor documentation like Configure External SSL for Tableau.