From 968830a2be5742775123379b16ac610740302650 Mon Sep 17 00:00:00 2001 From: Cao Manh Dat Date: Tue, 18 Jun 2019 12:49:51 +0100 Subject: [PATCH] SOLR-12988: Avoid using TLSv1.3 for HttpClient --- solr/CHANGES.txt | 2 ++ .../cloud/TestMiniSolrCloudClusterSSL.java | 2 -- .../solr/cloud/TestSSLRandomization.java | 2 -- .../client/solrj/impl/HttpClientUtil.java | 34 +++++++++++++++++-- .../client/solrj/impl/HttpClientUtilTest.java | 11 ++++++ .../org/apache/solr/util/SSLTestConfig.java | 15 +++----- 6 files changed, 50 insertions(+), 16 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index b0de7ce43ee..700ab0057b4 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -126,6 +126,8 @@ Bug Fixes CloudSolrClient to be triggered on liveNode changes. Also add Predicate equivilents for callers that don't care about liveNodes. (hossman) +* SOLR-12988: Avoid using TLSv1.3 for HttpClient (Cao Manh Dat) + Other Changes ---------------------- diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java index 29bdfaec01c..b659a1f397b 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java @@ -85,8 +85,6 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 { @Before public void before() { - assumeFalse("@AwaitsFix: SOLR-12988 - ssl issues on Java 11/12", Constants.JRE_IS_MINIMUM_JAVA11); - // undo the randomization of our super class log.info("NOTE: This Test ignores the randomized SSL & clientAuth settings selected by base class"); HttpClientUtil.resetHttpClientBuilder(); // also resets SchemaRegistryProvider diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSSLRandomization.java b/solr/core/src/test/org/apache/solr/cloud/TestSSLRandomization.java index 12411895553..e846f73bc33 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestSSLRandomization.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestSSLRandomization.java @@ -19,7 +19,6 @@ package org.apache.solr.cloud; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import org.apache.lucene.util.Constants; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.util.SSLTestConfig; import org.apache.solr.util.RandomizeSSL; @@ -44,7 +43,6 @@ public class TestSSLRandomization extends SolrCloudTestCase { @BeforeClass public static void createMiniSolrCloudCluster() throws Exception { - assumeFalse("@AwaitsFix: SOLR-12988 - ssl issues on Java 11/12", Constants.JRE_IS_MINIMUM_JAVA11); configureCluster(TestMiniSolrCloudClusterSSL.NUM_SERVERS).configure(); } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java index d415f214827..7781fd33d0a 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java @@ -19,6 +19,8 @@ package org.apache.solr.client.solrj.impl; import java.io.IOException; import java.io.InputStream; import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.CopyOnWriteArrayList; @@ -58,6 +60,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpRequestExecutor; import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.TextUtils; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.ObjectReleaseTracker; @@ -74,7 +77,8 @@ import org.slf4j.LoggerFactory; public class HttpClientUtil { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - + + public static final String[] SUPPORTED_SSL_PROTOCOLS = {"TLSv1.2", "TLSv1.1", "TLSv1", "DTLSv1.2", "DTLSv1.0"}; public static final int DEFAULT_CONNECT_TIMEOUT = 60000; public static final int DEFAULT_SO_TIMEOUT = 600000; public static final int DEFAULT_MAXCONNECTIONSPERHOST = 100000; @@ -232,7 +236,9 @@ public class HttpClientUtil { boolean sslCheckPeerName = toBooleanDefaultIfNull( toBooleanObject(System.getProperty(HttpClientUtil.SYS_PROP_CHECK_PEER_NAME)), true); if (sslCheckPeerName) { - sslConnectionSocketFactory = SSLConnectionSocketFactory.getSystemSocketFactory(); + String[] cipherSuites = split(System.getProperty("https.cipherSuites")); + sslConnectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createSystemDefault(), + getSupportedSSLProtocols(), cipherSuites, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); } else { sslConnectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createSystemDefault(), NoopHostnameVerifier.INSTANCE); @@ -243,6 +249,30 @@ public class HttpClientUtil { return builder.build(); } } + + static String[] getSupportedSSLProtocols() { + String[] protocols = split(System.getProperty("https.protocols")); + if (protocols == null) { + return SUPPORTED_SSL_PROTOCOLS; + } + List list = new ArrayList<>(Arrays.asList(protocols)); + list.remove("TLSv1.3"); + if (protocols.length == list.size()) + return protocols; + + if (list.isEmpty()) { + throw new IllegalArgumentException("TLSv1.3 is not supported yet!"); + } + + return list.toArray(new String[0]); + } + + private static String[] split(final String s) { + if (TextUtils.isBlank(s)) { + return null; + } + return s.split(" *, *"); + } /** * Creates new http client by using the provided configuration. diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpClientUtilTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpClientUtilTest.java index 381e20297c7..b5c5e3b7ca7 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpClientUtilTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpClientUtilTest.java @@ -67,6 +67,17 @@ public class HttpClientUtilTest extends SolrTestCase { assertSSLHostnameVerifier(NoopHostnameVerifier.class, HttpClientUtil.getSchemaRegisteryProvider()); } + public void testSSLConfig() { + assertArrayEquals(HttpClientUtil.SUPPORTED_SSL_PROTOCOLS, HttpClientUtil.getSupportedSSLProtocols()); + System.setProperty("https.protocols", "TLSv1.1,TLSv1.2"); + assertArrayEquals(new String[]{"TLSv1.1","TLSv1.2"}, HttpClientUtil.getSupportedSSLProtocols()); + System.setProperty("https.protocols", "TLSv1.1,TLSv1.2,TLSv1.3"); + assertArrayEquals(new String[]{"TLSv1.1","TLSv1.2"}, HttpClientUtil.getSupportedSSLProtocols()); + System.setProperty("https.protocols", "TLSv1.3"); + expectThrows(IllegalArgumentException.class, HttpClientUtil::getSupportedSSLProtocols); + System.clearProperty("https.protocols"); + } + private void assertSSLHostnameVerifier(Class expected, SchemaRegistryProvider provider) { ConnectionSocketFactory socketFactory = provider.getSchemaRegistry().lookup("https"); diff --git a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java index 48438d6de3c..1f7b3d0099a 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java +++ b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java @@ -16,6 +16,7 @@ */ package org.apache.solr.util; +import javax.net.ssl.SSLContext; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -25,8 +26,6 @@ import java.security.SecureRandomSpi; import java.security.UnrecoverableKeyException; import java.util.Random; -import javax.net.ssl.SSLContext; - import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; @@ -39,7 +38,6 @@ import org.apache.http.ssl.SSLContexts; import org.apache.solr.client.solrj.embedded.SSLConfig; import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpClientUtil.SchemaRegistryProvider; -import org.apache.solr.client.solrj.util.Constants; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.security.CertificateUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -101,12 +99,7 @@ public class SSLTestConfig { * @see HttpClientUtil#SYS_PROP_CHECK_PEER_NAME */ public SSLTestConfig(boolean useSSL, boolean clientAuth, boolean checkPeerName) { - // @AwaitsFix: SOLR-12988 - ssl issues on Java 11/12 - if (Constants.JRE_IS_MINIMUM_JAVA11) { - this.useSsl = false; - } else { - this.useSsl = useSSL; - } + this.useSsl = useSSL; this.clientAuth = clientAuth; this.checkPeerName = checkPeerName; @@ -260,7 +253,9 @@ public class SSLTestConfig { if (checkPeerName == false) { sslConnectionFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); } else { - sslConnectionFactory = new SSLConnectionSocketFactory(sslContext); + sslConnectionFactory = new SSLConnectionSocketFactory(sslContext, + HttpClientUtil.SUPPORTED_SSL_PROTOCOLS, + null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); } } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) { throw new IllegalStateException("Unable to setup https scheme for HTTPClient to test SSL.", e);