[ 
https://issues.apache.org/jira/browse/HTTPCLIENT-2235?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Oleg Kalnichevski resolved HTTPCLIENT-2235.
-------------------------------------------
    Resolution: Information Provided

> Spring Cloud Vault Config - SocketTimeoutException using 
> HttpComponentsClientHttpRequest
> ----------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-2235
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2235
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpClient (classic)
>    Affects Versions: 4.5.14
>         Environment: Production
>            Reporter: Spectateur
>            Priority: Major
>
> Hello,
> We are using spring cloud vault with spring boot application hosted in a 
> cloud provider, and an hashicorp vault v1.11.2 on premise.
> {code:java}
> <spring-boot.version>2.3.12.RELEASE</spring-boot.version> 
> <groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-vault-config</artifactId><version>2.2.7.RELEASE</version>{code}
> Our Spring boot application use an abstraction for interchangeable HTTP 
> Clients, we are using here Apache HTTP Client httpclient-4.5.13
> {code:java}
>   <dependencies>
>     <dependency>
>       <groupId>org.apache.httpcomponents</groupId>
>       <artifactId>httpclient</artifactId>
>       <version>4.5.10</version>
>       <scope>compile</scope>
>       <exclusions>
>         <exclusion>
>           <artifactId>commons-logging</artifactId>
>           <groupId>commons-logging</groupId>
>         </exclusion>
>       </exclusions>
>     </dependency>
>     <dependency>
>       <groupId>org.apache.httpcomponents</groupId>
>       <artifactId>httpcore</artifactId>
>       <version>4.4.12</version>
>       <scope>compile</scope>
>     </dependency> {code}
> We are experiencing randomly, timeouts during renew (in our case 48H lease) 
> or authentication with the vault.
> These timeouts are produce only when the client does not ACK the FIN from the 
> server.
> *Error detail :*
> {{ }}
> {code:java}
> Sep 18 17:47:08 pod-name-back WARN | | | 
> o.s.v.c.l.SecretLeaseEventPublisher$LoggingErrorListener - [RequestedSecret 
> [path='database/postgres/instance01/creds/own_instance01', mode=RENEW]] Lease 
> [leaseId='database/postgres/instance01/creds/own_instance01/bPz8jG8SmDJXYt36f5ZVVQ3x.BXpj9',
>  leaseDuration=PT48H, renewable=true] Cannot renew lease; nested exception is 
> org.springframework.web.client.ResourceAccessException: I/O error on PUT 
> request for "https://hvault.mysite.com:443/v1/sys/renew": Read timed out; 
> nested exception is java.net.SocketTimeoutException: Read timed out 
> org.springframework.vault.VaultException: Cannot renew lease; nested 
> exception is org.springframework.web.client.ResourceAccessException: I/O 
> error on PUT request for "https://hvault.mysite.com:443/v1/sys/renew": Read 
> timed out; nested exception is java.net.SocketTimeoutException: Read timed 
> out at 
> org.springframework.vault.core.lease.SecretLeaseContainer.doRenewLease(SecretLeaseContainer.java:720)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer.renewAndSchedule(SecretLeaseContainer.java:589)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer.lambda$scheduleLeaseRenewal$0(SecretLeaseContainer.java:581)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer$LeaseRenewalScheduler$1.run(SecretLeaseContainer.java:891)
>  at 
> org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
>  at 
> org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
>  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
> at java.util.concurrent.FutureTask.run(FutureTask.java:266) at 
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
>  at 
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
>  at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
>  at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
>  at java.lang.Thread.run(Thread.java:750) Caused by: 
> org.springframework.web.client.ResourceAccessException: I/O error on PUT 
> request for "https://hvault.mysite.com:443/v1/sys/renew": Read timed out; 
> nested exception is java.net.SocketTimeoutException: Read timed out at 
> org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:746) 
> at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:672) 
> at 
> org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:581) 
> at 
> org.springframework.vault.core.lease.LeaseEndpoints$1.renew(LeaseEndpoints.java:59)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer.lambda$doRenew$2(SecretLeaseContainer.java:752)
>  at 
> org.springframework.vault.core.VaultTemplate.doWithSession(VaultTemplate.java:388)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer.doRenew(SecretLeaseContainer.java:751)
>  at 
> org.springframework.vault.core.lease.SecretLeaseContainer.doRenewLease(SecretLeaseContainer.java:688)
>  ... 12 common frames omitted Caused by: java.net.SocketTimeoutException: 
> Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at 
> java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at 
> java.net.SocketInputStream.read(SocketInputStream.java:171) at 
> java.net.SocketInputStream.read(SocketInputStream.java:141) at 
> sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:464) at 
> sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:68)
>  at 
> sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1346) 
> at sun.security.ssl.SSLSocketImpl.access$300(SSLSocketImpl.java:73) at 
> sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:962) at 
> org.apache.http.impl.conn.LoggingInputStream.read(LoggingInputStream.java:84) 
> at 
> org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
>  at 
> org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
>  at 
> org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280)
>  at 
> org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)
>  at 
> org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
>  at 
> org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
>  at 
> org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
>  at 
> org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157)
>  at 
> org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
>  at 
> org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
>  at 
> org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
>  at 
> org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) at 
> org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at 
> org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at 
> org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
>  at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
>  at 
> org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
>  at 
> org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:87)
>  at 
> org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
>  at 
> org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
>  at 
> org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:109)
>  at 
> org.springframework.vault.core.VaultTemplate.lambda$getSessionInterceptor$1(VaultTemplate.java:200)
>  at 
> org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
>  at 
> org.springframework.vault.client.VaultClients.lambda$createRestTemplate$0(VaultClients.java:128)
>  at 
> org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
>  at 
> org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77)
>  at 
> org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
>  at 
> org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
>  at 
> org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:737) 
> ... 19 common frames omitted{code}
> {{ }}
> After digging into communications between our vault server and the clients we 
> have seen that spring cloud vault framework reuse TLS sessions and TCP 
> sessions that have been created with the previous renew.
> From vault perspective these sessions have been closed accordingly to the 
> vault timeout as vault server didn't receive anymore communications from the 
> client. All network equipments, worker nodes also dropped the original 
> session in kernel table after grace period (TCP end timeout) triggered by 
> receiving FIN from vault server.
> So in the following capture you can see a timeout event on 2022-09-18 
> 17:47:08 that triggered a close_notify from client (see frame N°2741), and 
> which is 15sec after the renew request (read-timeout = 15000ms),
> [!https://user-images.githubusercontent.com/102883284/191934711-67c6d611-55ea-44e9-8523-9c85ab27eb63.png!|https://user-images.githubusercontent.com/102883284/191934711-67c6d611-55ea-44e9-8523-9c85ab27eb63.png]
> The port used during the timeout is the same than the one used for the 
> previous renew 48H before (see frame N° 2725)/
> [!https://user-images.githubusercontent.com/102883284/191936332-8503d5de-e6f8-4ef2-9ebc-8886268fafc4.png!|https://user-images.githubusercontent.com/102883284/191936332-8503d5de-e6f8-4ef2-9ebc-8886268fafc4.png]
> Note that the client does not ACK vault close_notify for TLS / TCP FIN, 
> (frame N°1985 to 1988) but we are not sure that this could explain why the 
> client reuse the same TLS sessions days after.
> But even if the client does not ACK (whereas most of the time it does) the 
> current implementation should timed-out on the client side.
> As the vault client is reusing a session that is no longer existing, the 
> worker node initiate a new port (the sequence number 1 in frame N°2726) and 
> because this new TCP session isn't SYN on next hop network equipment, it is 
> dropped with "first packet isn't SYN error message".
> Even if it was SYN we would end up reaching the vault with the original port 
> that was FIN 48H ago by the vault server itself.
> So here we are exploring ways to understand if it's a bug in or if it a 
> wrongfull use of {{org.apache.http.impl.client }}
> Thanks for your help,



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to