Fix/mnt 23878 timeouting transforms fix (#2126)

* MNT-23878: By default there was no timeout set for HttpClients, we've wrongly directed ourselfes with the values of currently existing mTLS (Solr/Elasticsearch) for Transform that used default http clients with infinite timeouts
This commit is contained in:
Marcin Strankowski
2023-08-08 14:21:13 +02:00
committed by GitHub
parent 87cab11fe2
commit 66ff28243f
3 changed files with 48 additions and 48 deletions

View File

@@ -92,15 +92,16 @@ public class HttpClient4Factory
else else
{ {
//Setting a connectionManager overrides these properties //Setting a connectionManager overrides these properties
clientBuilder.setMaxConnTotal(config.getMaxTotalConnections()); config.getMaxTotalConnections().ifPresent(v -> clientBuilder.setMaxConnTotal(v));
clientBuilder.setMaxConnPerRoute(config.getMaxHostConnections()); config.getMaxHostConnections().ifPresent(v -> clientBuilder.setMaxConnPerRoute(v));
} }
RequestConfig requestConfig = RequestConfig.custom() RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
.setConnectTimeout(config.getConnectionTimeout()) config.getConnectionTimeout().ifPresent(v -> requestConfigBuilder.setConnectTimeout(v));
.setSocketTimeout(config.getSocketTimeout()) config.getConnectionRequestTimeout().ifPresent(v -> requestConfigBuilder.setConnectionRequestTimeout(v));
.setConnectionRequestTimeout(config.getConnectionRequestTimeout()) config.getSocketTimeout().ifPresent(v -> requestConfigBuilder.setSocketTimeout(v));
.build();
RequestConfig requestConfig = requestConfigBuilder.build();
clientBuilder.setDefaultRequestConfig(requestConfig); clientBuilder.setDefaultRequestConfig(requestConfig);
@@ -135,8 +136,8 @@ public class HttpClient4Factory
.register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("http", PlainConnectionSocketFactory.getSocketFactory())
.build()); .build());
} }
poolingHttpClientConnectionManager.setMaxTotal(config.getMaxTotalConnections()); config.getMaxTotalConnections().ifPresent(v -> poolingHttpClientConnectionManager.setMaxTotal(v));
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(config.getMaxHostConnections()); config.getMaxHostConnections().ifPresent(v -> poolingHttpClientConnectionManager.setDefaultMaxPerRoute(v));
return poolingHttpClientConnectionManager; return poolingHttpClientConnectionManager;
} }

View File

