How to Configure trusted SSL keystore with Spring boot? - java

Want to introduce HTTPS protocol (trusted certificate) to my Spring Boot(1.3.2.RELEASE) application.
For this purpose tried next SSL properties:
server.ssl.trust-store=classpath:key.jks
server.ssl.trust-store-password=pass
and have the error:
Caused by: java.lang.IllegalArgumentException: Resource location must not be null
at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.util.ResourceUtils.getURL(ResourceUtils.java:131) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.configureSslKeyStore(TomcatEmbeddedServletContainerFactory.java:340) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.configureSsl(TomcatEmbeddedServletContainerFactory.java:323) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
In that error you can see that configureSslKeyStore should be passed.
When I am trying to launch the application with next set of changes:
server.ssl.key-store=classpath:key.jks
server.ssl.key-store-password=pass
server.ssl.trust-store=classpath:key.jks
server.ssl.trust-store-password=pass
Application starts successfully but https is not reachable:
So now I have several questions:
What can be the reason of such behavior, that protocol is unsupported?(Certificate is fresh and not outdated)
Is it correctly that there is no way to configure trusted certificate without redundant properties?
Is there some other more convenient way to configure trusted
SSL?
UPDATE:
It is JAR file and certificate exists inside of it classpath:key.jks"".

The reason was in my .jks file. It was generated in a wrong way.
Here is the link where you can find the correct structure of storekeys.

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

Springboot ssl truststore properties not working

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.

java web service client trying to access web service through SSL - TrustManagerFactoryImpl is not initialized

I'm a web service client and I'm connecting to the web service through SSL.
It's a 2-way SSL and the producer has shared the certificate. I did run the InstallCert.java, got the alias and created a Keystore.
I'm using weblogic application server and I have placed my Keystore in it.
Now when I run it, I'm getting an error,
Caused by: java.lang.RuntimeException: java.lang.IllegalStateException:
TrustManagerFactoryImpl is not initialized
Before this I could see that it is trying to load the identity certificate and the private key. But as per standards the producer isn't willing to share the private key with us.
Any suggestion on this would be of great help to me. Thanks.
I resolved it.
I added my .cer file to cacerts which is referred by the weblogic server (Using keytool import). In the keystores section, I kept the default option (Demo identity and Demo trust). In the SSL section, I went to advanced, click on the checkbox ("Use JSSE SSL").
It worked.
I had this issue connecting to a MySQL database that requires SSL to connect.
It turns out, for me, the driver version needed to be updated in order to properly-handle the trust store configuration in the JDBC URL.

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.

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

Categories

Resources