In my java application I need to send POST requests to a server sitting behind https. On the machine where my java application is running there is a java trust store in: /usr/local/comp.jks that contains the certificate for the server I need to interact with (its already imported).
The problem is that I cannot control how the JVM is started that will run my java application - e.g. by adding:
-Djavax.net.ssl.trustStore=/usr/local/comp.jks to the VM arguments.
Is it possible to load the trust store in the above path at runtime from my application after the JVM has started so I can authenticate against the https site?
I have only found guides on how to import certificates at runtime but that I cannot use - also since I don't have the password for /usr/local/comp.jks
Below my current implementation (in groovy):
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.security.KeyManagementException; import java.security.KeyStore import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException import java.security.cert.X509Certificate import java.util.Base64; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpsClientImpl extends AbstractHttpClient { private String username = null; private String password = null; public HttpsClientImpl (String username, String password) { this.username=username; this.password=password; } @Override public String sendRequest(String request, String method) { System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" ); URL url = new URL(request); HttpsURLConnection con = (HttpsURLConnection) url.openConnection() // Set auth byte[] name = (username + ":" + password).getBytes(); String authStr = Base64.getEncoder().encodeToString(name); con.setRequestProperty("Authorization", "Basic " + authStr) con.setRequestMethod(method); writeResult(con); return con.getResponseCode(); } private void writeResult(HttpsURLConnection con) throws IOException { if(con!=null){ BufferedReader br = null; if (200 <= con.getResponseCode() && con.getResponseCode() <= 299) { br = new BufferedReader(new InputStreamReader(con.getInputStream())); } else { br = new BufferedReader(new InputStreamReader(con.getErrorStream())); } try { String input; while ((input = br.readLine()) != null){ System.out.println(input); } br.close(); } catch (IOException e) { e.printStackTrace(); } } } } When I run that I get:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) Caused: sun.security.validator.ValidatorException: PKIX path building failed