@@ -85,17 +85,27 @@ public class HttpClientConfig
this.keyStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getKeyStoreParameters(), keyResourceLoader); this.keyStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getKeyStoreParameters(), keyResourceLoader);
this.trustStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getTrustStoreParameters(), keyResourceLoader); this.trustStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getTrustStoreParameters(), keyResourceLoader);
config = retrieveConfig(serviceName); config = retrieveConfig();
checkUnsupportedProperties(config); checkUnsupportedProperties(config);
} }
/** /**
* Method used for retrieving HttpClient config from Global Properties * Method used for retrieving HttpClient config from Global Properties
* @param serviceName name of used service * that can also have values provided/overridden through System Properties
*
* @return map of properties * @return map of properties
*/ */
private Map<String, String> retrieveConfig(String serviceName) private Map<String, String> retrieveConfig()
{ {
Map<String, String> resultProperties = getHttpClientPropertiesForService(properties);
Map<String, String> systemProperties = getHttpClientPropertiesForService(System.getProperties());
systemProperties.forEach((k, v) -> resultProperties.put(k, v)); //Override/Add to Global Properties results with values from System Properties
return resultProperties;
}
private Map<String, String> getHttpClientPropertiesForService(Properties properties) {
return properties.keySet().stream() return properties.keySet().stream()
.filter(key -> key instanceof String) .filter(key -> key instanceof String)
.map(Object::toString) .map(Object::toString)
@@ -112,79 +122,75 @@ public class HttpClientConfig
.forEach(propertyName -> LOGGER.warn(String.format("For service [%s], an unsupported property [%s] is set", serviceName, propertyName))); .forEach(propertyName -> LOGGER.warn(String.format("For service [%s], an unsupported property [%s] is set", serviceName, propertyName)));
} }
private Integer getIntegerProperty(HttpClientPropertiesEnum property) private Optional<Integer> getIntegerProperty(HttpClientPropertiesEnum property)
{ {
return Integer.parseInt(extractValueFromConfig(property).orElse("0")); Optional<String> optionalProperty = extractValueFromConfig(property);
return optionalProperty.isPresent() ? Optional.of(Integer.parseInt(optionalProperty.get())) : Optional.empty();
} }
private Boolean getBooleanProperty(HttpClientPropertiesEnum property) private Optional<Boolean> getBooleanProperty(HttpClientPropertiesEnum property)
{ {
return Boolean.parseBoolean(extractValueFromConfig(property).orElse("false")); Optional<String> optionalProperty = extractValueFromConfig(property);
return optionalProperty.isPresent() ? Optional.of(Boolean.parseBoolean(optionalProperty.get())) : Optional.empty();
} }
private Optional<String> extractValueFromConfig(HttpClientPropertiesEnum property) private Optional<String> extractValueFromConfig(HttpClientPropertiesEnum property)
{ {
Optional<String> optionalProperty = Optional.ofNullable(config.get(property.name)); return Optional.ofNullable(config.get(property.name));
if(property.isRequired && optionalProperty.isEmpty())
{
String msg = String.format("Required property: '%s' is empty.", property.name);
throw new HttpClientException(msg);
}
return optionalProperty;
} }
public Integer getConnectionTimeout() public Optional<Integer> getConnectionTimeout()
{ {
return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT); return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT);
} }
public Integer getSocketTimeout() public Optional<Integer> getSocketTimeout()
{ {
return getIntegerProperty(HttpClientPropertiesEnum.SOCKET_TIMEOUT); return getIntegerProperty(HttpClientPropertiesEnum.SOCKET_TIMEOUT);
} }
public Integer getConnectionRequestTimeout() public Optional<Integer> getConnectionRequestTimeout()
{ {
return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT); return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT);
} }
public Integer getMaxTotalConnections() public Optional<Integer> getMaxTotalConnections()
{ {
return getIntegerProperty(HttpClientPropertiesEnum.MAX_TOTAL_CONNECTIONS); return getIntegerProperty(HttpClientPropertiesEnum.MAX_TOTAL_CONNECTIONS);
} }
public Integer getMaxHostConnections() public Optional<Integer> getMaxHostConnections()
{ {
return getIntegerProperty(HttpClientPropertiesEnum.MAX_HOST_CONNECTIONS); return getIntegerProperty(HttpClientPropertiesEnum.MAX_HOST_CONNECTIONS);
} }
public Boolean isMTLSEnabled() public boolean isMTLSEnabled()
{ {
return getBooleanProperty(HttpClientPropertiesEnum.MTLS_ENABLED); return getBooleanProperty(HttpClientPropertiesEnum.MTLS_ENABLED).orElse(Boolean.FALSE);
} }
public boolean isHostnameVerificationDisabled() public boolean isHostnameVerificationDisabled()
{ {
return getBooleanProperty(HttpClientPropertiesEnum.HOSTNAME_VERIFICATION_DISABLED); return getBooleanProperty(HttpClientPropertiesEnum.HOSTNAME_VERIFICATION_DISABLED).orElse(Boolean.FALSE);
} }
private enum HttpClientPropertiesEnum private enum HttpClientPropertiesEnum
{ {
CONNECTION_TIMEOUT("connectionTimeout", true), CONNECTION_TIMEOUT("connectionTimeout"),
SOCKET_TIMEOUT("socketTimeout", true), SOCKET_TIMEOUT("socketTimeout"),
CONNECTION_REQUEST_TIMEOUT("connectionRequestTimeout", true), CONNECTION_REQUEST_TIMEOUT("connectionRequestTimeout"),
MAX_TOTAL_CONNECTIONS("maxTotalConnections", true), MAX_TOTAL_CONNECTIONS("maxTotalConnections"),
MAX_HOST_CONNECTIONS("maxHostConnections", true), MAX_HOST_CONNECTIONS("maxHostConnections"),
HOSTNAME_VERIFICATION_DISABLED("hostnameVerificationDisabled", false), HOSTNAME_VERIFICATION_DISABLED("hostnameVerificationDisabled"),
MTLS_ENABLED("mTLSEnabled", true); MTLS_ENABLED("mTLSEnabled");
private final String name; private final String name;
private final Boolean isRequired;
HttpClientPropertiesEnum(String propertyName, Boolean isRequired) HttpClientPropertiesEnum(String propertyName)
{ {
this.name = propertyName; this.name = propertyName;
this.isRequired = isRequired;
} }
private static final List<String> supportedProperties = new ArrayList<>(); private static final List<String> supportedProperties = new ArrayList<>();

View File

@@ -754,13 +754,6 @@ encryption.ssl.truststore.keyMetaData.location=
httpclient.config.transform.mTLSEnabled=false httpclient.config.transform.mTLSEnabled=false
httpclient.config.transform.maxTotalConnections=20 httpclient.config.transform.maxTotalConnections=20
httpclient.config.transform.maxHostConnections=20 httpclient.config.transform.maxHostConnections=20
httpclient.config.transform.socketTimeout=5000
httpclient.config.transform.connectionRequestTimeout=5000
httpclient.config.transform.connectionTimeout=5000
# Property is disabled by default for security reasons, never enable it on for production environments.
# It will stop verification of hostnames placed in certificates returned with server responses to Repository requests towards transform services
httpclient.config.transform.hostnameVerificationDisabled=false
# Re-encryptor properties # Re-encryptor properties
encryption.reencryptor.chunkSize=100 encryption.reencryptor.chunkSize=100