Skip to content

javax.net.ssl.SSLException: Connection reset on long running applications #213

@r00ta

Description

@r00ta

We hit javax.net.ssl.SSLException: Connection reset multiple times on our long running application and we found a bug with the following scenario:

  1. the application makes a call
  2. the application keeps running for minutes without making any call
  3. the application makes another call but it gets a Connection reset exception

We found out that the step 3 was reusing the connection created at step one (from the connection pool) but it was closed on server side. This means that the sdk is set up with different values for the timeout.

Here's a reproducer

package com.redhat.cloud;

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.openshift.cloud.api.kas.auth.AclsApi;
import com.openshift.cloud.api.kas.auth.invoker.ApiClient;
import com.openshift.cloud.api.kas.auth.invoker.ApiException;
import com.openshift.cloud.api.kas.auth.invoker.Configuration;
import com.openshift.cloud.api.kas.auth.invoker.auth.OAuth;
import com.openshift.cloud.api.kas.auth.models.AclBinding;
import com.openshift.cloud.api.kas.auth.models.AclOperation;
import com.openshift.cloud.api.kas.auth.models.AclPatternType;
import com.openshift.cloud.api.kas.auth.models.AclPermissionType;
import com.openshift.cloud.api.kas.auth.models.AclResourceType;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;

public class KafkaInstanceIT {

    @Test
    public void testCreateExample() throws InterruptedException, ApiException {

        AclBinding aclBinding = new AclBinding()
                .resourceType(AclResourceType.TOPIC)
                .resourceName("ob-351b2b55-deb9-47cb-b535-35bf20ae09f1")
                .patternType(AclPatternType.LITERAL)
                .principal("User:srvc-acct-3a46e8f6-5a39-42d4-959f-857b5e0f944b")
                .operation(AclOperation.DESCRIBE)
                .permission(AclPermissionType.ALLOW);

        ApiClient defaultClient = Configuration.getDefaultApiClient();
        defaultClient.setBasePath("https://admin-server-**REDACTED**:443/rest");

        AclsApi apiInstance = new AclsApi(defaultClient);

        System.out.println("First shot");
        setToken(defaultClient, getAccessToken());
        apiInstance.createAcl(aclBinding);

        Thread.sleep(1000 * 60 * 10); // Sleep 10 minutes

        System.out.println("Second shot");
        setToken(defaultClient, getAccessToken());
        apiInstance.createAcl(aclBinding);
    }

    private void setToken(ApiClient apiClient, String token) {
        System.out.println(token);
        OAuth oauth = (OAuth) apiClient.getAuthentication("Bearer");
        oauth.setAccessToken(token);
    }

    private String getAccessToken() {
        return given().param("grant_type", "client_credentials")
                .param("client_secret", "**REDACTED**")
                .param("client_id", "**REDACTED**")
                .param("scope", "email")
                .when()
                .post("https://identity.api.openshift.com/auth/realms/rhoas/protocol/openid-connect/token")
                .as(AccessTokenResponse.class)
                .getToken();
    }

    public static class AccessTokenResponse {

        @JsonProperty("access_token")
        protected String token;
        @JsonProperty("expires_in")
        protected long expiresIn;
        @JsonProperty("refresh_expires_in")
        protected long refreshExpiresIn;
        @JsonProperty("refresh_token")
        protected String refreshToken;
        @JsonProperty("token_type")
        protected String tokenType;
        @JsonProperty("id_token")
        protected String idToken;
        @JsonProperty("not-before-policy")
        protected int notBeforePolicy;
        @JsonProperty("session_state")
        protected String sessionState;
        protected Map<String, Object> otherClaims = new HashMap<>();
        @JsonProperty("scope")
        protected String scope;
        @JsonProperty("error")
        protected String error;
        @JsonProperty("error_description")
        protected String errorDescription;
        @JsonProperty("error_uri")
        protected String errorUri;

        public AccessTokenResponse() {
        }

        public String getToken() {
            return this.token;
        }
    }
}

The execution of it leads to

javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.net.ssl.SSLException: Connection reset

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions