1

In my project we have a custom keystore that we were using with Spring. However, in the upgrade from Spring to SpringBoot, we now get this error:

    javax.xml.ws.soap.SOAPFaultException: Problem writing SAAJ model to stream: sun.security.validator.ValidatorException: No trusted certificate found
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
    at com.sun.proxy.$Proxy131.setGBUserSession(Unknown Source)
    at <ControllerClass>
    at <ControllerClass.submit>
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:164)
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.ctc.wstx.exc.WstxIOException: sun.security.validator.ValidatorException: No trusted certificate found
    at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:261)
    at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:213)
    at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:172)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:541)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:474)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:377)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:330)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
    ... 62 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1334)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1309)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:259)
    at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:168)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1278)
    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.unBuffer(AbstractThresholdOutputStream.java:89)
    at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:63)
    at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:71)
    at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
    at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:100)
    at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:225)
    at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:259)
    ... 71 more
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
    at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:397)
    at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:134)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
    ... 95 more

We have a custom keystore that we are using to store our certificate, and I have checked and the alias we are using can be found in the keystore. The keypassword as well as the keystore password are all correct as well, according to my lead.

I even tried removing the alias and reimporting the certificate into the keystore with the same alias. But then I get the error that Caused by: org.apache.ws.security.WSSecurityException: Cannot find key for alias: [key-alias]

Once again this worked in Spring, but now it doesn't work in Spring Boot. Has Spring Boot changed how it validates a certificate in this upgrade?

Thanks in advance for any resources you can point me towards, haven't been able to find anything yet on the docs that doesn't involve the password being incorrect being the main issue.

EDIT1: I should mention that I actually got rid of this error by using the cacerts keystore in the jre after importing the certificate into that keystore, but that is not how it should be done with the project, it should use this custom keystore. My guess has been that the keystore is messed up but I don't know how to check that.

EDIT2: I have located the problem to be a cxf.xml file that I have in my resources folder. It is set up as such:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xmlns:sec="http://cxf.apache.org/configuration/security"
       xsi:schemaLocation="
          http://cxf.apache.org/configuration/security
          http://cxf.apache.org/schemas/configuration/security.xsd
          http://cxf.apache.org/transports/http/configuration
          http://cxf.apache.org/schemas/configuration/http-conf.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<http:conduit name="*.http-conduit">
 <http:tlsClientParameters>

      <sec:keyManagers keyPassword="@keyPassword@">
        <sec:keyStore type="JKS" password="@keyStorePassword@"
                      file="@keyStoreFilePath@"/>
      </sec:keyManagers>

      <sec:trustManagers>
        <sec:keyStore type="JKS" password="@keyStorePassword@"
                      file="@keyStoreFilePath@"/>
      </sec:trustManagers>
      <sec:cipherSuitesFilter>
        <!-- these filters ensure that a ciphersuite with
             export-suitable or null encryption is used,
             but exclude anonymous Diffie-Hellman key change as
             this is vulnerable to man-in-the-middle attacks -->
        <sec:include>.*_EXPORT_.*</sec:include>
        <sec:include>.*_EXPORT1024_.*</sec:include>
        <sec:include>.*_WITH_DES_.*</sec:include>
        <sec:include>.*_WITH_AES_.*</sec:include>
        <sec:include>.*_WITH_NULL_.*</sec:include>
        <sec:exclude>.*_DH_anon_.*</sec:exclude>
      </sec:cipherSuitesFilter>
    </http:tlsClientParameters>

 </http:conduit>

</beans>

If i set the paths and passwords in here to be the jre keystore, it works. These need to be the custom keystore.

Daniel Hawes
  • 77
  • 1
  • 1
  • 9
  • see, whether [this answer/questions](https://stackoverflow.com/questions/27724544/specifying-trust-store-information-in-spring-boot-application-properties) can help you ....especially `-Djavax.net.debug=ssl` – xerx593 May 04 '18 at 20:03
  • I tried those answers and it seems not to work. I created a ssl configuration bean and truststore and password are all set up correctly now as well. See EDIT2 above for more info. – Daniel Hawes May 04 '18 at 20:44
  • The `@...@` replacements are done via pre-build(ant/maven) or during runtime (spring)? everything kosher there!?? – xerx593 May 05 '18 at 07:54
  • They are done during runtime if I'm not mistaken, everything appears to work there, unsure how to check with the cxf.xml file if it is getting the correct values – Daniel Hawes May 07 '18 at 13:29
  • what about `-Djavax.net.debug=ssl` `[|all]` ? (find out, who/what replaces `@..@`!;) – xerx593 May 08 '18 at 18:21
  • ..and `spring-beans-2.0.xsd` sounds quite old!! (in my mind spring-boot came up with/dependends on spring >= 3.x) what is your spring-version? (it should match spring-beans.xsd -version) – xerx593 May 08 '18 at 18:28

2 Answers2

1

So i was able to resolve this issue. I had turned on -Djavax.net.debug=ssl before but had not understood the output correctly. I was under the impression that this was a specific certificate that I kept trying to use that was throwing the issues. It turned out it was looking for a completely different certificate and crashing. For me it was a root CA that happened to be missing from my keystore.

Daniel Hawes
  • 77
  • 1
  • 1
  • 9
0

How are you loading the keystore ? And which version of Spring are you using ? There might be a mismatch in property file values .

R Rai
  • 1
  • 1
  • 1
  • I have a properties file to filter as such: `keyStoreFilePath=` which is passed through to application.properties as `keyStoreFilePath=@keyStoreFilePath@` and used in a signature.properties file as `org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=@keyStorePassword@ org.apache.ws.security.crypto.merlin.keystore.alias=@keyAlias@ org.apache.ws.security.crypto.merlin.keystore.file=@keyStoreFilePath@` – Daniel Hawes May 04 '18 at 20:02