Springboot ssl truststore properties not working - java

I am running a spring boot application which is a webservice client and sends requests to a webservice on a Jboss.
A certificate was added on the jboss and since then i started having exception:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
So i searched on google on how to communicate with a cert based Jboss and came up with the idea that I needed to create a trust store from the jboss cert and then use that in my application.yaml
server:
port: 7887
address: 127.0.0.1
ssl:
# enabled: true
trust-store: file:config/myapp.truststore
trust-store-password: myappdomain
These didnt work. So i went with more manual and on the grounds approach
I just did the below and this worked. ( for any one having the same issue this works;I added the truststore in the config directory and the config directory was at the same level as the myapp.jar)
java -Djavax.net.ssl.trustStore=config/myapp.truststore -jar myapp.jar
My question: why did the application.yaml configs didnt work. was i missing something.
the above approach works without a password ( may be because the password is the same on keystore and cert in jboss as the trust store password).
Is there any security issue or any kind of issue with the approach that worked. and for future how can i make the yaml configs work.

It is correct as you wrote it, you need to use javax.net.ssl.trustStore and his pair prop javax.net.ssl.trustStorePassword to check the validity of the remote service you are calling.
I understand the 3 options the following way:
server.ssl.key-store => use to authenticate yourself (the server) to other clients calling you
javax.net.ssl.trustStore => use to authenticate servers you are calling as a client from your Spring Boot app.
server.ssl.trust-store => use only if you are using 2-way ssl with Spring, where you authenticate yourself as a client towards other SSL secured server. Probably you will not use this so often when implementing SSL (one way ssl). So stick with the first two and you are good.

Related

Using https in Rest web service

I have a Rest web service developed in java, glassfish, running on a centos server.
We recently opted to use the https protocol and started testing through the test certificate provided by glassfish itself at deployment time (port 8181).
Using Postman for testing I just needed to disable one option in the configuration: "SSL certificate verification".
However the modules that consumed my service, service destop, in java, started to throw exceptions.
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
In test environment, windows, the lines below corrected the problem, already in production, hundreds, could not solve.
String certificatesTrustStorePath = "/etc/alternatives/jre_1.8.0/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath); System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
The error in centos is the one presented in the post below, already read about the various reasons but could not solve.
Error - trustAnchors parameter must be non-empty
If you know how to solve in linux I appreciate it,but the question is not this ...
Do these lines I have published specify where the cacerts file is (and within my platform certificate)?
But it seems to me wrong ... I've already consumed third party https rest services and never had to specify the certificate path ... this would require me to know structurally some details of a third party server. Am I wrong?
So, I imagine there must be another way to do it ... could anyone help?
Yes, your code specifies a custom path for truststore where the ssl cert is present.
This is the public key shared corresponding to the https protocol for the handshake(either self-signed or signed by a whitelisted CA).
Default path where these get stored is
$JAVA_HOME/jre/lib/security/cacerts
Though above can be overridden.
So in your code, you have overridden the path, to point it where the public key(cert) is already present. Thus it's working for you.
Truststore is just a collection of public keys.
Alternatively, you can import the public key in the default truststore as well to make it work.
In that case, you don't have to explicitly set a different truststore.
There is many ways to do it.
copy your file to $java_home\jre\lib\security\cacerts\ than you don't have to set property manually.
you can also mention path at runtime using
-Djavax.net.ssl.trustStore=/home/user/SSL/mycacerts
-Djavax.net.ssl.keyStore=/home/user/SSL/serverkeystore.jks

Apache CXF issue while using mutual SSL

I am using apache cxf for calling a web service from a weblogic server.The web service is SSL with mutual authentication based authorization.
There were some issues with the weblogic version 10.3 supporting the jdk version which i managed to resolve.
But now i am getting another error and not able to get much help on the internet
Caused by: org.apache.cxf.transport.http.UntrustedURLConnectionIOException: RequireClientCertificate is set, but no local certificates were negotiated. Is
the server set to ask for client authorization?
at org.apache.cxf.ws.security.policy.interceptors.HttpsTokenInterceptorProvider$HttpsTokenOutInterceptor$1.establishTrust(HttpsTokenInterceptorProvider.java:117)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.makeTrustDecision(HTTPConduit.java:1680)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1264)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1234)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:195)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1291)
... 43 more
I am using the configuration given here : http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html
we were getting this error also in these cases:
wrong path to keystore
referencing non existing alias in the keystore
wrong certificate (cert for DEV environment used in TEST environment)
So I would suggest to double check the whole chain of settings to private certificate used to authenthicate against the ws.

Use keystore file to run client for a SOAP WS

