From 94ce2b584762a6f88a17a0b9624e6baea4e466c4 Mon Sep 17 00:00:00 2001 From: jaymode Date: Mon, 29 Apr 2019 12:53:02 -0600 Subject: [PATCH] Update ciphers for TLSv1.3 and JDK11 if available This commit updates the default ciphers and TLS protocols that are used when the runtime JDK supports them. New cipher support has been introduced in JDK 11 and 12 along with performance fixes for AES GCM. The ciphers are ordered with PFS ciphers being most preferred, then AEAD ciphers, and finally those with mainstream hardware support. When available stronger encryption is preferred for a given cipher. This is a backport of #41385 and #41808. There are known JDK bugs with TLSv1.3 that have been fixed in various versions. These are: 1. The JDK's bundled HttpsServer will endless loop under JDK11 and JDK 12.0 (Fixed in 12.0.1) based on the way the Apache HttpClient performs a close (half close). 2. In all versions of JDK 11 and 12, the HttpsServer will endless loop when certificates are not trusted or another handshake error occurs. An email has been sent to the openjdk security-dev list and #38646 is open to track this. 3. In JDK 11.0.2 and prior there is a race condition with session resumption that leads to handshake errors when multiple concurrent handshakes are going on between the same client and server. This bug does not appear when client authentication is in use. This is JDK-8213202, which was fixed in 11.0.3 and 12.0. 4. In JDK 11.0.2 and prior there is a bug where resumed TLS sessions do not retain peer certificate information. This is JDK-8212885. The way these issues are addressed is that the current java version is checked and used to determine the supported protocols for tests that provoke these issues. --- .../client/RestClientBuilderIntegTests.java | 37 +++++- .../settings/security-settings.asciidoc | 31 +++-- .../common/ssl/SslConfigurationLoader.java | 69 +++++++---- .../reindex/ReindexRestClientSslTests.java | 4 + .../AzureDiscoveryClusterFormationTests.java | 24 +++- .../xpack/core/XPackSettings.java | 83 +++++++++---- .../transport/ssl/certs/simple/testclient.jks | Bin 3358 -> 3893 bytes .../exporter/http/HttpExporterSslIT.java | 27 +++++ .../security/transport/nio/SSLDriver.java | 2 +- .../test/SecuritySettingsSource.java | 6 +- .../authc/pki/PkiAuthenticationTests.java | 9 +- .../security/authc/saml/SamlRealmTests.java | 25 ++++ ...stractSimpleSecurityTransportTestCase.java | 4 +- ...ServerTransportFilterIntegrationTests.java | 9 +- .../transport/ssl/EllipticCurveSSLTests.java | 5 +- .../transport/ssl/SslMultiPortTests.java | 51 ++++++-- .../xpack/ssl/SSLClientAuthTests.java | 41 ++++++- .../xpack/ssl/SSLReloadIntegTests.java | 4 + .../xpack/ssl/SSLTrustRestrictionsTests.java | 21 +++- .../ssl/certs/simple/README.asciidoc | 113 ++++++++++++++++++ .../transport/ssl/certs/simple/testclient.jks | Bin 3358 -> 3893 bytes .../transport/ssl/certs/simple/testnode.jks | Bin 7414 -> 9360 bytes .../transport/ssl/certs/simple/testnode.p12 | Bin 2654 -> 2699 bytes .../ssl/certs/simple/testnode_ec.crt | 13 ++ .../webhook/WebhookHttpsIntegrationTests.java | 27 +++++ .../watcher/common/http/HttpClientTests.java | 30 +++++ .../reindex-tests-with-security/build.gradle | 6 + 27 files changed, 553 insertions(+), 88 deletions(-) create mode 100644 x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java index 49eefc527baf1..780cc447ba8a6 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientBuilderIntegTests.java @@ -38,8 +38,10 @@ import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Paths; +import java.security.AccessController; import java.security.KeyFactory; import java.security.KeyStore; +import java.security.PrivilegedAction; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.PKCS8EncodedKeySpec; @@ -106,7 +108,7 @@ private RestClient buildRestClient() { } private static SSLContext getSslContext() throws Exception { - SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLContext sslContext = SSLContext.getInstance(getProtocol()); try (InputStream certFile = RestClientBuilderIntegTests.class.getResourceAsStream("/test.crt")) { // Build a keystore of default type programmatically since we can't use JKS keystores to // init a KeyManagerFactory in FIPS 140 JVMs. @@ -126,4 +128,37 @@ private static SSLContext getSslContext() throws Exception { } return sslContext; } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK that supports TLSv1.3 prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK. + */ + private static String getProtocol() { + String version = AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty("java.version")); + String[] components = version.split("\\."); + if (components.length > 0) { + final int major = Integer.valueOf(components[0]); + if (major < 11) { + return "TLS"; + } if (major > 12) { + return "TLS"; + } else if (major == 12 && components.length > 2) { + final int minor = Integer.valueOf(components[1]); + if (minor > 0) { + return "TLS"; + } else { + String patch = components[2]; + final int index = patch.indexOf("_"); + if (index > -1) { + patch = patch.substring(0, index); + } + + if (Integer.valueOf(patch) >= 1) { + return "TLS"; + } + } + } + } + return "TLSv1.2"; + } } diff --git a/docs/reference/settings/security-settings.asciidoc b/docs/reference/settings/security-settings.asciidoc index 426605f63d7cb..4185cce13c3ca 100644 --- a/docs/reference/settings/security-settings.asciidoc +++ b/docs/reference/settings/security-settings.asciidoc @@ -1526,13 +1526,30 @@ Controls the verification of certificates. Valid values are: The default value is `full`. `*.ssl.cipher_suites`:: -Supported cipher suites can be found in Oracle's http://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html[ -Java Cryptography Architecture documentation]. Defaults to `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256`, -`TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`, -`TLS_RSA_WITH_AES_128_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA`. If the _Java Cryptography Extension (JCE) Unlimited Strength -Jurisdiction Policy Files_ has been installed, the default value also includes `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384`, -`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`, -`TLS_RSA_WITH_AES_256_CBC_SHA256`, `TLS_RSA_WITH_AES_256_CBC_SHA`. +Supported cipher suites can be found in Oracle's +https://docs.oracle.com/en/java/javase/11/security/oracle-providers.html#GUID-7093246A-31A3-4304-AC5F-5FB6400405E2[Java + Cryptography Architecture documentation]. +Defaults to `TLS_AES_256_GCM_SHA384`, `TLS_AES_128_GCM_SHA256`, +`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`, +`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`, `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`, +`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256`, +`TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256`, +`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA`, +`TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA`, +`TLS_RSA_WITH_AES_256_GCM_SHA384`, `TLS_RSA_WITH_AES_128_GCM_SHA256`, +`TLS_RSA_WITH_AES_256_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA256`, +`TLS_RSA_WITH_AES_256_CBC_SHA`, `TLS_RSA_WITH_AES_128_CBC_SHA`. ++ +-- +NOTE: The default cipher suites list above includes TLSv1.3 ciphers and ciphers +that require the _Java Cryptography Extension (JCE) Unlimited Strength +Jurisdiction Policy Files_ for 256-bit AES encryption. If TLSv1.3 is not +available, the TLSv1.3 ciphers TLS_AES_256_GCM_SHA384`, `TLS_AES_128_GCM_SHA256` +will not be included in the default list. If 256-bit AES is unavailable, ciphers +with `AES_256` in their names wil not be included in the default list. Finally, +AES GCM has known performance issues in Java versions prior to 11 and will only +be included in the default list when using Java 11 or above. +-- [float] [[tls-ssl-key-settings]] diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java index 6e511565a9f53..e53600c251424 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfigurationLoader.java @@ -19,6 +19,8 @@ package org.elasticsearch.common.ssl; +import org.elasticsearch.bootstrap.JavaVersion; + import javax.crypto.Cipher; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; @@ -338,30 +340,53 @@ private List resolveListSetting(String key, Function parser, L } private static List loadDefaultCiphers() { - final List ciphers128 = Arrays.asList( - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA" - ); - final List ciphers256 = Arrays.asList( - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_AES_256_CBC_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA" - ); - if (has256BitAES()) { - List ciphers = new ArrayList<>(ciphers256.size() + ciphers128.size()); - ciphers.addAll(ciphers256); - ciphers.addAll(ciphers128); - return ciphers; + final boolean has256BitAES = has256BitAES(); + final boolean useGCM = JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0; + final boolean tlsV13Supported = DEFAULT_PROTOCOLS.contains("TLSv1.3"); + List ciphers = new ArrayList<>(); + if (tlsV13Supported) { // TLSv1.3 cipher has PFS, AEAD, hardware support + if (has256BitAES) { + ciphers.add("TLS_AES_256_GCM_SHA384"); + } + ciphers.add("TLS_AES_128_GCM_SHA256"); + } + if (useGCM) { // PFS, AEAD, hardware support + if (has256BitAES) { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")); + } else { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")); + } + } + + // PFS, hardware support + if (has256BitAES) { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")); + } else { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")); + } + + // AEAD, hardware support + if (useGCM) { + if (has256BitAES) { + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256")); + } else { + ciphers.add("TLS_RSA_WITH_AES_128_GCM_SHA256"); + } + } + + // hardware support + if (has256BitAES) { + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA")); } else { - return ciphers128; + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA")); } + return ciphers; } private static boolean has256BitAES() { diff --git a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ReindexRestClientSslTests.java b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ReindexRestClientSslTests.java index 7c94b94bbb1d5..a2e00e66fd218 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ReindexRestClientSslTests.java +++ b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/ReindexRestClientSslTests.java @@ -120,6 +120,7 @@ public void testClientFailsWithUntrustedCertificate() throws IOException { final List threads = new ArrayList<>(); final Settings settings = Settings.builder() .put("path.home", createTempDir()) + .put("reindex.ssl.supported_protocols", "TLSv1.2") .build(); final Environment environment = TestEnvironment.newEnvironment(settings); final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class)); @@ -134,6 +135,7 @@ public void testClientSucceedsWithCertificateAuthorities() throws IOException { final Settings settings = Settings.builder() .put("path.home", createTempDir()) .putList("reindex.ssl.certificate_authorities", ca.toString()) + .put("reindex.ssl.supported_protocols", "TLSv1.2") .build(); final Environment environment = TestEnvironment.newEnvironment(settings); final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class)); @@ -149,6 +151,7 @@ public void testClientSucceedsWithVerificationDisabled() throws IOException { final Settings settings = Settings.builder() .put("path.home", createTempDir()) .put("reindex.ssl.verification_mode", "NONE") + .put("reindex.ssl.supported_protocols", "TLSv1.2") .build(); final Environment environment = TestEnvironment.newEnvironment(settings); final ReindexSslConfig ssl = new ReindexSslConfig(settings, environment, mock(ResourceWatcherService.class)); @@ -169,6 +172,7 @@ public void testClientPassesClientCertificate() throws IOException { .put("reindex.ssl.certificate", cert) .put("reindex.ssl.key", key) .put("reindex.ssl.key_passphrase", "client-password") + .put("reindex.ssl.supported_protocols", "TLSv1.2") .build(); AtomicReference clientCertificates = new AtomicReference<>(); handler = https -> { diff --git a/plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java b/plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java index 1ee2e2490727b..8bfb373f644f2 100644 --- a/plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java +++ b/plugins/discovery-azure-classic/src/test/java/org/elasticsearch/discovery/azure/classic/AzureDiscoveryClusterFormationTests.java @@ -25,6 +25,7 @@ import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsServer; import org.apache.logging.log4j.LogManager; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.cloud.azure.classic.management.AzureComputeService; import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.io.FileSystemUtils; @@ -59,7 +60,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.security.AccessController; import java.security.KeyStore; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -262,11 +265,30 @@ private static SSLContext getSSLContext() throws Exception { kmf.init(ks, passphrase); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); - SSLContext ssl = SSLContext.getInstance("TLS"); + SSLContext ssl = SSLContext.getInstance(getProtocol()); ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return ssl; } + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static String getProtocol() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return "TLS"; + } else if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) { + return "TLSv1.2"; + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return "TLSv1.2"; + } + } + return "TLS"; + } + @AfterClass public static void stopHttpd() throws IOException { for (int i = 0; i < internalCluster().size(); i++) { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java index 0eeb173b8b84e..4f6202f2b5c13 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackSettings.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.core; import org.apache.logging.log4j.LogManager; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.xpack.core.security.SecurityField; @@ -118,6 +119,20 @@ private XPackSettings() { /** Setting for enabling or disabling sql. Defaults to true. */ public static final Setting SQL_ENABLED = Setting.boolSetting("xpack.sql.enabled", true, Setting.Property.NodeScope); + public static final List DEFAULT_SUPPORTED_PROTOCOLS; + + static { + boolean supportsTLSv13 = false; + try { + SSLContext.getInstance("TLSv1.3"); + supportsTLSv13 = true; + } catch (NoSuchAlgorithmException e) { + LogManager.getLogger(XPackSettings.class).debug("TLSv1.3 is not supported", e); + } + DEFAULT_SUPPORTED_PROTOCOLS = supportsTLSv13 ? + Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"); + } + /* * SSL settings. These are the settings that are specifically registered for SSL. Many are private as we do not explicitly use them * but instead parse based on a prefix (eg *.ssl.*) @@ -125,24 +140,58 @@ private XPackSettings() { public static final List DEFAULT_CIPHERS; static { - List ciphers = Arrays.asList("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_CBC_SHA"); + List ciphers = new ArrayList<>(); + final boolean useGCM = JavaVersion.current().compareTo(JavaVersion.parse("11")) >= 0; + final boolean tlsV13Supported = DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3"); try { final boolean use256Bit = Cipher.getMaxAllowedKeyLength("AES") > 128; + if (tlsV13Supported) { // TLSv1.3 cipher has PFS, AEAD, hardware support + if (use256Bit) { + ciphers.add("TLS_AES_256_GCM_SHA384"); + } + ciphers.add("TLS_AES_128_GCM_SHA256"); + } + if (useGCM) { // PFS, AEAD, hardware support + if (use256Bit) { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")); + } else { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")); + } + } + + // PFS, hardware support + if (use256Bit) { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")); + } else { + ciphers.addAll(Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA")); + } + + // AEAD, hardware support + if (useGCM) { + if (use256Bit) { + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256")); + } else { + ciphers.add("TLS_RSA_WITH_AES_128_GCM_SHA256"); + } + } + + // hardware support if (use256Bit) { - List strongerCiphers = new ArrayList<>(ciphers.size() * 2); - strongerCiphers.addAll(Arrays.asList("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA")); - strongerCiphers.addAll(ciphers); - ciphers = strongerCiphers; + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA")); + } else { + ciphers.addAll(Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA")); } } catch (NoSuchAlgorithmException e) { // ignore it here - there will be issues elsewhere and its not nice to throw in a static initializer } - DEFAULT_CIPHERS = ciphers; + DEFAULT_CIPHERS = Collections.unmodifiableList(ciphers); } /* @@ -164,20 +213,6 @@ private XPackSettings() { } }, Setting.Property.NodeScope); - public static final List DEFAULT_SUPPORTED_PROTOCOLS; - - static { - boolean supportsTLSv13 = false; - try { - SSLContext.getInstance("TLSv1.3"); - supportsTLSv13 = true; - } catch (NoSuchAlgorithmException e) { - LogManager.getLogger(XPackSettings.class).debug("TLSv1.3 is not supported", e); - } - DEFAULT_SUPPORTED_PROTOCOLS = supportsTLSv13 ? - Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1"); - } - public static final SSLClientAuth CLIENT_AUTH_DEFAULT = SSLClientAuth.REQUIRED; public static final SSLClientAuth HTTP_CLIENT_AUTH_DEFAULT = SSLClientAuth.NONE; public static final VerificationMode VERIFICATION_MODE_DEFAULT = VerificationMode.FULL; diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks index d6dc21c1bd5ff4a248bfba5a171518cd649e278d..4f897d80f4af494c8fffc0acab1cc1365fe28353 100644 GIT binary patch delta 375 zcmbOywN;Mi-`jt085kItfS7qB&p#e_Fo(M&wYVfNKP5FjHJO2dF)J%guato`LeJE| z63G2*(8Ty2h$k;#W@2PwVkyc{ur}af{g@iKQ3k4>IoV_Ez>XMNQ!yR}OW zR4#7ZV$itJK$eX;RF;oLj77wkA$j+^R7L3}6ZW)T@ZA+7&KZAmat{0CY!ufsdoUQd zGAX1N>6fKh>V!uhYYp1GD)iQ+%Afw`cQo=YKP$HD`>hztq{wjbcwlJP)x0xOS%*ZX t{hXD(J;mED(&^DTMh-4FK6#~Uvvt=vNToT>FF1T~kF;@=kk getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } else if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) { + return Collections.singletonList("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SSLDriver.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SSLDriver.java index e54bc9fa16e57..c5dcb260919b3 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SSLDriver.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SSLDriver.java @@ -438,7 +438,7 @@ public void read(InboundChannelBuffer encryptedBuffer, InboundChannelBuffer appl SSLEngineResult result = unwrap(encryptedBuffer, applicationBuffer); boolean renegotiationRequested = result.getStatus() != SSLEngineResult.Status.CLOSED && maybeRenegotiation(result.getHandshakeStatus()); - continueUnwrap = result.bytesProduced() > 0 && renegotiationRequested == false; + continueUnwrap = result.bytesConsumed() > 0 && renegotiationRequested == false; } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecuritySettingsSource.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecuritySettingsSource.java index a8ad2fbd4aad3..491fd66c4530b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecuritySettingsSource.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecuritySettingsSource.java @@ -218,7 +218,8 @@ public static void addSSLSettingsForNodePEMFiles(Settings.Builder builder, Strin "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/active-directory-ca.crt", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/openldap.crt", - "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt"), hostnameVerificationEnabled, false); } @@ -244,7 +245,8 @@ public void addClientSSLSettings(Settings.Builder builder, String prefix) { "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.pem", "testclient", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt", Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", - "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt"), + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt"), hostnameVerificationEnabled, true); } else { addSSLSettingsForStore(builder, prefix, "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks", diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthenticationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthenticationTests.java index 52c87c75a13a7..03d107a50a864 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthenticationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiAuthenticationTests.java @@ -66,8 +66,9 @@ protected Settings nodeSettings() { .put("xpack.security.http.ssl.client_authentication", sslClientAuth) .put("xpack.security.authc.realms.file.file.order", "0") .put("xpack.security.authc.realms.pki.pki1.order", "1") - .put("xpack.security.authc.realms.pki.pki1.certificate_authorities", - getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .putList("xpack.security.authc.realms.pki.pki1.certificate_authorities", + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt").toString(), + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt").toString()) .put("xpack.security.authc.realms.pki.pki1.files.role_mapping", getDataPath("role_mapping.yml")); return builder.build(); } @@ -91,8 +92,8 @@ public void testTransportClientCanAuthenticateViaPki() { "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem", "testnode", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", - Arrays.asList - ("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); try (TransportClient client = createTransportClient(builder.build())) { client.addTransportAddress(randomFrom(node().injector().getInstance(Transport.class).boundAddress().boundAddresses())); IndexResponse response = client.prepareIndex("foo", "bar").setSource("pki", "auth").get(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java index d139d99bf9ce2..aea50691119a2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java @@ -5,9 +5,11 @@ */ package org.elasticsearch.xpack.security.authc.saml; +import com.sun.net.httpserver.HttpsServer; import org.apache.logging.log4j.message.ParameterizedMessage; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.MockSecureSettings; import org.elasticsearch.common.settings.Settings; @@ -19,6 +21,7 @@ import org.elasticsearch.test.http.MockResponse; import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.watcher.ResourceWatcherService; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; import org.elasticsearch.xpack.core.security.authc.Realm; import org.elasticsearch.xpack.core.security.authc.RealmConfig; @@ -52,8 +55,10 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.security.AccessController; import java.security.KeyStore; import java.security.PrivateKey; +import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PublicKey; import java.security.cert.Certificate; @@ -131,6 +136,7 @@ public void testReadIdpMetadataFromHttps() throws Exception { getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) .put("xpack.security.http.ssl.certificate_authorities", getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .putList("xpack.security.http.ssl.supported_protocols", getProtocols()) .put("path.home", createTempDir()) .setSecureSettings(mockSecureSettings) .build(); @@ -715,4 +721,23 @@ private void assertIdp1MetadataParsedCorrectly(EntityDescriptor descriptor) { assertEquals(SAMLConstants.SAML2_POST_BINDING_URI, ssoServices.get(0).getBinding()); assertEquals(SAMLConstants.SAML2_REDIRECT_BINDING_URI, ssoServices.get(1).getBinding()); } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static List getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } else if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) { + return Collections.singletonList("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java index ca548251d3713..1b7a7f8d870f2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java @@ -155,7 +155,9 @@ public void testTcpHandshake() { @SuppressForbidden(reason = "Need to open socket connection") public void testRenegotiation() throws Exception { - SSLService sslService = createSSLService(); + // force TLSv1.2 since renegotiation is not supported by 1.3 + SSLService sslService = + createSSLService(Settings.builder().put("xpack.security.transport.ssl.supported_protocols", "TLSv1.2").build()); final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); SocketFactory factory = sslService.sslSocketFactory(sslConfiguration); try (SSLSocket socket = (SSLSocket) factory.createSocket()) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterIntegrationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterIntegrationTests.java index f8bf1f47a38f1..e3f561c47119b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterIntegrationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ServerTransportFilterIntegrationTests.java @@ -19,7 +19,6 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.MockHttpTransport; import org.elasticsearch.test.SecurityIntegTestCase; -import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.test.SecuritySettingsSourceField; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.ConnectionProfile; @@ -80,8 +79,6 @@ protected Settings nodeSettings(int nodeOrdinal) { settingsBuilder.put("transport.profiles.default.xpack.security.type", "node"); // this is default lets set it randomly } - SecuritySettingsSource.addSecureSettings(settingsBuilder, secureSettings -> - secureSettings.setString("transport.profiles.client.xpack.security.ssl.keystore.secure_password", "testnode")); return settingsBuilder.build(); } @@ -112,7 +109,8 @@ public void testThatConnectionToServerTypeConnectionWorks() throws IOException, "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem", "testnode", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", - Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); try (Node node = new MockNode(nodeSettings.build(), mockPlugins)) { node.start(); ensureStableCluster(cluster().size() + 1); @@ -151,7 +149,8 @@ public void testThatConnectionToClientTypeConnectionIsRejected() throws IOExcept "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem", "testnode", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", - Collections.singletonList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); try (Node node = new MockNode(nodeSettings.build(), mockPlugins)) { node.start(); TransportService instance = node.injector().getInstance(TransportService.class); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java index 5f0f3c94e36e8..761726c5f670f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/EllipticCurveSSLTests.java @@ -33,7 +33,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; +import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; public class EllipticCurveSSLTests extends SecurityIntegTestCase { @@ -106,7 +108,8 @@ public SSLSocket run() throws Exception { Certificate[] peerChain = session.getPeerCertificates(); assertEquals(1, peerChain.length); assertEquals(certs[0], peerChain[0]); - assertThat(session.getCipherSuite(), containsString("ECDSA")); + assertThat(session.getCipherSuite(), + anyOf(containsString("ECDSA"), equalTo("TLS_AES_256_GCM_SHA384"), equalTo("TLS_AES_128_GCM_SHA256"))); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslMultiPortTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslMultiPortTests.java index 04c1ff03f8270..f12304bd88532 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslMultiPortTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslMultiPortTests.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.xpack.security.transport.ssl; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.client.transport.NoNodeAvailableException; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.network.NetworkAddress; @@ -13,6 +14,7 @@ import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.core.TestXPackTransportClient; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.security.SecurityField; import org.elasticsearch.xpack.core.ssl.SSLClientAuth; import org.elasticsearch.xpack.security.LocalStateSecurity; @@ -21,8 +23,11 @@ import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; +import java.util.List; import static org.elasticsearch.test.SecuritySettingsSource.TEST_USER_NAME; import static org.elasticsearch.test.SecuritySettingsSource.addSSLSettingsForNodePEMFiles; @@ -116,6 +121,7 @@ public void testThatStandardTransportClientCanConnectToNoClientAuthProfile() thr try(TransportClient transportClient = new TestXPackTransportClient(Settings.builder() .put(transportClientSettings()) .put("xpack.security.transport.ssl.enabled", true) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) .put("node.name", "programmatic_transport_client") .put("cluster.name", internalCluster().getClusterName()) .build(), LocalStateSecurity.class)) { @@ -154,7 +160,8 @@ public void testThatProfileTransportClientCanConnectToClientProfile() throws Exc "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.pem", "testclient-client-profile", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.crt", - Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); try (TransportClient transportClient = createTransportClient(builder.build())) { transportClient.addTransportAddress(new TransportAddress(localAddress, getProfilePort("client"))); assertGreenClusterState(transportClient); @@ -174,7 +181,9 @@ public void testThatProfileTransportClientCanConnectToNoClientAuthProfile() thro "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.pem", "testclient-client-profile", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.crt", - Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); + builder.putList("xpack.security.transport.ssl.supported_protocols", getProtocols()); try (TransportClient transportClient = createTransportClient(builder.build())) { transportClient.addTransportAddress(new TransportAddress(localAddress, getProfilePort("no_client_auth"))); @@ -195,7 +204,8 @@ public void testThatProfileTransportClientCannotConnectToDefaultProfile() throws "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.pem", "testclient-client-profile", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.crt", - Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")); + Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt")); try (TransportClient transportClient = createTransportClient(builder.build())) { TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()); transportClient.addTransportAddress(transportAddress); @@ -273,8 +283,10 @@ public void testThatTransportClientWithOnlyTruststoreCanConnectToNoClientAuthPro .put(SecurityField.USER_SETTING.getKey(), TEST_USER_NAME + ":" + TEST_PASSWORD) .put("cluster.name", internalCluster().getClusterName()) .put("xpack.security.transport.ssl.enabled", true) - .put("xpack.security.transport.ssl.certificate_authorities", - getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .putList("xpack.security.transport.ssl.certificate_authorities", + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt").toString(), + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt").toString()) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) .build(); try (TransportClient transportClient = new TestXPackTransportClient(settings, Collections.singletonList(LocalStateSecurity.class))) { @@ -294,8 +306,10 @@ public void testThatTransportClientWithOnlyTruststoreCannotConnectToClientProfil .put("cluster.name", internalCluster().getClusterName()) .put("xpack.security.transport.ssl.enabled", true) .put("xpack.security.transport.ssl.client_authentication", SSLClientAuth.REQUIRED) - .put("xpack.security.transport.ssl.certificate_authorities", - getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .putList("xpack.security.transport.ssl.certificate_authorities", + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt").toString(), + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt").toString()) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) .build(); try (TransportClient transportClient = new TestXPackTransportClient(settings, Collections.singletonList(LocalStateSecurity.class))) { @@ -318,8 +332,10 @@ public void testThatTransportClientWithOnlyTruststoreCannotConnectToDefaultProfi .put("cluster.name", internalCluster().getClusterName()) .put("xpack.security.transport.ssl.enabled", true) .put("xpack.security.transport.ssl.client_authentication", SSLClientAuth.REQUIRED) - .put("xpack.security.transport.ssl.certificate_authorities", - getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt")) + .putList("xpack.security.transport.ssl.certificate_authorities", + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt").toString(), + getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt").toString()) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) .build(); try (TransportClient transportClient = new TestXPackTransportClient(settings, Collections.singletonList(LocalStateSecurity.class))) { @@ -409,4 +425,21 @@ private static int getProfilePort(String profile) { throw new IllegalStateException("failed to find transport address equal to [" + NetworkAddress.format(localAddress) + "] " + " in the following bound addresses " + Arrays.toString(transportAddresses)); } + + /** + * TLSv1.3 when running in a JDK prior to 11.0.3 has a race condition when multiple simultaneous connections are established. See + * JDK-8213202. This issue is not triggered when using client authentication, which we do by default for transport connections. + * However if client authentication is turned off and TLSv1.3 is used on the affected JVMs then we will hit this issue. + */ + private static List getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java index 7075a677a26ce..85f18ddff922c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLClientAuthTests.java @@ -11,6 +11,7 @@ import org.apache.http.util.EntityUtils; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.client.Request; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; @@ -23,6 +24,7 @@ import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.core.TestXPackTransportClient; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.security.SecurityField; import org.elasticsearch.xpack.core.ssl.CertParsingUtils; import org.elasticsearch.xpack.core.ssl.PemUtils; @@ -38,11 +40,14 @@ import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.security.SecureRandom; import java.security.cert.CertPathBuilderException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.hamcrest.Matchers.containsString; @@ -101,7 +106,7 @@ protected boolean transportSSLEnabled() { return true; } - public void testThatHttpFailsWithoutSslClientAuth() throws IOException { + public void testThatHttpFailsWithoutSslClientAuth() { SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(SSLContexts.createDefault(), NoopHostnameVerifier.INSTANCE); try (RestClient restClient = createRestClient(httpClientBuilder -> httpClientBuilder.setSSLStrategy(sessionStrategy), "https")) { restClient.performRequest(new Request("GET", "/")); @@ -130,11 +135,12 @@ public void testThatHttpWorksWithSslClientAuth() throws IOException { } } - public void testThatTransportWorksWithoutSslClientAuth() throws IOException { + public void testThatTransportWorksWithoutSslClientAuth() { // specify an arbitrary key and certificate - not the certs needed to connect to the transport protocol Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.pem"); Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient-client-profile.crt"); Path nodeCertPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"); + Path nodeECCertPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt"); if (Files.notExists(keyPath) || Files.notExists(certPath)) { throw new ElasticsearchException("key or certificate path doesn't exist"); @@ -147,7 +153,8 @@ public void testThatTransportWorksWithoutSslClientAuth() throws IOException { .put("xpack.security.transport.ssl.client_authentication", SSLClientAuth.NONE) .put("xpack.security.transport.ssl.key", keyPath) .put("xpack.security.transport.ssl.certificate", certPath) - .put("xpack.security.transport.ssl.certificate_authorities", nodeCertPath) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) + .putList("xpack.security.transport.ssl.certificate_authorities", nodeCertPath.toString(), nodeECCertPath.toString()) .setSecureSettings(secureSettings) .put("cluster.name", internalCluster().getClusterName()) .put(SecurityField.USER_SETTING.getKey(), transportClientUsername() + ":" + new String(transportClientPassword().getChars())) @@ -165,12 +172,19 @@ private SSLContext getSSLContext() { try { String certPath = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt"; String nodeCertPath = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"; + String nodeEcCertPath = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt"; String keyPath = "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.pem"; TrustManager tm = CertParsingUtils.trustManager(CertParsingUtils.readCertificates(Arrays.asList(getDataPath - (certPath), getDataPath(nodeCertPath)))); + (certPath), getDataPath(nodeCertPath), getDataPath(nodeEcCertPath)))); KeyManager km = CertParsingUtils.keyManager(CertParsingUtils.readCertificates(Collections.singletonList(getDataPath (certPath))), PemUtils.readPrivateKey(getDataPath(keyPath), "testclient"::toCharArray), "testclient".toCharArray()); - SSLContext context = SSLContext.getInstance("TLSv1.2"); + + final SSLContext context; + if (XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3")) { + context = SSLContext.getInstance(randomBoolean() ? "TLSv1.3" : "TLSv1.2"); + } else { + context = SSLContext.getInstance("TLSv1.2"); + } context.init(new KeyManager[] { km }, new TrustManager[] { tm }, new SecureRandom()); return context; } catch (Exception e) { @@ -188,4 +202,21 @@ private byte[] toByteArray(InputStream is) throws IOException { } return baos.toByteArray(); } + + /** + * TLSv1.3 when running in a JDK prior to 11.0.3 has a race condition when multiple simultaneous connections are established. See + * JDK-8213202. This issue is not triggered when using client authentication, which we do by default for transport connections. + * However if client authentication is turned off and TLSv1.3 is used on the affected JVMs then we will hit this issue. + */ + private static List getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java index dd6985889d7ee..3eeaca1a3f114 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java @@ -115,6 +115,10 @@ public void testThatSSLConfigurationReloadsOnModification() throws Exception { try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) { assertThat(socket.isConnected(), is(true)); socket.startHandshake(); + if (socket.getSession().getProtocol().equals("TLSv1.3")) { + // blocking read for TLSv1.3 to see if the other side closed the connection + socket.getInputStream().read(); + } fail("handshake should not have been successful!"); } catch (SSLException | SocketException expected) { logger.trace("expected exception", expected); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java index a89b8fcdd6981..944c3306763a6 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java @@ -31,6 +31,7 @@ import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.net.SocketException; +import java.net.SocketTimeoutException; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.Files; import java.nio.file.Path; @@ -165,7 +166,7 @@ protected boolean transportSSLEnabled() { public void testCertificateWithTrustedNameIsAccepted() throws Exception { writeRestrictions("*.trusted"); try { - tryConnect(trustedCert); + tryConnect(trustedCert, false); } catch (SSLException | SocketException ex) { logger.warn(new ParameterizedMessage("unexpected handshake failure with certificate [{}] [{}]", trustedCert.certificate.getSubjectDN(), trustedCert.certificate.getSubjectAlternativeNames()), ex); @@ -176,7 +177,7 @@ public void testCertificateWithTrustedNameIsAccepted() throws Exception { public void testCertificateWithUntrustedNameFails() throws Exception { writeRestrictions("*.trusted"); try { - tryConnect(untrustedCert); + tryConnect(untrustedCert, true); fail("handshake should have failed, but was successful"); } catch (SSLException | SocketException ex) { // expected @@ -187,7 +188,7 @@ public void testRestrictionsAreReloaded() throws Exception { writeRestrictions("*"); assertBusy(() -> { try { - tryConnect(untrustedCert); + tryConnect(untrustedCert, false); } catch (SSLException | SocketException ex) { fail("handshake should have been successful, but failed with " + ex); } @@ -196,7 +197,7 @@ public void testRestrictionsAreReloaded() throws Exception { writeRestrictions("*.trusted"); assertBusy(() -> { try { - tryConnect(untrustedCert); + tryConnect(untrustedCert, true); fail("handshake should have failed, but was successful"); } catch (SSLException | SocketException ex) { // expected @@ -221,7 +222,7 @@ private void runResourceWatcher() { } } - private void tryConnect(CertificateInfo certificate) throws Exception { + private void tryConnect(CertificateInfo certificate, boolean shouldFail) throws Exception { Settings settings = Settings.builder() .put("path.home", createTempDir()) .put("xpack.security.transport.ssl.key", certificate.getKeyPath()) @@ -239,6 +240,16 @@ private void tryConnect(CertificateInfo certificate) throws Exception { assertThat(socket.isConnected(), is(true)); // The test simply relies on this (synchronously) connecting (or not), so we don't need a handshake handler socket.startHandshake(); + + // blocking read for TLSv1.3 to see if the other side closed the connection + if (socket.getSession().getProtocol().equals("TLSv1.3")) { + if (shouldFail) { + socket.getInputStream().read(); + } else { + socket.setSoTimeout(1000); // 1 second timeout + expectThrows(SocketTimeoutException.class, () -> socket.getInputStream().read()); + } + } } } diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc index 5b2a6b737d779..0136e967106e1 100644 --- a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc +++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/README.asciidoc @@ -34,3 +34,116 @@ keytool -importkeystore -destkeystore .jks -srckeystore .p12 -srcsto The keystore is now created and has the private/public key pair. You can import additional trusted certificates using `keytool -importcert`. When doing so make sure to specify an alias so that others can recreate the keystore if necessary. + +=== Changes and additions for removing Bouncy Castle Dependency + +`testnode-unprotected.pem` is simply the decrypted `testnode.pem` +------ +openssl rsa -in testnode.pem -out testnode-unprotected.pem +------ + +`rsa_key_pkcs8_plain.pem` is the same plaintext key encoded in `PKCS#8` +------ +openssl pkcs8 -topk8 -inform PEM -outform PEM -in testnode-unprotected.pem -out rsa_key_pkcs8_plain.pem -nocrypt +------ + +`testnode-aes{128,192,256}.pem` is the testnode.pem private key, encrypted with `AES-128`, `AES-192` and `AES-256` +respectively, encoded in `PKCS#1` +[source,shell] +------ +openssl rsa -aes128 -in testnode-unprotected.pem -out testnode-aes128.pem +------ +[source,shell] +------ +openssl rsa -aes192 -in testnode-unprotected.pem -out testnode-aes192.pem +------ +[source,shell] +------ +openssl rsa -aes256 -in testnode-unprotected.pem -out testnode-aes256.pem +------ + +Adding `DSA` and `EC` Keys to the Keystore + +[source,shell] +------ +keytool -genkeypair -keyalg DSA -alias testnode_dsa -keystore testnode.jks -storepass testnode \ + -keypass testnode -validity 10000 -keysize 1024 -dname "CN=Elasticsearch Test Node" \ + -ext SAN=dns:localhost,dns:localhost.localdomain,dns:localhost4,dns:localhost4.localdomain4,dns:localhost6,dns:localhost6.localdomain6,ip:127.0.0.1,ip:0:0:0:0:0:0:0:1 +------ +[source,shell] +------ +keytool -genkeypair -keyalg EC -alias testnode_ec -keystore testnode.jks -storepass testnode \ + -keypass testnode -validity 10000 -keysize 256 -dname "CN=Elasticsearch Test Node" \ + -ext SAN=dns:localhost,dns:localhost.localdomain,dns:localhost4,dns:localhost4.localdomain4,dns:localhost6,dns:localhost6.localdomain6,ip:127.0.0.1,ip:0:0:0:0:0:0:0:1 +------ + +Exporting the `DSA` and `EC` private keys from the keystore + +[source,shell] +---- +keytool -importkeystore -srckeystore testnode.jks -destkeystore dsa.p12 -deststoretype PKCS12 \ + -srcalias testnode_dsa -deststorepass testnode -destkeypass testnode +---- +[source,shell] +---- +openssl pkcs12 -in dsa.p12 -nodes -nocerts | openssl pkcs8 -topk8 -nocrypt -outform pem \ + -out dsa_key_pkcs8_plain.pem +---- +[source,shell] +---- +keytool -importkeystore -srckeystore testnode.jks -destkeystore ec.p12 -deststoretype PKCS12 \ + -srcalias testnode_ec -deststorepass testnode -destkeypass testnode +---- +[source,shell] +---- +openssl pkcs12 -in ec.p12 -nodes -nocerts | openssl pkcs8 -topk8 -nocrypt -outform pem \ + -out ec_key_pkcs8_plain.pem +---- + + + +Create `PKCS#8` encrypted key from the encrypted `PKCS#1` encoded `testnode.pem` +[source,shell] +----- +openssl pkcs8 -topk8 -inform PEM -outform PEM -in testnode.pem -out key_pkcs8_encrypted.pem +----- +[source,shell] +----- +ssh-keygen -t ed25519 -f key_unsupported.pem +----- + + +Convert `prime256v1-key-noparam.pem` to `PKCS#8` format +----- +openssl pkcs8 -topk8 -in prime256v1-key-noparam.pem -nocrypt -out prime256v1-key-noparam-pkcs8.pem +----- + +Generate the keys and self-signed certificates in `nodes/self/` : + +------ +openssl req -newkey rsa:2048 -keyout n1.c1.key -x509 -days 3650 -subj "/CN=n1.c1" -reqexts SAN \ + -extensions SAN -config <(cat /etc/ssl/openssl.cnf \ + <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node1.cluster1")) -out n1.c1.crt +------ + + +Create a `CA` keypair for testing +[source,shell] +----- +openssl req -newkey rsa:2048 -nodes -keyout ca.key -x509 -subj "/CN=certAuth" -days 10000 -out ca.crt +----- + +Generate Certificates signed with our CA for testing +[source,shell] +------ + openssl req -new -newkey rsa:2048 -keyout n2.c2.key -reqexts SAN -extensions SAN \ + -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node2.cluster2"))\ + -out n2.c2.csr +------ + +[source,shell] +------ +openssl x509 -req -in n2.c2.csr -extensions SAN -CA ca.crt -CAkey ca.key -CAcreateserial \ + -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=otherName.1:2.5.4.3;UTF8:node2.cluster2"))\ + -out n2.c2.crt -days 10000 +------ diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks index d6dc21c1bd5ff4a248bfba5a171518cd649e278d..495d43d69eb112dafb4c0067f8586b7da33f6d75 100644 GIT binary patch delta 375 zcmbOywN;Mi-`jt085kItfS7qB&p#e_Fo(M&wYVfNKP5FjHJO2dF)J%Y7nTeIbKxy(DPGv0;$`k69-BPF#kH6L-Ou-sfyA|ChTdw;JYhEoHPFB?`Y&*epYPP_ggWPNs-~=@xaiot9fUnvJQz% u`#CFndy2PRq|>8wj2v8UeDX@y>U3^?irYSK%A>pUG?gpcyTZS{@&*7CTZ7jC delta 42 wcmdlgH&2S^-`jt085kItKzJk1KOPZ7xA^DtD-_@6?)fvvVUENMk3DX20A3^!Bme*a diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks index 832a23d2dbf09ef4571049b617623200af3dd86d..ebe6146124e8fd607e46a1a3129bdf9b4de0370d 100644 GIT binary patch delta 2897 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 AEC2ui diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12 b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12 index 2ac8125b58d3113e25351f95999241ae2d4ef031..0e6bcaa4f8b7685d7f5b99df290a52949500367c 100644 GIT binary patch literal 2699 zcmY+EcRUn~AIHxvxg!ZDdnQ5-@f_K^jLyjF%3eh{GeRBCx{iku*?VT3QF0lF=%lQ; z&bU;PE##==@%z1gzvp>9e|*>H`}uzVd?RtNL?8AJl$c_2 zOs_(AcG)+k^y8jh>BG51{h)vU1VFvNWaR%(b%#g|>xYrGgpK)hsH zCt{3cF4Tu9dA@#Bh0t$}=mWoVCe(i*`dJb7Hz&E=p2SMdSDr8(BZ-5oZQ8e2V&hiQ5&_I+j`a=T08Q*Re8 z@!UG_@%dJqRaY@6WlZfEb-c2%p&@wA)yaKaCZ1r_FFC2y(4&8z!gFm(;d*c`%}MO* z-0QR-ujLkLiM3a?jy8V7>i>~b; zG>v$X&;bmA40q>l-Q+C2Rqh+8>D0g$uT1U{jtm${qpl(s@7N2EE{MxScYZwML^=C| z#}+2{r8r_J`tndT?|J*k1ws_DCR?rGl5$E&TUCJ%4bZf4JHCb0(Is2NHeVCfZ!_D9 z_hn(vw?FN`J^tkcKn`H-5TUQgZ(`sg{h4)hXTSTqBzZBUfuwP7tlb}U4rWf^=_53v zNrDs`a|QNu&t7Og@{+Bv4@`V7(!AO3Zu6i9dq1DNLK7V}^tI+PLQGBM33@}OIfP3U zkY!lvdFdTZ$ZXLmbb9+}Xv`I-Koe@Nd1AWWh0MLVwwAheIdj$mBJ$NVyuPQeNZtoi z^x9%M`1Gi2Z}4n8DcdUM_y|7pbFW+HKHlu=xE1*gd2`fK`vvP;f;WdcQ(it{Hg*wl zAJTLWM(!zGEc7&{^>UslCK-!3jv`m+Yjh1~^}gOd;_!%(aG>lO9FKNsK9(}2Wgg@m zFuN|S+c4HW{rqu*HK-(d%k^$V<6U<%HJ1g9vNIqd^kXkMXwOIEW|rmXm8b}t2W9cp zx?zHX$YYbZXvZ^tp?bdbUExS$HSCg`vkkt_j#&&dW2CGi6s*^Bgr(r<8QXxq-Nb%b z2h4FjHxKhgO*cY{n$z2R{A<%1?@)jXYSV-w=dM+(TGj0<+Y6hv1^e@lio>JZH-S=DrzWY zbrtnLjzC)Xw}};c#Mb;HDF?^`I4T+cY*_w9Tj+miyMlr*D`&Dfc^P{(?~WdDL-%2~Jg zoVceNZ(d&!(jLVVnuzCeLt$OxTp~sOyYB=x)F1k#FC|=ZZfSa1MpH&$)+F+<-VAfc zT-L1{VHNBj&mNBdR6aDgNoFJP{;wg&99h$6bP}?hy1p=gJ#-#3PwJ==fG1h} zxVO+r_i~7yzQ_1+z$u@|&_uPWPSTX~V5fHwajw!GP$tu>1O3W;Ds)tjz*~Q4F}$M% zSB>mmOCLy`&zMVTs_JY|YxD}g_N>1MF;6cB!l~shQ7wDlrdz+F$8KJ=k8i3xC-il% zjBn3U|Nex~48Or73KepF1W`wCk94~Y6X|6RTXRn#SGV4i4XglR%=7~&8oDrD zE1G|(&*Ga}8Sp@7OKi+&fc1&7RDDf*NPbvJ$EnvNz(RrqkV$+h=U%jtxnnr-Y>7Hqx0N^gM|gX+ zc1vR`s5ML4htZ|=6ah}qwdW&N>3W+&C(D_w{`Du%UFAg@Pd~Q% znR3ct@UsD}uq)@oGUVYYey9>>*(DA6x;Zn|>n;SoJi>v`IPDtLmzQA13pO}q#JD7o zuSHXR`zdH{k%KF;ni}xIFd*#h3F)zmZS!vZBwJT6$Bq}O1T|TGNc1K)iqIphB+yqj%};ywFHUgj%xf*n&uc1fXow^90K@8mRTYL| zIrnNnKChAr)jnI)8kx<65@sU!C0+>W*AIW~NRM^KFRy%5H1-U4zf2#=)TiY2UXmBQ zA$A=6j?+%}q^G7f*z!xcRL2d$7u!P3SCHCBaU>fQB6l1F6o3H0JcWT7PnvxAQJh;Z o(V~Hq)$ literal 2654 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 D&}!D= diff --git a/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt new file mode 100644 index 0000000000000..f4c9a6a7aaca8 --- /dev/null +++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB7zCCAZOgAwIBAgIEcmggOzAMBggqhkjOPQQDAgUAMCIxIDAeBgNVBAMTF0Vs +YXN0aWNzZWFyY2ggVGVzdCBOb2RlMB4XDTE4MDUxNzA5MzYxMFoXDTQ1MTAwMjA5 +MzYxMFowIjEgMB4GA1UEAxMXRWxhc3RpY3NlYXJjaCBUZXN0IE5vZGUwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAATuZRlXGn/ROcO7yFJJ50b20YvgV3U+FpRx0nx/ +yigWj6xiEMKnWbbUnM0mKF8c3GHGk5g8OXPnbK96uj6tpMB5o4G0MIGxMB0GA1Ud +DgQWBBRNAGO77mUhG6SQvIXQTbpcFwlf2TCBjwYDVR0RBIGHMIGEgglsb2NhbGhv +c3SCFWxvY2FsaG9zdC5sb2NhbGRvbWFpboIKbG9jYWxob3N0NIIXbG9jYWxob3N0 +NC5sb2NhbGRvbWFpbjSCCmxvY2FsaG9zdDaCF2xvY2FsaG9zdDYubG9jYWxkb21h +aW42hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMAwGCCqGSM49BAMCBQADSAAwRQIg +Z3IvdmY5LFdbxoVSs6pV2tJ5+U833Chu0+ZzPo77IVUCIQDRx1FVitVuzBpqwhSW ++Zprt2RLPllC4s4BCApGDh8i1g== +-----END CERTIFICATE----- diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java index bdaa2377fd1d7..d93657acdc094 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/webhook/WebhookHttpsIntegrationTests.java @@ -5,12 +5,15 @@ */ package org.elasticsearch.xpack.watcher.actions.webhook; +import com.sun.net.httpserver.HttpsServer; import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.test.http.MockResponse; import org.elasticsearch.test.http.MockWebServer; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.TestsSSLService; import org.elasticsearch.xpack.core.watcher.history.WatchRecord; import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource; @@ -26,6 +29,10 @@ import org.junit.Before; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; @@ -51,6 +58,7 @@ protected Settings nodeSettings(int nodeOrdinal) { .put("xpack.http.ssl.key", keyPath) .put("xpack.http.ssl.certificate", certPath) .put("xpack.http.ssl.keystore.password", "testnode") + .putList("xpack.http.ssl.supported_protocols", getProtocols()) .build(); } @@ -131,4 +139,23 @@ public void testHttpsAndBasicAuth() throws Exception { assertThat(webServer.requests().get(0).getBody(), equalTo("{key=value}")); assertThat(webServer.requests().get(0).getHeader("Authorization"), equalTo("Basic X3VzZXJuYW1lOl9wYXNzd29yZA==")); } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static List getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } else if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) { + return Collections.singletonList("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java index 6bb607d6805a3..3ae96499b6a5a 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.watcher.common.http; import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import com.sun.net.httpserver.HttpsServer; import org.apache.http.HttpHeaders; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; @@ -13,6 +14,7 @@ import org.apache.logging.log4j.util.Supplier; import org.apache.lucene.util.automaton.CharacterRunAutomaton; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.MockSecureSettings; @@ -28,6 +30,7 @@ import org.elasticsearch.test.http.MockResponse; import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.core.ssl.TestsSSLService; import org.elasticsearch.xpack.core.ssl.VerificationMode; @@ -44,9 +47,12 @@ import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -190,6 +196,7 @@ public void testHttps() throws Exception { Settings settings2 = Settings.builder() .put("xpack.security.http.ssl.key", keyPath) .put("xpack.security.http.ssl.certificate", certPath) + .putList("xpack.security.http.ssl.supported_protocols", getProtocols()) .setSecureSettings(secureSettings) .build(); @@ -218,6 +225,7 @@ public void testHttpsDisableHostnameVerification() throws Exception { Settings settings2 = Settings.builder() .put("xpack.security.http.ssl.key", keyPath) .put("xpack.security.http.ssl.certificate", certPath) + .putList("xpack.security.http.ssl.supported_protocols", getProtocols()) .setSecureSettings(secureSettings) .build(); @@ -234,6 +242,7 @@ public void testHttpsClientAuth() throws Exception { Settings settings = Settings.builder() .put("xpack.http.ssl.key", keyPath) .put("xpack.http.ssl.certificate", certPath) + .putList("xpack.http.ssl.supported_protocols", getProtocols()) .setSecureSettings(secureSettings) .build(); @@ -370,6 +379,7 @@ public void testProxyCanHaveDifferentSchemeThanRequest() throws Exception { Settings serverSettings = Settings.builder() .put("xpack.http.ssl.key", keyPath) .put("xpack.http.ssl.certificate", certPath) + .putList("xpack.http.ssl.supported_protocols", getProtocols()) .setSecureSettings(serverSecureSettings) .build(); TestsSSLService sslService = new TestsSSLService(serverSettings, environment); @@ -383,6 +393,7 @@ public void testProxyCanHaveDifferentSchemeThanRequest() throws Exception { .put(HttpSettings.PROXY_PORT.getKey(), proxyServer.getPort()) .put(HttpSettings.PROXY_SCHEME.getKey(), "https") .put("xpack.http.ssl.certificate_authorities", trustedCertPath) + .putList("xpack.http.ssl.supported_protocols", getProtocols()) .build(); HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()) @@ -737,4 +748,23 @@ public static ClusterService mockClusterService() { private String getWebserverUri() { return String.format(Locale.ROOT, "http://%s:%s", webServer.getHostName(), webServer.getPort()); } + + /** + * The {@link HttpsServer} in the JDK has issues with TLSv1.3 when running in a JDK prior to + * 12.0.1 so we pin to TLSv1.2 when running on an earlier JDK + */ + private static List getProtocols() { + if (JavaVersion.current().compareTo(JavaVersion.parse("11")) < 0) { + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } else if (JavaVersion.current().compareTo(JavaVersion.parse("12")) < 0) { + return Collections.singletonList("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return Collections.singletonList("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } diff --git a/x-pack/qa/reindex-tests-with-security/build.gradle b/x-pack/qa/reindex-tests-with-security/build.gradle index 64e1c61b60717..7cbdfae5ed48c 100644 --- a/x-pack/qa/reindex-tests-with-security/build.gradle +++ b/x-pack/qa/reindex-tests-with-security/build.gradle @@ -36,6 +36,12 @@ integTestCluster { setting 'xpack.security.http.ssl.key_passphrase', 'http-password' setting 'reindex.ssl.truststore.path', 'ca.p12' setting 'reindex.ssl.truststore.password', 'password' + + // Workaround for JDK-8212885 + if (project.ext.runtimeJavaVersion.isJava12Compatible() == false) { + setting 'reindex.ssl.supported_protocols', 'TLSv1.2' + } + extraConfigFile 'roles.yml', 'roles.yml' [ test_admin: 'superuser',