When connecting to the API Gateway via Policy Manager, some SSL-related stack traces may be observed. An example of such a stack trace snippet is below.
org.springframework.remoting.RemoteAccessException: Could not access HTTP invoker remote service at [https://securespangateway/ssg/manager/<Path>]; nested exception is javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.convertHttpInvokerAccessException(HttpInvokerClientInterceptor.java:212)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:145)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy9.getAssertionResourceData(Unknown Source)
at sun.reflect.GeneratedMethodAccessor14.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.l7tech.gateway.common.spring.remoting.http.a.call(Unknown Source)
at com.l7tech.gateway.common.spring.remoting.http.SecureHttpComponentsHttpInvokerRequestExecutor.doWithSession(Unknown Source)
at com.l7tech.gateway.common.spring.remoting.http.RemotingContext.doRemoteInvocation(Unknown Source)
at com.l7tech.console.util.AdminContextImpl.access$001(Unknown Source)
at com.l7tech.console.util.c.call(Unknown Source)
at com.l7tech.gui.util.at.construct(Unknown Source)
at com.l7tech.gui.util.av.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:147)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flush(AbstractSessionOutputBuffer.java:154)
at org.apache.http.impl.AbstractHttpClientConnection.doFlush(AbstractHttpClientConnection.java:278)
at org.apache.http.impl.AbstractHttpClientConnection.flush(AbstractHttpClientConnection.java:283)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.flush(ManagedClientConnectionImpl.java:175)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:232)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:715)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:520)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:827)
at com.l7tech.gateway.common.spring.remoting.http.SecureHttpComponentsHttpInvokerRequestExecutor.executePostMethod(Unknown Source)
at com.l7tech.gateway.common.spring.remoting.http.SecureHttpComponentsHttpInvokerRequestExecutor.doExecuteRequest(Unknown Source)
at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:136)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:192)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:174)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:142)
... 14 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
The root cause of this behaviour is often the lack of what is called session persistence (aka "sticky sessions" or it's equivalent - language depends on the vendor of the load balancer). In a typical environment, the Gateway cluster will be fronted by load balancer(s). When there are multiple Gateway nodes, sometimes - depending on the configuration of the load balancer - the load balancer may send traffic from the same Policy Manager request to multiple nodes during the handshake rather than just to one Gateway node.
Example scenario where this is often observed:
In this kind of scenario, session persistence should be enabled on the load balancer to keep all the traffic of that single request / thread to one Gateway node rather than sending half the conversation to one node and the other half to another node.
The ideal scenario where this would not be observed:
The load balancer should be configured for session persistence. Please review vendor documentation on the load balancer to enable that functionality. A quick overview of this "best practice" for the load balancer configuration fronting the Gateway is in the Gateway product documentation.
Customers of the CA SaaS Portal & SaaS Gateway: In the CA SaaS infrastructure, the port to clients should use in Policy Manager after the Gateway hostname is 9443 rather than the usual 8443, as 9443 is the port configured for session persistence inside of the CA SaaS infrastructure.