javax.net.ssl.SSLHandshakeException when loading Graphviz
TimEngie opened this issue · 5 comments
Description
I recently upgraded to the latest docker image (3054) of Structurizr on-prem.
However, when I try to change the lay-out of my diagrams, I can't use the diagram editor (https://www.structurizr.com/help/diagram-editor) anymore.
When looking into the docker logs I can see that there is a javax.net.ssl.SSLHandshakeException thrown when trying to load the diagram editor.
My PC is running from behind a proxy (ZScaler) however, editing the diagram layout was working in the previous version
Steps to reproduce
- From the Structurizr home page open any workspace
- Click on Diagrams
- The icon with the pencil is shown when opening the "Diagrams" page
- Icon disappears after loading and changing the layout is not possible anymore.
Screenshot
No response
Code sample
No response
Configuration
No response
Severity
Major
Priority
Medium
Resolution
I have no budget, please fix this for free
More information
2023-05-02 11:42:12 javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2023-05-02 11:42:12 at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLHandshake.consume(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
2023-05-02 11:42:12 at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.executeHandshake(SSLConnectionSocketFactory.java:303)
2023-05-02 11:42:12 at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
2023-05-02 11:42:12 at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:251)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:181)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:447)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.connectEndpoint(InternalExecRuntime.java:162)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.connectEndpoint(InternalExecRuntime.java:172)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:142)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:192)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.HttpRequestRetryExec.execute(HttpRequestRetryExec.java:96)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ContentCompressionExec.execute(ContentCompressionExec.java:152)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.RedirectExec.execute(RedirectExec.java:115)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(InternalHttpClient.java:170)
2023-05-02 11:42:12 at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:123)
2023-05-02 11:42:12 at com.structurizr.view.ThemeUtils.loadThemes(ThemeUtils.java:74)
2023-05-02 11:42:12 at com.structurizr.onpremises.web.graphviz.GraphvizController.post(GraphvizController.java:32)
2023-05-02 11:42:12 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2023-05-02 11:42:12 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2023-05-02 11:42:12 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2023-05-02 11:42:12 at java.base/java.lang.reflect.Method.invoke(Unknown Source)
2023-05-02 11:42:12 at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
2023-05-02 11:42:12 at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
2023-05-02 11:42:12 at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
2023-05-02 11:42:12 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
2023-05-02 11:42:12 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
2023-05-02 11:42:12 at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
2023-05-02 11:42:12 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071)
2023-05-02 11:42:12 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964)
2023-05-02 11:42:12 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
2023-05-02 11:42:12 at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
2023-05-02 11:42:12 at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
2023-05-02 11:42:12 at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
2023-05-02 11:42:12 at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
2023-05-02 11:42:12 at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
2023-05-02 11:42:12 at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122)
2023-05-02 11:42:12 at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
2023-05-02 11:42:12 at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:102)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:93)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:219)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
2023-05-02 11:42:12 at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
2023-05-02 11:42:12 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
2023-05-02 11:42:12 at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
2023-05-02 11:42:12 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
2023-05-02 11:42:12 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
2023-05-02 11:42:12 at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
2023-05-02 11:42:12 at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
2023-05-02 11:42:12 at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
2023-05-02 11:42:12 at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at com.structurizr.onpremises.web.NoOpSpringSessionRepositoryFilter.doFilter(NoOpSpringSessionRepositoryFilter.java:14)
2023-05-02 11:42:12 at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
2023-05-02 11:42:12 at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
2023-05-02 11:42:12 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:102)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
2023-05-02 11:42:12 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
2023-05-02 11:42:12 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
2023-05-02 11:42:12 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
2023-05-02 11:42:12 at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
2023-05-02 11:42:12 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
2023-05-02 11:42:12 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
2023-05-02 11:42:12 at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
2023-05-02 11:42:12 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
2023-05-02 11:42:12 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
2023-05-02 11:42:12 at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
2023-05-02 11:42:12 at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
2023-05-02 11:42:12 at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)
2023-05-02 11:42:12 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)
2023-05-02 11:42:12 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
2023-05-02 11:42:12 at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
2023-05-02 11:42:12 at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
2023-05-02 11:42:12 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
2023-05-02 11:42:12 at java.base/java.lang.Thread.run(Unknown Source)
2023-05-02 11:42:12 Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2023-05-02 11:42:12 at java.base/sun.security.validator.PKIXValidator.doBuild(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.validator.Validator.validate(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
2023-05-02 11:42:12 ... 128 more
2023-05-02 11:42:12 Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2023-05-02 11:42:12 at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
2023-05-02 11:42:12 at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
2023-05-02 11:42:12 at java.base/java.security.cert.CertPathBuilder.build(Unknown Source)
2023-05-02 11:42:12 ... 133 more
I suspect one of the themes you're using can't be loaded via HTTPS:
...
2023-05-02 11:42:12 at com.structurizr.view.ThemeUtils.loadThemes(ThemeUtils.java:74)
2023-05-02 11:42:12 at com.structurizr.onpremises.web.graphviz.GraphvizController.post(GraphvizController.java:32)
Ok, after some experimenting I discovered that the latest version seem to expect the views to be explicitly defined before the layout can be edited, while it was still possible in the older version(s) I was using (I don't know the exact version as I have been deleting the Docker Images) to edit the "default" generated views when no view was explicitly defined.
So when I add e.g.
...
views {
...
systemlandscape "SystemLandscape" {
include *
}
....
}
...
I only have the "SystemLandscape" view, but I can modify the layout of that one.
A bit weird this causes a SSLHandshakeException ihmo.
while it was still possible in the older version(s)
I'm guessing this must have been a very old version, since the createDefaultViews()
with automatic layout was introduced in June 2020 -> structurizr/java@08d7b12
A bit weird this causes a SSLHandshakeException ihmo.
As I said, I suspect it's a theme related issue. Are you using any themes?
while it was still possible in the older version(s)
I'm guessing this must have been a very old version, since the
createDefaultViews()
with automatic layout was introduced in June 2020 -> structurizr/java@08d7b12
It was indeed an old version but not that old, I think I started experimenting with Structurizr OnPrem since it became free to use (if I remember correctly).
A bit weird this causes a SSLHandshakeException ihmo.
As I said, I suspect it's a theme related issue. Are you using any themes?
No themes I was using just this views "code":
views {
theme default
styles {
element "External System" {
background #999999
}
}
The automatic layout support will need to load any themes in case they have element width/height properties that will alter the layout, and theme default
is just a DSL shortcut for theme https://static.structurizr.com/themes/default/theme.json
, so you are using a theme. I suspect that the server running your on-premises installation cannot load https://static.structurizr.com/themes/default/theme.json
for some reason, which is why you're seeing the SSL handshake exception.