From 476c82d2b0607806132311e84250614bcfb29a41 Mon Sep 17 00:00:00 2001 From: Jay Modi Date: Thu, 2 May 2019 11:54:54 -0600 Subject: [PATCH 1/3] Update TLS ciphers and protocols for JDK 11 (#41385) This commit updates the default ciphers and TLS protocols that are used after the minimum supported JDK is JDK 11. The conditionals around TLSv1.3 and 256-bit cipher support have been removed. JDK 11 no longer requires an unlimited JCE policy file for 256 bit cipher support and TLSv1.3 is supported in JDK 11+. New cipher support has been introduced in the newer JDK versions as well. The ciphers are ordered with PFS ciphers being most preferred, then AEAD ciphers, and finally those with mainstream hardware support. --- .../settings/security-settings.asciidoc | 31 +++++---- .../common/ssl/SslConfiguration.java | 8 +-- .../common/ssl/SslConfigurationLoader.java | 65 +++++------------- .../reindex/ReindexRestClientSslTests.java | 4 ++ .../xpack/core/XPackSettings.java | 52 ++++---------- .../xpack/core/ssl/SSLService.java | 6 +- .../xpack/core/ssl/TrustConfig.java | 5 +- .../xpack/core/XPackSettingsTests.java | 32 +-------- .../transport/ssl/certs/simple/testclient.jks | Bin 3358 -> 3887 bytes .../ssl/certs/simple/testnode_ec.pem | 8 +++ .../security/transport/nio/SSLDriver.java | 2 +- .../test/SecurityIntegTestCase.java | 2 - .../test/SecuritySettingsSource.java | 6 +- .../authc/pki/PkiAuthenticationTests.java | 15 ++-- ...stractSimpleSecurityTransportTestCase.java | 4 +- ...ServerTransportFilterIntegrationTests.java | 10 +-- .../transport/ssl/EllipticCurveSSLTests.java | 5 +- .../xpack/ssl/SSLClientAuthTests.java | 8 ++- .../xpack/ssl/SSLReloadIntegTests.java | 4 ++ .../xpack/ssl/SSLTrustRestrictionsTests.java | 21 ++++-- .../transport/ssl/certs/simple/testclient.jks | Bin 3358 -> 3887 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 ++++ .../ssl/certs/simple/testnode_ec.pem | 8 +++ 25 files changed, 135 insertions(+), 174 deletions(-) create mode 100644 x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem create mode 100644 x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.crt create mode 100644 x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem diff --git a/docs/reference/settings/security-settings.asciidoc b/docs/reference/settings/security-settings.asciidoc index dd2af0eeda955..9ce723d2815fb 100644 --- a/docs/reference/settings/security-settings.asciidoc +++ b/docs/reference/settings/security-settings.asciidoc @@ -513,8 +513,7 @@ and `full`. Defaults to `full`. See <> for an explanation of these values. `ssl.supported_protocols`:: -Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if -the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`. +Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`. `ssl.cipher_suites`:: Specifies the cipher suites that should be supported when communicating with the LDAP server. @@ -765,8 +764,7 @@ and `full`. Defaults to `full`. See <> for an explanation of these values. `ssl.supported_protocols`:: -Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if -the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`. +Supported protocols for TLS/SSL (with versions). Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`. `ssl.cipher_suites`:: Specifies the cipher suites that should be supported when communicating with the Active Directory server. @@ -1173,8 +1171,7 @@ Defaults to `full`. See <> for a more detailed explanation of these values. `ssl.supported_protocols`:: -Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if -the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`. +Specifies the supported protocols for TLS/SSL. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`. `ssl.cipher_suites`:: Specifies the @@ -1489,8 +1486,7 @@ settings. For more information, see `ssl.supported_protocols`:: Supported protocols with versions. Valid protocols: `SSLv2Hello`, -`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1` if -the JVM supports TLSv1.3, otherwise `TLSv1.2,TLSv1.1`. +`SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. Defaults to `TLSv1.3,TLSv1.2,TLSv1.1`. + -- NOTE: If `xpack.security.fips_mode.enabled` is `true`, you cannot use `SSLv2Hello` @@ -1521,13 +1517,18 @@ 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`. [float] [[tls-ssl-key-settings]] diff --git a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java index 68df7d248340d..52c1e8151f49d 100644 --- a/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java +++ b/libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslConfiguration.java @@ -24,7 +24,6 @@ import javax.net.ssl.X509ExtendedTrustManager; import java.nio.file.Path; import java.security.GeneralSecurityException; -import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -52,12 +51,7 @@ public class SslConfiguration { static final Map ORDERED_PROTOCOL_ALGORITHM_MAP; static { LinkedHashMap protocolAlgorithmMap = new LinkedHashMap<>(); - try { - SSLContext.getInstance("TLSv1.3"); - protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); - } catch (NoSuchAlgorithmException e) { - // ignore since we support JVMs that do not support TLSv1.3 - } + protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2"); protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1"); protocolAlgorithmMap.put("TLSv1", "TLSv1"); 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..a880090a048ef 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,21 +19,15 @@ package org.elasticsearch.common.ssl; -import javax.crypto.Cipher; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import java.nio.file.Path; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; import static org.elasticsearch.common.ssl.KeyStoreUtil.inferKeyStoreType; -import static org.elasticsearch.common.ssl.SslConfiguration.ORDERED_PROTOCOL_ALGORITHM_MAP; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CERTIFICATE_AUTHORITIES; import static org.elasticsearch.common.ssl.SslConfigurationKeys.CIPHERS; @@ -70,10 +64,22 @@ */ public abstract class SslConfigurationLoader { - static final List DEFAULT_PROTOCOLS = Collections.unmodifiableList( - ORDERED_PROTOCOL_ALGORITHM_MAP.containsKey("TLSv1.3") ? - Arrays.asList("TLSv1.3", "TLSv1.2", "TLSv1.1") : Arrays.asList("TLSv1.2", "TLSv1.1")); - static final List DEFAULT_CIPHERS = loadDefaultCiphers(); + static final List DEFAULT_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1"); + + /** + * This list has been created with ordering + */ + static final List DEFAULT_CIPHERS = List.of( + "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", // TLSv1.3 cipher has PFS, AEAD, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // PFS, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // PFS, hardware support + "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", // AEAD, hardware support + "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", // hardware support + "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"); // hardware support private static final char[] EMPTY_PASSWORD = new char[0]; private final String settingPrefix; @@ -141,9 +147,6 @@ public void setDefaultClientAuth(SslClientAuthenticationMode defaultClientAuth) /** * Change the default supported ciphers. - * The initial cipher list depends on the availability of {@link #has256BitAES() 256 bit AES}. - * - * @see #loadDefaultCiphers() */ public void setDefaultCiphers(List defaultCiphers) { this.defaultCiphers = defaultCiphers; @@ -336,40 +339,4 @@ private List resolveListSetting(String key, Function parser, L throw new SslConfigException("cannot retrieve setting [" + settingPrefix + key + "]", e); } } - - 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; - } else { - return ciphers128; - } - } - - private static boolean has256BitAES() { - try { - return Cipher.getMaxAllowedKeyLength("AES") > 128; - } catch (NoSuchAlgorithmException e) { - // No AES? Things are going to be very weird, but technically that means we don't have 256 bit AES, so ... - return false; - } - } } 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/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..92f8915e922f1 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 @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.core; -import org.apache.logging.log4j.LogManager; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.xpack.core.security.SecurityField; @@ -15,13 +14,10 @@ import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.VerificationMode; -import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; -import javax.net.ssl.SSLContext; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -38,7 +34,6 @@ private XPackSettings() { throw new IllegalStateException("Utility class should not be instantiated"); } - /** * Setting for controlling whether or not CCR is enabled. */ @@ -122,28 +117,17 @@ private XPackSettings() { * 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.*) */ - 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"); - try { - final boolean use256Bit = Cipher.getMaxAllowedKeyLength("AES") > 128; - 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; - } - } catch (NoSuchAlgorithmException e) { - // ignore it here - there will be issues elsewhere and its not nice to throw in a static initializer - } - - DEFAULT_CIPHERS = ciphers; - } + public static final List DEFAULT_CIPHERS = List.of( + "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", // TLSv1.3 cipher has PFS, AEAD, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", // PFS, AEAD, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", // PFS, hardware support + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", // PFS, hardware support + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", // PFS, hardware support + "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", // AEAD, hardware support + "TLS_RSA_WITH_AES_256_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", // hardware support + "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA"); // hardware support /* * Do not allow insecure hashing algorithms to be used for password hashing @@ -164,19 +148,7 @@ 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 List DEFAULT_SUPPORTED_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2", "TLSv1.1"); public static final SSLClientAuth CLIENT_AUTH_DEFAULT = SSLClientAuth.REQUIRED; public static final SSLClientAuth HTTP_CLIENT_AUTH_DEFAULT = SSLClientAuth.NONE; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java index fa5ec665043ae..6f74a182e5a77 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java @@ -57,8 +57,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import static org.elasticsearch.xpack.core.XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; - /** * Provides access to {@link SSLEngine} and {@link SSLSocketFactory} objects based on a provided configuration. All * configurations loaded by this service must be configured on construction. @@ -75,9 +73,7 @@ public class SSLService { private static final Map ORDERED_PROTOCOL_ALGORITHM_MAP; static { LinkedHashMap protocolAlgorithmMap = new LinkedHashMap<>(); - if (DEFAULT_SUPPORTED_PROTOCOLS.contains("TLSv1.3")) { - protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); - } + protocolAlgorithmMap.put("TLSv1.3", "TLSv1.3"); protocolAlgorithmMap.put("TLSv1.2", "TLSv1.2"); protocolAlgorithmMap.put("TLSv1.1", "TLSv1.1"); protocolAlgorithmMap.put("TLSv1", "TLSv1"); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java index a9bc737c94387..f570e0b42ed44 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TrustConfig.java @@ -119,9 +119,8 @@ X509ExtendedTrustManager createTrustManager(@Nullable Environment environment) { try { return CertParsingUtils.trustManager(trustConfigs.stream() - .flatMap((tc) -> Arrays.stream(tc.createTrustManager(environment).getAcceptedIssuers())) - .collect(Collectors.toList()) - .toArray(new X509Certificate[0])); + .flatMap((tc) -> Arrays.stream(tc.createTrustManager(environment).getAcceptedIssuers())) + .toArray(X509Certificate[]::new)); } catch (Exception e) { throw new ElasticsearchException("failed to create trust manager", e); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java index 004b46897a48e..924e55be51cb4 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/XPackSettingsTests.java @@ -7,30 +7,19 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.ESTestCase; -import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; -import javax.net.ssl.SSLContext; import java.security.NoSuchAlgorithmException; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.not; public class XPackSettingsTests extends ESTestCase { - public void testDefaultSSLCiphers() throws Exception { + public void testDefaultSSLCiphers() { assertThat(XPackSettings.DEFAULT_CIPHERS, hasItem("TLS_RSA_WITH_AES_128_CBC_SHA")); - - final boolean useAES256 = Cipher.getMaxAllowedKeyLength("AES") > 128; - if (useAES256) { - logger.info("AES 256 is available"); - assertThat(XPackSettings.DEFAULT_CIPHERS, hasItem("TLS_RSA_WITH_AES_256_CBC_SHA")); - } else { - logger.info("AES 256 is not available"); - assertThat(XPackSettings.DEFAULT_CIPHERS, not(hasItem("TLS_RSA_WITH_AES_256_CBC_SHA"))); - } + assertThat(XPackSettings.DEFAULT_CIPHERS, hasItem("TLS_RSA_WITH_AES_256_CBC_SHA")); } public void testPasswordHashingAlgorithmSettingValidation() { @@ -50,16 +39,10 @@ public void testPasswordHashingAlgorithmSettingValidation() { Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), bcryptAlgo).build())); } - public void testDefaultSupportedProtocolsWithTLSv13() throws Exception { - assumeTrue("current JVM does not support TLSv1.3", supportTLSv13()); + public void testDefaultSupportedProtocols() { assertThat(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS, contains("TLSv1.3", "TLSv1.2", "TLSv1.1")); } - public void testDefaultSupportedProtocolsWithoutTLSv13() throws Exception { - assumeFalse("current JVM supports TLSv1.3", supportTLSv13()); - assertThat(XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS, contains("TLSv1.2", "TLSv1.1")); - } - private boolean isSecretkeyFactoryAlgoAvailable(String algorithmId) { try { SecretKeyFactory.getInstance(algorithmId); @@ -68,13 +51,4 @@ private boolean isSecretkeyFactoryAlgoAvailable(String algorithmId) { return false; } } - - private boolean supportTLSv13() { - try { - SSLContext.getInstance("TLSv1.3"); - return true; - } catch (NoSuchAlgorithmException e) { - return false; - } - } } 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..b4cf27dfd26a87f36fec50d52d84c81d15d71589 100644 GIT binary patch delta 369 zcmbOywO)?r-`jt085kItfS7qB&p#eVFo!j_GCQ@Bfq^m0YhLp|2G$5YQv*vN_p?D0 z<9i^UynvaBk%@_=C_};8fQOAktIgw_EekUfD}#a3tB;3aAUm9EVVxwbmuJo_8%U0hfG`iI delta 42 wcmZ24H&2S^-`jt085kItKzJk1KOPZ7xA^DtD-_@6?)fvvVUENMk3DX209_~%9smFU diff --git a/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem new file mode 100644 index 0000000000000..f8f29e47e0d35 --- /dev/null +++ b/x-pack/plugin/core/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem @@ -0,0 +1,8 @@ +Bag Attributes + friendlyName: testnode_ec + localKeyID: 54 69 6D 65 20 31 35 35 36 30 33 32 36 30 37 32 33 30 +Key Attributes: +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCxFwoKqfcGailZhuh0 +xEj3gssdjuEw6BasiC8+zhqHBA== +-----END PRIVATE KEY----- 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/SecurityIntegTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java index bd9d58e6ea549..462e4e26541e6 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java @@ -243,8 +243,6 @@ protected Settings nodeSettings(int nodeOrdinal) { Settings customSettings = customSecuritySettingsSource.nodeSettings(nodeOrdinal); builder.put(customSettings, false); // handle secure settings separately builder.put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial"); - builder.put(NetworkModule.TRANSPORT_TYPE_KEY, randomBoolean() ? SecurityField.NAME4 : SecurityField.NIO); - builder.put(NetworkModule.HTTP_TYPE_KEY, randomBoolean() ? SecurityField.NAME4 : SecurityField.NIO); Settings.Builder customBuilder = Settings.builder().put(customSettings); if (customBuilder.getSecureSettings() != null) { SecuritySettingsSource.addSecureSettings(builder, secureSettings -> 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..09e1c00cb543e 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/testnode_ec.crt", + "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.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..1ef36f4fdbdf7 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(); @@ -119,7 +120,8 @@ public void testRestAuthenticationViaPki() throws Exception { "testnode", "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt", Arrays.asList("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.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")); try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()) { HttpPut put = new HttpPut(getNodeUrl() + "foo"); try (CloseableHttpResponse response = SocketAccess.doPrivileged(() -> client.execute(put))) { @@ -133,7 +135,8 @@ public void testRestAuthenticationFailure() throws Exception { SSLContext context = getRestSSLContext("/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/testclient.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")); try (CloseableHttpClient client = HttpClients.custom().setSSLContext(context).build()) { HttpPut put = new HttpPut(getNodeUrl() + "foo"); try (CloseableHttpResponse response = SocketAccess.doPrivileged(() -> client.execute(put))) { 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..8bf5bf1d0af77 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; @@ -40,6 +39,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.concurrent.CountDownLatch; import static org.elasticsearch.discovery.SettingsBasedSeedHostsProvider.DISCOVERY_SEED_HOSTS_SETTING; @@ -80,8 +80,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 +110,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")); + List.of("/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 +150,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")); + List.of("/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..71b3d7a1990b4 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.is; 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"), is("TLS_AES_256_GCM_SHA384"), is("TLS_AES_128_GCM_SHA256"))); } } 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..33d75ecb1d9ac 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 @@ -135,6 +135,7 @@ public void testThatTransportWorksWithoutSslClientAuth() throws IOException { 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 +148,7 @@ 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.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 +166,13 @@ 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"); + SSLContext context = SSLContext.getInstance(randomFrom("TLSv1.3", "TLSv1.2")); context.init(new KeyManager[] { km }, new TrustManager[] { tm }, new SecureRandom()); return context; } catch (Exception e) { 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/testclient.jks b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks index d6dc21c1bd5ff4a248bfba5a171518cd649e278d..b4cf27dfd26a87f36fec50d52d84c81d15d71589 100644 GIT binary patch delta 369 zcmbOywO)?r-`jt085kItfS7qB&p#eVFo!j_GCQ@Bfq^m0YhLp|2G$5YQv*vN_p?D0 z<9i^UynvaBk%@_=C_};8fQOAktIgw_EekUfD}#a3tB;3aAUm9EVVxwbmuJo_8%U0hfG`iI delta 42 wcmZ24H&2S^-`jt085kItKzJk1KOPZ7xA^DtD-_@6?)fvvVUENMk3DX209_~%9smFU 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/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem new file mode 100644 index 0000000000000..f8f29e47e0d35 --- /dev/null +++ b/x-pack/plugin/security/src/test/resources/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_ec.pem @@ -0,0 +1,8 @@ +Bag Attributes + friendlyName: testnode_ec + localKeyID: 54 69 6D 65 20 31 35 35 36 30 33 32 36 30 37 32 33 30 +Key Attributes: +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCxFwoKqfcGailZhuh0 +xEj3gssdjuEw6BasiC8+zhqHBA== +-----END PRIVATE KEY----- From 4f4f4fa1970e557ded3861d97ab43ba749bc5bd2 Mon Sep 17 00:00:00 2001 From: jaymode Date: Fri, 3 May 2019 09:40:50 -0600 Subject: [PATCH 2/3] Fixes for TLSv1.3 on JDK11 --- .../client/RestClientBuilderIntegTests.java | 35 ++++++++++++++++- .../AzureDiscoveryClusterFormationTests.java | 22 ++++++++++- .../exporter/http/HttpExporterSslIT.java | 25 ++++++++++++ .../security/authc/saml/SamlRealmTests.java | 23 +++++++++++ .../transport/ssl/SslMultiPortTests.java | 38 +++++++++++++++---- .../xpack/ssl/SSLClientAuthTests.java | 20 ++++++++++ .../webhook/WebhookHttpsIntegrationTests.java | 24 ++++++++++++ .../watcher/common/http/HttpClientTests.java | 36 ++++++++++++++++-- 8 files changed, 210 insertions(+), 13 deletions(-) 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..4aa69d3b3e9c1 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,35 @@ private static SSLContext getSslContext() throws Exception { } return sslContext; } + + /** + * 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() { + 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 > 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/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..82347ca2bf1e4 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,28 @@ 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("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/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java index ae363cd3c8258..2621a43ccee4d 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java @@ -5,9 +5,11 @@ */ package org.elasticsearch.xpack.monitoring.exporter.http; +import com.sun.net.httpserver.HttpsServer; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; +import org.elasticsearch.bootstrap.JavaVersion; import org.elasticsearch.common.settings.MockSecureSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; @@ -15,6 +17,7 @@ import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.Scope; import org.elasticsearch.test.http.MockWebServer; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.TestsSSLService; import org.elasticsearch.xpack.core.ssl.VerificationMode; import org.elasticsearch.xpack.monitoring.exporter.Exporter; @@ -28,6 +31,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.instanceOf; @@ -98,6 +104,7 @@ private MockWebServer buildWebServer() throws IOException { .put("xpack.transport.security.ssl.certificate", cert) .put("xpack.transport.security.ssl.key", key) .put("xpack.transport.security.ssl.key_passphrase", "testnode") + .putList("xpack.transport.security.ssl.supported_protocols", getProtocols()) .put(globalSettings) .build(); @@ -185,4 +192,22 @@ private void clearTransientSettings(String... names) { updateSettings.transientSettings(builder.build()); client().admin().cluster().updateSettings(updateSettings).actionGet(); } + + + /** + * 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("12")) < 0) { + return List.of("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return List.of("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } 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..c5b5e734b6505 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,21 @@ 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("12")) < 0) { + return List.of("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return List.of("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } 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..d07bff822a2f8 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; @@ -114,11 +119,12 @@ public void testThatStandardTransportClientCanConnectToDefaultProfile() throws E */ public void testThatStandardTransportClientCanConnectToNoClientAuthProfile() throws Exception { try(TransportClient transportClient = new TestXPackTransportClient(Settings.builder() - .put(transportClientSettings()) - .put("xpack.security.transport.ssl.enabled", true) - .put("node.name", "programmatic_transport_client") - .put("cluster.name", internalCluster().getClusterName()) - .build(), LocalStateSecurity.class)) { + .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)) { transportClient.addTransportAddress(new TransportAddress(localAddress, getProfilePort("no_client_auth"))); assertGreenClusterState(transportClient); @@ -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,8 @@ 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")); + List.of("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.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"))); @@ -275,6 +283,7 @@ public void testThatTransportClientWithOnlyTruststoreCanConnectToNoClientAuthPro .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.supported_protocols", getProtocols()) .build(); try (TransportClient transportClient = new TestXPackTransportClient(settings, Collections.singletonList(LocalStateSecurity.class))) { @@ -386,6 +395,7 @@ public void testThatSSLTransportClientWithNoTruststoreCannotConnectToNoClientAut .put("cluster.name", internalCluster().getClusterName()) .put("xpack.security.transport.ssl.client_authentication", SSLClientAuth.REQUIRED) .put("xpack.security.transport.ssl.enabled", true) + .putList("xpack.security.transport.ssl.supported_protocols", getProtocols()) .build(); try (TransportClient transportClient = new TestXPackTransportClient(settings, Collections.singletonList(LocalStateSecurity.class))) { @@ -409,4 +419,18 @@ 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() { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) { + return List.of("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 33d75ecb1d9ac..52a03dca95b36 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; @@ -148,6 +153,7 @@ 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) + .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()) @@ -190,4 +196,18 @@ 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() { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("11.0.3")) < 0) { + return List.of("TLSv1.2"); + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } 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..377ffa67c9a8f 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,9 @@ import org.junit.Before; import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder; @@ -51,6 +57,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 +138,21 @@ 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("12")) < 0) { + return List.of("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return List.of("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..6e9957a404d9a 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.security.http.ssl.supported_protocols", getProtocols()) .setSecureSettings(serverSecureSettings) .build(); TestsSSLService sslService = new TestsSSLService(serverSettings, environment); @@ -379,11 +389,12 @@ public void testProxyCanHaveDifferentSchemeThanRequest() throws Exception { proxyServer.start(); Settings settings = Settings.builder() - .put(HttpSettings.PROXY_HOST.getKey(), "localhost") - .put(HttpSettings.PROXY_PORT.getKey(), proxyServer.getPort()) - .put(HttpSettings.PROXY_SCHEME.getKey(), "https") + .put(HttpSettings.PROXY_HOST.getKey(), "localhost") + .put(HttpSettings.PROXY_PORT.getKey(), proxyServer.getPort()) + .put(HttpSettings.PROXY_SCHEME.getKey(), "https") .put("xpack.http.ssl.certificate_authorities", trustedCertPath) - .build(); + .putList("xpack.security.http.ssl.supported_protocols", getProtocols()) + .build(); HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort()) .method(HttpMethod.GET) @@ -737,4 +748,21 @@ 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("12")) < 0) { + return List.of("TLSv1.2"); + } else { + JavaVersion full = + AccessController.doPrivileged((PrivilegedAction) () -> JavaVersion.parse(System.getProperty("java.version"))); + if (full.compareTo(JavaVersion.parse("12.0.1")) < 0) { + return List.of("TLSv1.2"); + } + } + return XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; + } } From c109a6f9c24db93dbde81ffeea2cc377f14f73f8 Mon Sep 17 00:00:00 2001 From: jaymode Date: Mon, 6 May 2019 08:37:51 -0600 Subject: [PATCH 3/3] fix for JDK-8212885 --- x-pack/qa/reindex-tests-with-security/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) 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',