I was given a SOAP WS to work with.
They gave me the wsdl file from which I was able to create client stub (I've used wsdl2java utility within cxf).
With that wsdl I was also give a .keystore file and the thing is I do know know how to add it to my keytool (is this is even the right way of putting it?).
I've built a junit test that I run to test my client but I constantly get
HTTP transport 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
Where can I find an easy guide on what to do with this .keystore file?
Thanks
The error means that the server certificate could not be found in your truststore. Check the contents of the .keystore file to see whether it contains the server certificate (listed as trustedEntry in your truststore). If yes, set the following system properties (either using -D JVM parameter or System.setProperty()).
javax.net.ssl.trustStore=<<your .keystore>>
javax.net.ssl.trustStorePassword=<<keystore password>>
If these properties are not set, the default ones will be picked up from your the default location.[$JAVA_HOME/lib/security/jssecacerts, $JAVA_HOME/lib/security/cacerts]
To view the contents of keystore file, use
keytool -list -v -keystore file.keystore -storepass mypassword
To debug the ssl handshake process and view the certificates, set the VM parameter -Djavax.net.debug=all
If the web service requires 2 way SSL, the client needs to send its identity (picked up from your keystore). In this case, your .keystore will contain a privateKeyEntry which will be sent to the server during handshake process. To configure this, set the JVMM properties javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword to point to your keystore.
The next works for me:
Application server configuration. Apache Tomcat/7.0.52. server.xml: set clientAuth="true" in the https connector.
Application server configuration. Apache Tomcat/7.0.52. tomcat-users.xml: crate a user with the DN of the user as it appears in your certificate (subject)
Web service JAX-WS web service eclipse tutorial. Thanks Arpit! Add it a security constraint in the deployment descriptor (web.xml)
Client. Generated with apache-cxf maven plugin.
Main class:
HelloWorldImplService helloWorldImplService = new HelloWorldImplService();
HelloWorld helloWorld = helloWorldImplService.getHelloWorldImplPort();
SayHelloWorld parameters = new SayHelloWorld();
parameters.setArg0("World");
SayHelloWorldResponse helloWorldResponse = helloWorld.sayHelloWorld(parameters);
System.out.println(helloWorldResponse.getReturn());
Client JVM options:
-Djavax.net.ssl.trustStore=/xxxx/cacerts.jks -Djavax.net.ssl.trustStorePassword=xxxx -Djavax.net.ssl.keyStore=/xxx/user.jks -Djavax.net.ssl.keyStorePassword=xxxx
You can take a look here: Java SOAP client with certificate authentication
An excellent blog to help you understand the keystores and certificates imports required for HTTPS SSL handshake:
http://ruchirawageesha.blogspot.in/2010/07/how-to-create-clientserver-keystores.html
Hope it helps you to setup ur client keystore correctly in order to call the web services.
Good Luck!

Is it possible to merge java\jre\security\lib\cacerts file

In my project,I have integrated Spring Security with CAS server authentication. Now my project is an http application where as the CAS server is an Https application. I was getting following exception after Spring Security and CAS integration: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
In order to solve this error ,I replaced CAS server usr\java\jre\lib\security\cacerts file with my local usr\java\jre\lib\security\cacerts file. After this step the error was gone.
Now I want to deploy my application to some other server. In this new server some other applications are also deployed which may be using different CAS authentication. I cannot directly replace my CAS server cacerts file with this new server cacerts file as in that other application deployed may fail.Right? Can anyone suggest what should I do so that cacerts can be merged,or what should be done? i got to know a command called as keytool but unable to understand how it could be used to merge cacerts file. I dont know how to get my CAS server .cer file,I got to know this could be used in merging,please suggest solution
There is a missunderstanding here.
cacerts is Java's default truststore containing all the trusted certificates for known CA's (Verisign etc). So java can by default trust these certificates same way that your browser does.
This truststore should be used when you want to connect to servers that are signed by these CAs.
In all other cases you are expected to use your own custom truststore so that you can trust specific servers.Actually this is the norm.
So what you should be doing is to load in your code your own truststore and provide that to Java's JSSE to use for authentication during handshake

Axis over SSL and 2-way authentication with a PKCS#12 keystore

I have PKCS#12 keystore that I've sucessfully imported in my browser for accessing a server that needs 2-way SSL authentication. Works perfectly reaching any https URL there.
However, I'm unable to access an URL in the same server, and from the same host when using Axis 1.4. The given Axis faultString is:
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
My javax.net.ssl.{keyStore,keyStorePassword,keyStoreType} properties seem to be set up fine.
How can I resolve this?
I came across a simpler answer if all you want is for your client to be able to call the SSL web service and ignore SSL certificate errors. (Of course you would NOT do this in production!, but it sure is handy for testing.)
Just put this statement before you invoke any web services:
System.setProperty("axis.socketSecureFactory",
"org.apache.axis.components.net.SunFakeTrustSocketFactory");
I found this at the Axis wiki.
Finally, importing the certificates into my own truststore, using Andreas Sterbenz's InstallCert, and setting the trustStore properties as indicated here did the trick!

Categories

Resources