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 8f22063d3f27f..ca30cca498346 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 @@ -157,34 +157,4 @@ private String contextProtocol() { "no supported SSL/TLS protocol was found in the configured supported protocols: " + supportedProtocols ); } - - // TODO Add explicitlyConfigured to equals&hashCode? - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final SslConfiguration that = (SslConfiguration) o; - return Objects.equals(this.settingPrefix, that.settingPrefix) - && Objects.equals(this.trustConfig, that.trustConfig) - && Objects.equals(this.keyConfig, that.keyConfig) - && this.verificationMode == that.verificationMode - && this.clientAuth == that.clientAuth - && Objects.equals(this.ciphers, that.ciphers) - && Objects.equals(this.supportedProtocols, that.supportedProtocols) - && this.handshakeTimeoutMillis == that.handshakeTimeoutMillis; - } - - @Override - public int hashCode() { - return Objects.hash( - settingPrefix, - trustConfig, - keyConfig, - verificationMode, - clientAuth, - ciphers, - supportedProtocols, - handshakeTimeoutMillis - ); - } } diff --git a/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/TLSConfig.java b/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/TLSConfig.java index 9e8d452ba2f46..9079f2177ad46 100644 --- a/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/TLSConfig.java +++ b/modules/transport-netty4/src/main/java/org/elasticsearch/transport/netty4/TLSConfig.java @@ -9,30 +9,28 @@ package org.elasticsearch.transport.netty4; -import org.elasticsearch.common.ssl.SslConfiguration; - import javax.net.ssl.SSLEngine; -public record TLSConfig(SslConfiguration sslConfiguration, EngineProvider engineProvider) { +public record TLSConfig(EngineProvider engineProvider) { public boolean isTLSEnabled() { - return sslConfiguration != null; + return engineProvider != null; } public SSLEngine createServerSSLEngine() { assert isTLSEnabled(); - SSLEngine sslEngine = engineProvider.create(sslConfiguration, null, -1); + SSLEngine sslEngine = engineProvider.create(null, -1); sslEngine.setUseClientMode(false); return sslEngine; } public static TLSConfig noTLS() { - return new TLSConfig(null, null); + return new TLSConfig(null); } @FunctionalInterface public interface EngineProvider { - SSLEngine create(SslConfiguration configuration, String host, int port); + SSLEngine create(String host, int port); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/CommandLineHttpClient.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/CommandLineHttpClient.java index be0199fc8ba30..20c6e40c6db39 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/CommandLineHttpClient.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/CommandLineHttpClient.java @@ -14,7 +14,6 @@ import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.core.CharArrays; import org.elasticsearch.core.CheckedFunction; import org.elasticsearch.core.Releasables; @@ -26,6 +25,7 @@ import org.elasticsearch.xpack.core.security.HttpResponse.HttpResponseBuilder; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.io.IOException; import java.io.InputStream; @@ -154,10 +154,12 @@ private HttpResponse execute( sslContext.init(null, new TrustManager[] { fingerprintTrustingTrustManager(pinnedCaCertFingerprint) }, null); httpsConn.setSSLSocketFactory(sslContext.getSocketFactory()); } else { - final SslConfiguration sslConfiguration = sslService.getHttpTransportSSLConfiguration(); + final SslProfile sslProfile = sslService.profile(XPackSettings.HTTP_SSL_PREFIX); // Requires permission java.lang.RuntimePermission "setFactory"; - httpsConn.setSSLSocketFactory(sslService.sslSocketFactory(sslConfiguration)); - final boolean isHostnameVerificationEnabled = sslConfiguration.verificationMode().isHostnameVerificationEnabled(); + httpsConn.setSSLSocketFactory(sslProfile.socketFactory()); + final boolean isHostnameVerificationEnabled = sslProfile.configuration() + .verificationMode() + .isHostnameVerificationEnabled(); if (isHostnameVerificationEnabled == false) { httpsConn.setHostnameVerifier((hostname, session) -> true); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilder.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilder.java new file mode 100644 index 0000000000000..f2676c701edc5 --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilder.java @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.ssl; + +import org.apache.http.HttpHost; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy; +import org.apache.http.nio.reactor.IOSession; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.logging.LoggerMessageFormat; +import org.elasticsearch.common.ssl.SslConfiguration; +import org.elasticsearch.common.ssl.SslDiagnostics; + +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.auth.x500.X500Principal; + +public class SSLIOSessionStrategyBuilder { + + public static final SSLIOSessionStrategyBuilder INSTANCE = new SSLIOSessionStrategyBuilder(); + + public SSLIOSessionStrategy sslIOSessionStrategy(SslConfiguration config, SSLContext sslContext) { + String[] ciphers = supportedCiphers(sslParameters(sslContext).getCipherSuites(), config.getCipherSuites(), false); + String[] supportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); + HostnameVerifier verifier; + + if (config.verificationMode().isHostnameVerificationEnabled()) { + verifier = SSLIOSessionStrategy.getDefaultHostnameVerifier(); + } else { + verifier = NoopHostnameVerifier.INSTANCE; + } + + return sslIOSessionStrategy(sslContext, supportedProtocols, ciphers, verifier); + } + + /** + * This method exists to simplify testing + */ + String[] supportedCiphers(String[] supportedCiphers, List requestedCiphers, boolean log) { + return SSLService.supportedCiphers(supportedCiphers, requestedCiphers, log); + } + + /** + * The {@link SSLParameters} that are associated with the {@code sslContext}. + *

+ * This method exists to simplify testing since {@link SSLContext#getSupportedSSLParameters()} is {@code final}. + * + * @param sslContext The SSL context for the current SSL settings + * @return Never {@code null}. + */ + SSLParameters sslParameters(SSLContext sslContext) { + return sslContext.getSupportedSSLParameters(); + } + + /** + * This method only exists to simplify testing because {@link SSLIOSessionStrategy} does + * not expose any of the parameters that you give it. + */ + SSLIOSessionStrategy sslIOSessionStrategy(SSLContext sslContext, String[] protocols, String[] ciphers, HostnameVerifier verifier) { + return new SSLIOSessionStrategy(sslContext, protocols, ciphers, verifier) { + @Override + protected void verifySession(HttpHost host, IOSession iosession, SSLSession session) throws SSLException { + if (verifier.verify(host.getHostName(), session) == false) { + final Certificate[] certs = session.getPeerCertificates(); + final X509Certificate x509 = (X509Certificate) certs[0]; + final X500Principal x500Principal = x509.getSubjectX500Principal(); + final String altNames = Strings.collectionToCommaDelimitedString(SslDiagnostics.describeValidHostnames(x509)); + throw new SSLPeerUnverifiedException( + LoggerMessageFormat.format( + "Expected SSL certificate to be valid for host [{}]," + + " but it is only valid for subject alternative names [{}] and subject [{}]", + new Object[] { host.getHostName(), altNames, x500Principal.toString() } + ) + ); + } + } + }; + } +} 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 d0d5e463f9652..86e3e0a0e9c37 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 @@ -6,25 +6,22 @@ */ package org.elasticsearch.xpack.core.ssl; -import org.apache.http.HttpHost; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy; -import org.apache.http.nio.reactor.IOSession; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.ssl.DiagnosticTrustManager; import org.elasticsearch.common.ssl.KeyStoreUtil; import org.elasticsearch.common.ssl.SslConfigException; import org.elasticsearch.common.ssl.SslConfiguration; -import org.elasticsearch.common.ssl.SslDiagnostics; import org.elasticsearch.common.ssl.SslKeyConfig; import org.elasticsearch.common.ssl.SslTrustConfig; import org.elasticsearch.common.util.Maps; @@ -42,8 +39,6 @@ import java.security.KeyManagementException; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -67,16 +62,13 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; -import javax.security.auth.x500.X500Principal; import static org.elasticsearch.transport.RemoteClusterPortSettings.REMOTE_CLUSTER_SERVER_ENABLED; import static org.elasticsearch.xpack.core.XPackSettings.DEFAULT_SUPPORTED_PROTOCOLS; @@ -216,6 +208,20 @@ public static void registerSettings(List> settingList) { settingList.add(DIAGNOSE_TRUST_EXCEPTIONS_SETTING); } + /** + * Return an encapsulated object for the named profile. + * A profile is named according to the settings prefix under which it is defined (e.g. {@code xpack.http.ssl} or + * {@code xpack.security.transport.ssl} + * @throws IllegalArgumentException if the named profile does not exist + */ + public SslProfile profile(String profileName) { + final SslConfiguration configuration = getSSLConfiguration(profileName); + if (configuration == null) { + throw new IllegalArgumentException(Strings.format("No SSL configuration for context name [%s]", profileName)); + } + return sslContextHolder(configuration); + } + /** * Create a new {@link SSLIOSessionStrategy} based on the provided settings. The settings are used to identify the SSL configuration * that should be used to create the context. @@ -224,134 +230,14 @@ public static void registerSettings(List> settingList) { * return a context created from the default configuration * @return Never {@code null}. * @deprecated This method will fail if the SSL configuration uses a {@link org.elasticsearch.common.settings.SecureSetting} but the - * {@link org.elasticsearch.common.settings.SecureSettings} have been closed. Use {@link #getSSLConfiguration(String)} - * and {@link #sslIOSessionStrategy(SslConfiguration)} (Deprecated, but not removed because monitoring uses dynamic SSL settings) + * {@link org.elasticsearch.common.settings.SecureSettings} have been closed. Use {@link #profile(String)} + * and {@link SslProfile#ioSessionStrategy4()} + * (Deprecated, but not removed because monitoring uses dynamic SSL settings) */ @Deprecated public SSLIOSessionStrategy sslIOSessionStrategy(Settings settingsToUse) { SslConfiguration config = sslConfiguration(settingsToUse); - return sslIOSessionStrategy(config); - } - - public SSLIOSessionStrategy sslIOSessionStrategy(SslConfiguration config) { - SSLContext sslContext = sslContext(config); - String[] ciphers = supportedCiphers(sslParameters(sslContext).getCipherSuites(), config.getCipherSuites(), false); - String[] supportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); - HostnameVerifier verifier; - - if (config.verificationMode().isHostnameVerificationEnabled()) { - verifier = SSLIOSessionStrategy.getDefaultHostnameVerifier(); - } else { - verifier = NoopHostnameVerifier.INSTANCE; - } - - final SSLIOSessionStrategy strategy = sslIOSessionStrategy(sslContext, supportedProtocols, ciphers, verifier); - return strategy; - } - - public static HostnameVerifier getHostnameVerifier(SslConfiguration sslConfiguration) { - if (sslConfiguration.verificationMode().isHostnameVerificationEnabled()) { - return new DefaultHostnameVerifier(); - } else { - return NoopHostnameVerifier.INSTANCE; - } - } - - /** - * The {@link SSLParameters} that are associated with the {@code sslContext}. - *

- * This method exists to simplify testing since {@link SSLContext#getSupportedSSLParameters()} is {@code final}. - * - * @param sslContext The SSL context for the current SSL settings - * @return Never {@code null}. - */ - SSLParameters sslParameters(SSLContext sslContext) { - return sslContext.getSupportedSSLParameters(); - } - - /** - * This method only exists to simplify testing of {@link #sslIOSessionStrategy(Settings)} because {@link SSLIOSessionStrategy} does - * not expose any of the parameters that you give it. - * - * @param sslContext SSL Context used to handle SSL / TCP requests - * @param protocols Supported protocols - * @param ciphers Supported ciphers - * @param verifier Hostname verifier - * @return Never {@code null}. - */ - SSLIOSessionStrategy sslIOSessionStrategy(SSLContext sslContext, String[] protocols, String[] ciphers, HostnameVerifier verifier) { - return new SSLIOSessionStrategy(sslContext, protocols, ciphers, verifier) { - @Override - protected void verifySession(HttpHost host, IOSession iosession, SSLSession session) throws SSLException { - if (verifier.verify(host.getHostName(), session) == false) { - final Certificate[] certs = session.getPeerCertificates(); - final X509Certificate x509 = (X509Certificate) certs[0]; - final X500Principal x500Principal = x509.getSubjectX500Principal(); - final String altNames = Strings.collectionToCommaDelimitedString(SslDiagnostics.describeValidHostnames(x509)); - throw new SSLPeerUnverifiedException( - LoggerMessageFormat.format( - "Expected SSL certificate to be valid for host [{}]," - + " but it is only valid for subject alternative names [{}] and subject [{}]", - new Object[] { host.getHostName(), altNames, x500Principal.toString() } - ) - ); - } - } - }; - } - - /** - * Create a new {@link SSLSocketFactory} based on the provided configuration. - * The socket factory will also properly configure the ciphers and protocols on each socket that is created - * - * @param configuration The SSL configuration to use. Typically obtained from {@link #getSSLConfiguration(String)} - * @return Never {@code null}. - */ - public SSLSocketFactory sslSocketFactory(SslConfiguration configuration) { - final SSLContextHolder contextHolder = sslContextHolder(configuration); - SSLSocketFactory socketFactory = contextHolder.sslContext().getSocketFactory(); - final SecuritySSLSocketFactory securitySSLSocketFactory = new SecuritySSLSocketFactory( - () -> contextHolder.sslContext().getSocketFactory(), - configuration.supportedProtocols().toArray(Strings.EMPTY_ARRAY), - supportedCiphers(socketFactory.getSupportedCipherSuites(), configuration.getCipherSuites(), false) - ); - contextHolder.addReloadListener(securitySSLSocketFactory::reload); - return securitySSLSocketFactory; - } - - /** - * Creates an {@link SSLEngine} based on the provided configuration. This SSLEngine can be used for a connection that requires - * hostname verification assuming the provided - * host and port are correct. The SSLEngine created by this method is most useful for clients with hostname verification enabled - * - * @param configuration the ssl configuration - * @param host the host of the remote endpoint. If using hostname verification, this should match what is in the remote - * endpoint's certificate - * @param port the port of the remote endpoint - * @return {@link SSLEngine} - * @see #getSSLConfiguration(String) - */ - public SSLEngine createSSLEngine(SslConfiguration configuration, String host, int port) { - SSLContext sslContext = sslContext(configuration); - SSLEngine sslEngine = sslContext.createSSLEngine(host, port); - String[] ciphers = supportedCiphers(sslEngine.getSupportedCipherSuites(), configuration.getCipherSuites(), false); - String[] supportedProtocols = configuration.supportedProtocols().toArray(Strings.EMPTY_ARRAY); - SSLParameters parameters = new SSLParameters(ciphers, supportedProtocols); - if (configuration.verificationMode().isHostnameVerificationEnabled() && host != null) { - // By default, an SSLEngine will not perform hostname verification. In order to perform hostname verification - // we need to specify a EndpointIdentificationAlgorithm. We use the HTTPS algorithm to prevent against - // man in the middle attacks for all of our connections. - parameters.setEndpointIdentificationAlgorithm("HTTPS"); - } - // we use the cipher suite order so that we can prefer the ciphers we set first in the list - parameters.setUseCipherSuitesOrder(true); - configuration.clientAuth().configure(parameters); - - // many SSLEngine options can be configured using either SSLParameters or direct methods on the engine itself, but there is one - // tricky aspect; if you set a value directly on the engine and then later set the SSLParameters the value set directly on the - // engine will be overwritten by the value in the SSLParameters - sslEngine.setSSLParameters(parameters); - return sslEngine; + return SSLIOSessionStrategyBuilder.INSTANCE.sslIOSessionStrategy(config, sslContext(config)); } /** @@ -375,11 +261,11 @@ public static boolean isSSLClientAuthEnabled(SslConfiguration sslConfiguration) /** * Returns the {@link SSLContext} for the configuration. Mainly used for testing */ - public SSLContext sslContext(SslConfiguration configuration) { + SSLContext sslContext(SslConfiguration configuration) { return sslContextHolder(configuration).sslContext(); } - public void reloadSSLContext(SslConfiguration configuration) { + void reloadSSLContext(SslConfiguration configuration) { sslContextHolder(configuration).reload(); } @@ -428,7 +314,7 @@ Collection getLoadedSslConfigurations() { * * @throws IllegalArgumentException if no supported ciphers are in the requested ciphers */ - String[] supportedCiphers(String[] supportedCiphers, List requestedCiphers, boolean log) { + static String[] supportedCiphers(String[] supportedCiphers, List requestedCiphers, boolean log) { List supportedCiphersList = new ArrayList<>(requestedCiphers.size()); List unsupportedCiphers = new LinkedList<>(); boolean found; @@ -797,7 +683,7 @@ private static SSLSocket createWithPermissions(CheckedSupplier(); } - SSLContext sslContext() { + public SSLContext sslContext() { return context; } + @Override + public SslConfiguration configuration() { + return this.sslConfiguration; + } + + @Override + public SSLSocketFactory socketFactory() { + SSLSocketFactory socketFactory = context.getSocketFactory(); + final SecuritySSLSocketFactory securitySSLSocketFactory = new SecuritySSLSocketFactory( + () -> context.getSocketFactory(), + sslConfiguration.supportedProtocols().toArray(Strings.EMPTY_ARRAY), + supportedCiphers(socketFactory.getSupportedCipherSuites(), sslConfiguration.getCipherSuites(), false) + ); + this.addReloadListener(securitySSLSocketFactory::reload); + return securitySSLSocketFactory; + } + + @Override + public HostnameVerifier hostnameVerifier() { + if (this.sslConfiguration.verificationMode().isHostnameVerificationEnabled()) { + return new DefaultHostnameVerifier(); + } else { + return NoopHostnameVerifier.INSTANCE; + } + } + + @Override + public SSLConnectionSocketFactory connectionSocketFactory() { + return new SSLConnectionSocketFactory(socketFactory(), hostnameVerifier()); + } + + @Override + public SSLIOSessionStrategy ioSessionStrategy4() { + return SSLIOSessionStrategyBuilder.INSTANCE.sslIOSessionStrategy(this.sslConfiguration, context); + } + + @Override + public SSLEngine engine(String host, int port) { + final SSLEngine sslEngine = this.context.createSSLEngine(host, port); + final String[] ciphers = supportedCiphers(sslEngine.getSupportedCipherSuites(), this.sslConfiguration.getCipherSuites(), false); + final String[] supportedProtocols = this.configuration().supportedProtocols().toArray(Strings.EMPTY_ARRAY); + final SSLParameters parameters = new SSLParameters(ciphers, supportedProtocols); + if (this.sslConfiguration.verificationMode().isHostnameVerificationEnabled() && host != null) { + // By default, an SSLEngine will not perform hostname verification. In order to perform hostname verification + // we need to specify a EndpointIdentificationAlgorithm. We use the HTTPS algorithm to prevent against + // man in the middle attacks for all of our connections. + parameters.setEndpointIdentificationAlgorithm("HTTPS"); + } + // we use the cipher suite order so that we can prefer the ciphers we set first in the list + parameters.setUseCipherSuitesOrder(true); + this.sslConfiguration.clientAuth().configure(parameters); + + // many SSLEngine options can be configured using either SSLParameters or direct methods on the engine itself, but there is one + // tricky aspect; if you set a value directly on the engine and then later set the SSLParameters the value set directly on the + // engine will be overwritten by the value in the SSLParameters + sslEngine.setSSLParameters(parameters); + return sslEngine; + } + synchronized void reload() { invalidateSessions(context.getClientSessionContext()); invalidateSessions(context.getServerSessionContext()); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SslProfile.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SslProfile.java new file mode 100644 index 0000000000000..d7a477019f2ce --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SslProfile.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.ssl; + +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy; +import org.elasticsearch.common.ssl.SslConfiguration; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSocketFactory; + +/** + * An SSL Profile is a runtime implementation of a {@link SslConfiguration}. + * It provides access to various SSL related objects that are automatically configured according to the associated {@link SslConfiguration}. + */ +public interface SslProfile { + SslConfiguration configuration(); + + SSLContext sslContext(); + + /** + * Create a new {@link SSLSocketFactory} based on the provided configuration. + * The socket factory will also properly configure the ciphers and protocols on each socket that is created + * + * @return Never {@code null}. + */ + SSLSocketFactory socketFactory(); + + HostnameVerifier hostnameVerifier(); + + SSLConnectionSocketFactory connectionSocketFactory(); + + /** + * @return An object that is useful for configuring Apache Http Client v4.x + */ + SSLIOSessionStrategy ioSessionStrategy4(); + + SSLEngine engine(String host, int port); +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilderTests.java new file mode 100644 index 0000000000000..8f3140dc154b7 --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLIOSessionStrategyBuilderTests.java @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.ssl; + +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.ssl.SslConfiguration; +import org.elasticsearch.common.ssl.SslVerificationMode; +import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.test.ESTestCase; +import org.mockito.Mockito; + +import java.util.List; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SSLIOSessionStrategyBuilderTests extends ESTestCase { + + public void testBuildSSLStrategy() { + var env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build()); + // this just exhaustively verifies that the right things are called and that it uses the right parameters + SslVerificationMode mode = randomFrom(SslVerificationMode.values()); + Settings settings = Settings.builder() + .put("supported_protocols", "protocols") + .put("cipher_suites", "INVALID_CIPHER") + .put("verification_mode", mode.name()) + .build(); + SSLIOSessionStrategyBuilder builder = mock(SSLIOSessionStrategyBuilder.class); + SslConfiguration sslConfig = SslSettingsLoader.load(settings, null, env); + SSLParameters sslParameters = mock(SSLParameters.class); + SSLContext sslContext = mock(SSLContext.class); + String[] protocols = new String[] { "protocols" }; + String[] ciphers = new String[] { "ciphers!!!" }; + String[] supportedCiphers = new String[] { "supported ciphers" }; + List requestedCiphers = List.of("INVALID_CIPHER"); + SSLIOSessionStrategy sslStrategy = mock(SSLIOSessionStrategy.class); + + when(builder.supportedCiphers(any(String[].class), anyList(), any(Boolean.TYPE))).thenAnswer(inv -> { + final Object[] args = inv.getArguments(); + assertThat(args[0], is(supportedCiphers)); + assertThat(args[1], is(requestedCiphers)); + assertThat(args[2], is(false)); + return ciphers; + }); + when(builder.sslParameters(sslContext)).thenReturn(sslParameters); + when(sslParameters.getCipherSuites()).thenReturn(supportedCiphers); + + when(builder.sslIOSessionStrategy(any(SSLContext.class), any(String[].class), any(String[].class), any(HostnameVerifier.class))) + .thenAnswer(inv -> { + final Object[] args = inv.getArguments(); + assertThat(args[0], is(sslContext)); + assertThat(args[1], is(protocols)); + assertThat(args[2], is(ciphers)); + if (mode.isHostnameVerificationEnabled()) { + assertThat(args[3], instanceOf(DefaultHostnameVerifier.class)); + } else { + assertThat(args[3], sameInstance(NoopHostnameVerifier.INSTANCE)); + } + return sslStrategy; + }); + + when(builder.sslIOSessionStrategy(Mockito.eq(sslConfig), Mockito.any(SSLContext.class))).thenCallRealMethod(); + + final SslConfiguration config = new SSLService(env).sslConfiguration(settings); + final SSLIOSessionStrategy actual = builder.sslIOSessionStrategy(config, sslContext); + assertThat(actual, sameInstance(sslStrategy)); + } + +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java index bfac286bc3c35..d5b089fe9acfe 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java @@ -10,8 +10,6 @@ import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.concurrent.FutureCallback; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; @@ -60,10 +58,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; @@ -81,6 +77,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItemInArray; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.iterableWithSize; @@ -90,10 +87,6 @@ import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.hamcrest.Matchers.startsWith; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class SSLServiceTests extends ESTestCase { @@ -160,16 +153,16 @@ public void testThatCustomTruststoreCanBeSpecified() throws Exception { .build(); SslConfiguration configuration = SslSettingsLoader.load(customTruststoreSettings, null, env); - SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(configuration, null, -1); + SslProfile profile = sslService.profile("transport.profiles.foo.xpack.security.ssl"); + assertThat(profile.configuration(), equalTo(configuration)); + assertThat(profile.configuration().getDependentFiles(), contains(testClientStore)); + SSLEngine sslEngineWithTruststore = profile.engine(null, -1); assertThat(sslEngineWithTruststore, is(not(nullValue()))); - SslConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine sslEngine = sslService.createSSLEngine(defaultConfig, null, -1); + SslProfile defaultProfile = sslService.profile("xpack.security.transport.ssl"); + SSLEngine sslEngine = defaultProfile.engine(null, -1); assertThat(sslEngineWithTruststore, is(not(sameInstance(sslEngine)))); - - final SslConfiguration profileConfiguration = sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl"); - assertThat(profileConfiguration, notNullValue()); - assertThat(profileConfiguration.getDependentFiles(), contains(testClientStore)); + assertThat(defaultProfile.configuration().getDependentFiles(), contains(testnodeStore)); } public void testThatSslContextCachingWorks() throws Exception { @@ -192,6 +185,12 @@ public void testThatSslContextCachingWorks() throws Exception { final SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); final SSLContext configContext = sslService.sslContext(configuration); assertThat(configContext, is(sameInstance(sslContext))); + + final SslProfile defaultSslProfile = sslService.profile( + randomFrom("xpack.security.transport.ssl", "xpack.security.transport.ssl.") + ); + assertThat(defaultSslProfile, notNullValue()); + assertThat(defaultSslProfile.sslContext(), sameInstance(sslContext)); } public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { @@ -209,8 +208,8 @@ public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { .build(); final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - sslService.createSSLEngine(configuration, null, -1); + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + profile.engine(null, -1); } public void testIncorrectKeyPasswordThrowsException() throws Exception { @@ -226,8 +225,8 @@ public void testIncorrectKeyPasswordThrowsException() throws Exception { .setSecureSettings(secureSettings) .build(); final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - sslService.createSSLEngine(configuration, null, -1); + SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + profile.engine(null, -1); fail("expected an exception"); } catch (ElasticsearchException e) { assertThat(e, throwableWithMessage(startsWith("failed to load SSL configuration [xpack.security.transport.ssl] - "))); @@ -244,17 +243,19 @@ public void testThatSSLv3IsNotEnabled() throws Exception { .put("xpack.security.transport.ssl.key", testnodeKey) .setSecureSettings(secureSettings) .build(); - SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); - assertThat(Arrays.asList(engine.getEnabledProtocols()), not(hasItem("SSLv3"))); + final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); + + final SslProfile profile = sslService.profile("xpack.security.transport.ssl."); + final String[] profileProtocols = profile.engine(null, -1).getEnabledProtocols(); + assertThat(profileProtocols, not(hasItemInArray("SSLv3"))); + assertThat(profileProtocols, hasItemInArray("TLSv1.2")); } public void testThatCreateClientSSLEngineWithoutAnySettingsWorks() throws Exception { SSLService sslService = new SSLService(env); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); - assertThat(sslEngine, notNullValue()); + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + final SSLEngine engine = profile.engine(null, -1); + assertThat(engine, notNullValue()); } public void testThatCreateSSLEngineWithOnlyTruststoreWorks() throws Exception { @@ -266,9 +267,11 @@ public void testThatCreateSSLEngineWithOnlyTruststoreWorks() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.http.ssl"); - SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); + SslProfile profile = sslService.profile("xpack.security.http.ssl"); + SSLEngine sslEngine = profile.engine(null, -1); assertThat(sslEngine, notNullValue()); + + assertThat(sslService.profile("xpack.security.http.ssl.").engine(null, -1), notNullValue()); } public void testCreateWithKeystoreIsValidForServer() throws Exception { @@ -366,6 +369,15 @@ public void testGetVerificationMode() throws Exception { sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl.").verificationMode(), is(SslVerificationMode.FULL) ); + + assertThat( + sslService.profile("xpack.security.transport.ssl").configuration().verificationMode(), + is(SslVerificationMode.CERTIFICATE) + ); + assertThat( + sslService.profile("transport.profiles.foo.xpack.security.ssl").configuration().verificationMode(), + is(SslVerificationMode.FULL) + ); } public void testIsSSLClientAuthEnabled() throws Exception { @@ -453,10 +465,11 @@ public void testCiphersAndInvalidCiphersWork() throws Exception { .putList("xpack.security.transport.ssl.ciphers", ciphers.toArray(new String[ciphers.size()])) .build(); SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); + + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + var engine = profile.engine(null, -1); assertThat(engine, is(notNullValue())); - String[] enabledCiphers = engine.getEnabledCipherSuites(); + var enabledCiphers = engine.getEnabledCipherSuites(); assertThat(Arrays.asList(enabledCiphers), not(contains("foo", "bar"))); } @@ -492,9 +505,11 @@ public void testThatSSLEngineHasCipherSuitesOrderSet() throws Exception { .put("xpack.security.transport.ssl.key", testnodeKey) .setSecureSettings(secureSettings) .build(); + SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); + + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + SSLEngine engine = profile.engine(null, -1); assertThat(engine, is(notNullValue())); assertTrue(engine.getSSLParameters().getUseCipherSuitesOrder()); } @@ -508,10 +523,14 @@ public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Except .put("xpack.security.transport.ssl.key", testnodeKey) .setSecureSettings(secureSettings) .build(); + SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration config = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - final SSLSocketFactory factory = sslService.sslSocketFactory(config); - final String[] ciphers = sslService.supportedCiphers(factory.getSupportedCipherSuites(), config.getCipherSuites(), false); + + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + + final SSLSocketFactory factory = profile.socketFactory(); + final SslConfiguration config = profile.configuration(); + final String[] ciphers = SSLService.supportedCiphers(factory.getSupportedCipherSuites(), config.getCipherSuites(), false); assertThat(factory.getDefaultCipherSuites(), is(ciphers)); final String[] getSupportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); @@ -534,10 +553,11 @@ public void testThatSSLEngineHasProperCiphersAndProtocols() throws Exception { .put("xpack.security.transport.ssl.key", testnodeKey) .setSecureSettings(secureSettings) .build(); - SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SslConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); - final String[] ciphers = sslService.supportedCiphers(engine.getSupportedCipherSuites(), configuration.getCipherSuites(), false); + final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + final SSLEngine engine = profile.engine(null, -1); + final SslConfiguration configuration = profile.configuration(); + final String[] ciphers = SSLService.supportedCiphers(engine.getSupportedCipherSuites(), configuration.getCipherSuites(), false); final String[] getSupportedProtocols = configuration.supportedProtocols().toArray(Strings.EMPTY_ARRAY); assertThat(engine.getEnabledCipherSuites(), is(ciphers)); assertArrayEquals(ciphers, engine.getSSLParameters().getCipherSuites()); @@ -546,58 +566,6 @@ public void testThatSSLEngineHasProperCiphersAndProtocols() throws Exception { assertThat(engine.getSSLParameters().getProtocols(), arrayContainingInAnyOrder(getSupportedProtocols)); } - public void testSSLStrategy() { - // this just exhaustively verifies that the right things are called and that it uses the right parameters - SslVerificationMode mode = randomFrom(SslVerificationMode.values()); - Settings settings = Settings.builder() - .put("supported_protocols", "protocols") - .put("cipher_suites", "INVALID_CIPHER") - .put("verification_mode", mode.name()) - .build(); - SSLService sslService = mock(SSLService.class); - SslConfiguration sslConfig = SslSettingsLoader.load(settings, null, env); - SSLParameters sslParameters = mock(SSLParameters.class); - SSLContext sslContext = mock(SSLContext.class); - String[] protocols = new String[] { "protocols" }; - String[] ciphers = new String[] { "ciphers!!!" }; - String[] supportedCiphers = new String[] { "supported ciphers" }; - List requestedCiphers = List.of("INVALID_CIPHER"); - SSLIOSessionStrategy sslStrategy = mock(SSLIOSessionStrategy.class); - - when(sslService.sslConfiguration(settings)).thenReturn(sslConfig); - when(sslService.sslContext(sslConfig)).thenReturn(sslContext); - when(sslService.supportedCiphers(any(String[].class), anyList(), any(Boolean.TYPE))).thenAnswer(inv -> { - final Object[] args = inv.getArguments(); - assertThat(args[0], is(supportedCiphers)); - assertThat(args[1], is(requestedCiphers)); - assertThat(args[2], is(false)); - return ciphers; - }); - when(sslService.sslParameters(sslContext)).thenReturn(sslParameters); - when(sslParameters.getCipherSuites()).thenReturn(supportedCiphers); - - when(sslService.sslIOSessionStrategy(any(SSLContext.class), any(String[].class), any(String[].class), any(HostnameVerifier.class))) - .thenAnswer(inv -> { - final Object[] args = inv.getArguments(); - assertThat(args[0], is(sslContext)); - assertThat(args[1], is(protocols)); - assertThat(args[2], is(ciphers)); - if (mode.isHostnameVerificationEnabled()) { - assertThat(args[3], instanceOf(DefaultHostnameVerifier.class)); - } else { - assertThat(args[3], sameInstance(NoopHostnameVerifier.INSTANCE)); - } - return sslStrategy; - }); - - // ensure it actually goes through and calls the real method - when(sslService.sslIOSessionStrategy(settings)).thenCallRealMethod(); - when(sslService.sslIOSessionStrategy(sslConfig)).thenCallRealMethod(); - - final SSLIOSessionStrategy actual = sslService.sslIOSessionStrategy(settings); - assertThat(actual, sameInstance(sslStrategy)); - } - public void testGetConfigurationByContextName() throws Exception { assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm()); final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); @@ -644,6 +612,8 @@ public void testGetConfigurationByContextName() throws Exception { assertThat("KeyStore Path for " + name, keyConfig.getDependentFiles(), contains(testnodeStore)); assertThat("Cipher for " + name, configuration.getCipherSuites(), contains(getCipherSuites[i])); assertThat("Configuration for " + name + ".", sslService.getSSLConfiguration(name + "."), sameInstance(configuration)); + + assertThat(sslService.profile(name).configuration(), sameInstance(configuration)); } } @@ -893,13 +863,17 @@ public int getSessionCacheSize() { @Network public void testThatSSLContextWithoutSettingsWorks() throws Exception { - SSLService sslService = new SSLService(env); - SSLContext sslContext = sslService.sslContext(sslService.sslConfiguration(Settings.EMPTY)); - try (CloseableHttpClient client = HttpClients.custom().setSSLContext(sslContext).build()) { - // Execute a GET on a site known to have a valid certificate signed by a trusted public CA - // This will result in an SSLHandshakeException if the SSLContext does not trust the CA, but the default - // truststore trusts all common public CAs so the handshake will succeed - privilegedConnect(() -> client.execute(new HttpGet("https://www.elastic.co/")).close()); + final SSLService sslService = new SSLService(env); + final SSLContext sslContext1 = sslService.sslContext(sslService.sslConfiguration(Settings.EMPTY)); + final SSLContext sslContext2 = sslService.profile("xpack.http.ssl").sslContext(); + + for (var sslContext : List.of(sslContext1, sslContext2)) { + try (CloseableHttpClient client = HttpClients.custom().setSSLContext(sslContext).build()) { + // Execute a GET on a site known to have a valid certificate signed by a trusted public CA + // This will result in an SSLHandshakeException if the SSLContext does not trust the CA, but the default + // truststore trusts all common public CAs so the handshake will succeed + privilegedConnect(() -> client.execute(new HttpGet("https://www.elastic.co/")).close()); + } } } @@ -923,9 +897,9 @@ public void testThatSSLContextTrustsJDKTrustedCAs() throws Exception { @Network public void testThatSSLIOSessionStrategyWithoutSettingsWorks() throws Exception { SSLService sslService = new SSLService(env); - SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - logger.info("SSL Configuration: {}", sslConfiguration); - SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(sslConfiguration); + SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + logger.info("SSL Configuration: {}", profile.configuration()); + SSLIOSessionStrategy sslStrategy = profile.ioSessionStrategy4(); try (CloseableHttpAsyncClient client = getAsyncHttpClient(sslStrategy)) { client.start(); @@ -945,7 +919,8 @@ public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { .setSecureSettings(secureSettings) .build(); final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(sslService.getSSLConfiguration("xpack.security.transport.ssl")); + final SslProfile profile = sslService.profile("xpack.security.transport.ssl"); + final SSLIOSessionStrategy sslStrategy = profile.ioSessionStrategy4(); try (CloseableHttpAsyncClient client = getAsyncHttpClient(sslStrategy)) { client.start(); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/HttpClientManager.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/HttpClientManager.java index ddf19ff0dc96f..eb651cd277008 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/HttpClientManager.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/HttpClientManager.java @@ -117,10 +117,8 @@ public static HttpClientManager create( TimeValue connectionTtl ) { // Set the sslStrategy to ensure an encrypted connection, as Elastic Inference Service requires it. - SSLIOSessionStrategy sslioSessionStrategy = sslService.sslIOSessionStrategy( - sslService.getSSLConfiguration(ELASTIC_INFERENCE_SERVICE_SSL_CONFIGURATION_PREFIX) - ); - + final SSLIOSessionStrategy sslioSessionStrategy = sslService.profile(ELASTIC_INFERENCE_SERVICE_SSL_CONFIGURATION_PREFIX) + .ioSessionStrategy4(); PoolingNHttpClientConnectionManager connectionManager = createConnectionManager(sslioSessionStrategy, connectionTtl); return new HttpClientManager(settings, connectionManager, threadPool, clusterService, throttlerManager); } diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java index ef777cd7806a4..8444856f81f1d 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporter.java @@ -39,6 +39,7 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.monitoring.Monitoring; import org.elasticsearch.xpack.monitoring.MonitoringTemplateRegistry; import org.elasticsearch.xpack.monitoring.exporter.ClusterAlertsUtil; @@ -758,8 +759,8 @@ private static SSLIOSessionStrategy configureSslStrategy( // This configuration uses secure settings. We cannot load a new SSL strategy, as the secure settings have already been closed. // Due to #registerSettingValidators we know that the settings not been dynamically updated, and the pre-configured strategy // is still the correct configuration for use in this exporter. - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(concreteSetting.getKey()); - sslStrategy = sslService.sslIOSessionStrategy(sslConfiguration); + final SslProfile profile = sslService.profile(concreteSetting.getKey()); + sslStrategy = profile.ioSessionStrategy4(); } return sslStrategy; } diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java index a4453521ffb44..03c000679c9d4 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java @@ -19,7 +19,6 @@ import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.core.Strings; import org.elasticsearch.env.TestEnvironment; @@ -27,6 +26,7 @@ import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.io.InputStreamReader; import java.net.InetSocketAddress; @@ -80,14 +80,11 @@ public void testThatConnectionToHTTPWorks() throws Exception { AuthScope.ANY, new UsernamePasswordCredentials(nodeClientUsername(), new String(nodeClientPassword().getChars())) ); - SslConfiguration sslConfiguration = service.getSSLConfiguration("xpack.security.http.ssl"); + SslProfile sslProfile = service.profile("xpack.security.http.ssl"); try ( CloseableHttpClient client = HttpClients.custom() .setSSLSocketFactory( - new SSLConnectionSocketFactory( - service.sslSocketFactory(sslConfiguration), - SSLConnectionSocketFactory.getDefaultHostnameVerifier() - ) + new SSLConnectionSocketFactory(sslProfile.socketFactory(), SSLConnectionSocketFactory.getDefaultHostnameVerifier()) ) .setDefaultCredentialsProvider(provider) .build(); diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java index 9d72b9eb5c526..ca93009ece211 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java @@ -9,12 +9,12 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.settings.MockSecureSettings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.io.IOException; import java.net.SocketException; @@ -112,8 +112,8 @@ public void testThatSSLConfigurationReloadsOnModification() throws Exception { .build(); String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(TestEnvironment.newEnvironment(settings)); - SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); + SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + SSLSocketFactory sslSocketFactory = sslProfile.socketFactory(); TransportAddress address = internalCluster().getInstance(Transport.class, node).boundAddress().publishAddress(); // Fails as our nodes do not trust testnode_updated.crt try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) { diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java index e11219bf6f93d..6f8ace3fb06b2 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java @@ -9,7 +9,6 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.ssl.PemUtils; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.core.PathUtils; import org.elasticsearch.core.TimeValue; @@ -22,6 +21,7 @@ import org.elasticsearch.xpack.core.ssl.CertParsingUtils; import org.elasticsearch.xpack.core.ssl.RestrictedTrustManager; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -243,8 +243,8 @@ private void tryConnect(CertificateInfo certificate, boolean shouldFail) throws String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(TestEnvironment.newEnvironment(settings)); - SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); + SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + SSLSocketFactory sslSocketFactory = sslProfile.socketFactory(); TransportAddress address = internalCluster().getInstance(Transport.class, node).boundAddress().publishAddress(); try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) { assertThat(socket.isConnected(), is(true)); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurations.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurations.java index 77127d2bd8e52..f1cb4a6d60d01 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurations.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurations.java @@ -11,6 +11,7 @@ import org.elasticsearch.transport.TransportSettings; import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.util.HashMap; import java.util.Map; @@ -73,12 +74,12 @@ private ProfileConfigurations() {} * as an entry for the "default" profile. If the remote_cluster feature is enabled, it also * contains an entry for the synthetic "_remote_cluster" profile. */ - public static Map get(Settings settings, SSLService sslService, boolean sslEnabledOnly) { + public static Map get(Settings settings, SSLService sslService, boolean sslEnabledOnly) { final boolean transportSslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings); final boolean remoteClusterPortEnabled = REMOTE_CLUSTER_SERVER_ENABLED.get(settings); final boolean remoteClusterServerSslEnabled = remoteClusterPortEnabled && REMOTE_CLUSTER_SERVER_SSL_ENABLED.get(settings); - final Map profileConfigurations = new HashMap<>(); + final Map profileConfigurations = new HashMap<>(); if (sslEnabledOnly) { if (transportSslEnabled == false && remoteClusterServerSslEnabled == false) { @@ -87,10 +88,8 @@ public static Map get(Settings settings, SSLService ss // The single TRANSPORT_SSL_ENABLED setting determines whether SSL is enabled for both // the default transport profile and any custom transport profiles. That is, SSL is // always either enabled or disabled together for default and custom transport profiles. - profileConfigurations.put( - REMOTE_CLUSTER_PROFILE, - sslService.getSSLConfiguration(XPackSettings.REMOTE_CLUSTER_SERVER_SSL_PREFIX) - ); + final SslProfile profile = getSslProfile(sslService, XPackSettings.REMOTE_CLUSTER_SERVER_SSL_PREFIX); + profileConfigurations.put(REMOTE_CLUSTER_PROFILE, profile); return profileConfigurations; } else if (remoteClusterServerSslEnabled == false) { populateFromTransportProfiles(settings, sslService, profileConfigurations); @@ -103,10 +102,7 @@ public static Map get(Settings settings, SSLService ss populateFromTransportProfiles(settings, sslService, profileConfigurations); if (remoteClusterPortEnabled) { assert profileConfigurations.containsKey(REMOTE_CLUSTER_PROFILE) == false; - profileConfigurations.put( - REMOTE_CLUSTER_PROFILE, - sslService.getSSLConfiguration(XPackSettings.REMOTE_CLUSTER_SERVER_SSL_PREFIX) - ); + profileConfigurations.put(REMOTE_CLUSTER_PROFILE, getSslProfile(sslService, XPackSettings.REMOTE_CLUSTER_SERVER_SSL_PREFIX)); } return profileConfigurations; @@ -115,9 +111,9 @@ public static Map get(Settings settings, SSLService ss private static void populateFromTransportProfiles( Settings settings, SSLService sslService, - Map profileConfigurations + Map profileConfigurations ) { - final SslConfiguration defaultConfiguration = sslService.getSSLConfiguration(setting("transport.ssl.")); + final SslProfile defaultProfile = getSslProfile(sslService, setting("transport.ssl.")); Set profileNames = settings.getGroups("transport.profiles.", true).keySet(); for (String profileName : profileNames) { @@ -136,11 +132,18 @@ private static void populateFromTransportProfiles( } } - SslConfiguration configuration = sslService.getSSLConfiguration("transport.profiles." + profileName + "." + setting("ssl")); - profileConfigurations.put(profileName, configuration); + final SslProfile profile = getSslProfile(sslService, "transport.profiles." + profileName + "." + setting("ssl")); + profileConfigurations.put(profileName, profile); } assert profileConfigurations.containsKey(TransportSettings.DEFAULT_PROFILE) == false; - profileConfigurations.put(TransportSettings.DEFAULT_PROFILE, defaultConfiguration); + profileConfigurations.put(TransportSettings.DEFAULT_PROFILE, defaultProfile); } + + private static SslProfile getSslProfile(final SSLService sslService, final String profileName) { + final SslProfile profile = sslService.profile(profileName); + assert profile != null : "Null Ssl profile for [" + profileName + "] (is [" + sslService + "] a mock?)"; + return profile; + } + } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java index fa16de22c865c..2e527dba980b9 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java @@ -24,7 +24,6 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.util.PageCacheRecycler; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -47,6 +46,7 @@ import org.elasticsearch.xpack.core.security.transport.ProfileConfigurations; import org.elasticsearch.xpack.core.security.transport.SecurityTransportExceptionHandler; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.authc.CrossClusterAccessAuthenticationService; import java.net.InetSocketAddress; @@ -73,11 +73,11 @@ public class SecurityNetty4Transport extends Netty4Transport { private final SecurityTransportExceptionHandler exceptionHandler; private final SSLService sslService; - private final SslConfiguration defaultSslConfiguration; - private final Map profileConfigurations; + private final SslProfile defaultSslProfile; + private final Map profiles; private final boolean transportSslEnabled; private final boolean remoteClusterServerSslEnabled; - private final SslConfiguration remoteClusterClientSslConfiguration; + private final SslProfile remoteClusterClientSslProfile; private final RemoteClusterClientBootstrapOptions remoteClusterClientBootstrapOptions; private final CrossClusterAccessAuthenticationService crossClusterAccessAuthenticationService; @@ -108,16 +108,16 @@ public SecurityNetty4Transport( this.sslService = sslService; this.transportSslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings); this.remoteClusterServerSslEnabled = REMOTE_CLUSTER_SERVER_SSL_ENABLED.get(settings); - this.profileConfigurations = Collections.unmodifiableMap(ProfileConfigurations.get(settings, sslService, true)); - this.defaultSslConfiguration = this.profileConfigurations.get(TransportSettings.DEFAULT_PROFILE); - assert this.transportSslEnabled == false || this.defaultSslConfiguration != null; + this.profiles = Collections.unmodifiableMap(ProfileConfigurations.get(settings, sslService, true)); + this.defaultSslProfile = this.profiles.get(TransportSettings.DEFAULT_PROFILE); + assert this.transportSslEnabled == false || this.defaultSslProfile != null; // Client configuration does not depend on whether the remote access port is enabled if (REMOTE_CLUSTER_CLIENT_SSL_ENABLED.get(settings)) { - this.remoteClusterClientSslConfiguration = sslService.getSSLConfiguration(REMOTE_CLUSTER_CLIENT_SSL_PREFIX); - assert this.remoteClusterClientSslConfiguration != null; + this.remoteClusterClientSslProfile = sslService.profile(REMOTE_CLUSTER_CLIENT_SSL_PREFIX); + assert this.remoteClusterClientSslProfile != null; } else { - this.remoteClusterClientSslConfiguration = null; + this.remoteClusterClientSslProfile = null; } this.remoteClusterClientBootstrapOptions = RemoteClusterClientBootstrapOptions.fromSettings(settings); } @@ -131,20 +131,20 @@ protected void doStart() { public final ChannelHandler getServerChannelInitializer(String name) { if (remoteClusterPortEnabled && REMOTE_CLUSTER_PROFILE.equals(name)) { if (remoteClusterServerSslEnabled) { - final SslConfiguration remoteClusterSslConfiguration = profileConfigurations.get(name); - if (remoteClusterSslConfiguration == null) { + final SslProfile remoteClusterSslProfile = profiles.get(name); + if (remoteClusterSslProfile == null) { throw new IllegalStateException("remote cluster SSL is enabled but no configuration is found"); } - return getSslChannelInitializer(name, remoteClusterSslConfiguration); + return getSslChannelInitializer(name, remoteClusterSslProfile); } else { return getNoSslChannelInitializer(name); } } else if (transportSslEnabled) { - SslConfiguration configuration = profileConfigurations.get(name); - if (configuration == null) { + SslProfile profile = profiles.get(name); + if (profile == null) { throw new IllegalStateException("unknown profile: " + name); } - return getSslChannelInitializer(name, configuration); + return getSslChannelInitializer(name, profile); } else { return getNoSslChannelInitializer(name); } @@ -228,27 +228,27 @@ public void onException(TcpChannel channel, Exception e) { } public class SslChannelInitializer extends ServerChannelInitializer { - private final SslConfiguration configuration; + private final SslProfile profile; - public SslChannelInitializer(String name, SslConfiguration configuration) { + public SslChannelInitializer(String name, SslProfile profile) { super(name); - this.configuration = configuration; + this.profile = profile; } @Override protected void initChannel(Channel ch) throws Exception { - SSLEngine serverEngine = sslService.createSSLEngine(configuration, null, -1); + SSLEngine serverEngine = profile.engine(null, -1); serverEngine.setUseClientMode(false); final SslHandler sslHandler = new SslHandler(serverEngine); - sslHandler.setHandshakeTimeoutMillis(configuration.handshakeTimeoutMillis()); + sslHandler.setHandshakeTimeoutMillis(profile.configuration().handshakeTimeoutMillis()); ch.pipeline().addFirst("sslhandler", sslHandler); super.initChannel(ch); assert ch.pipeline().first() == sslHandler : "SSL handler must be first handler in pipeline"; } } - protected ServerChannelInitializer getSslChannelInitializer(final String name, final SslConfiguration configuration) { - return new SslChannelInitializer(name, configuration); + protected ServerChannelInitializer getSslChannelInitializer(final String name, final SslProfile profile) { + return new SslChannelInitializer(name, profile); } @Override @@ -260,7 +260,7 @@ private class SecurityClientChannelInitializer extends ClientChannelInitializer private final boolean hostnameVerificationEnabled; private final SNIHostName serverName; - private final SslConfiguration channelSslConfiguration; + private final SslProfile channelSslProfile; SecurityClientChannelInitializer(DiscoveryNode node, ConnectionProfile connectionProfile) { final String transportProfile = connectionProfile.getTransportProfile(); @@ -268,13 +268,15 @@ private class SecurityClientChannelInitializer extends ClientChannelInitializer // Only client connections to a new RCS remote cluster can have transport profile of _remote_cluster // All other client connections use the default transport profile regardless of the transport profile used on the server side. if (REMOTE_CLUSTER_PROFILE.equals(transportProfile)) { - this.channelSslConfiguration = remoteClusterClientSslConfiguration; + this.channelSslProfile = remoteClusterClientSslProfile; } else { assert TransportSettings.DEFAULT_PROFILE.equals(transportProfile); - this.channelSslConfiguration = defaultSslConfiguration; + this.channelSslProfile = defaultSslProfile; } - if (this.channelSslConfiguration != null) { - this.hostnameVerificationEnabled = this.channelSslConfiguration.verificationMode().isHostnameVerificationEnabled(); + if (this.channelSslProfile != null) { + this.hostnameVerificationEnabled = this.channelSslProfile.configuration() + .verificationMode() + .isHostnameVerificationEnabled(); } else { this.hostnameVerificationEnabled = false; } @@ -293,11 +295,9 @@ private class SecurityClientChannelInitializer extends ClientChannelInitializer @Override protected void initChannel(Channel ch) throws Exception { super.initChannel(ch); - if (channelSslConfiguration != null) { + if (channelSslProfile != null) { ch.pipeline() - .addFirst( - new ClientSslHandlerInitializer(channelSslConfiguration, sslService, hostnameVerificationEnabled, serverName) - ); + .addFirst(new ClientSslHandlerInitializer(channelSslProfile, sslService, hostnameVerificationEnabled, serverName)); } } } @@ -305,17 +305,17 @@ protected void initChannel(Channel ch) throws Exception { private static class ClientSslHandlerInitializer extends ChannelOutboundHandlerAdapter { private final boolean hostnameVerificationEnabled; - private final SslConfiguration sslConfiguration; + private final SslProfile sslProfile; private final SSLService sslService; private final SNIServerName serverName; private ClientSslHandlerInitializer( - SslConfiguration sslConfiguration, + SslProfile sslProfile, SSLService sslService, boolean hostnameVerificationEnabled, SNIServerName serverName ) { - this.sslConfiguration = sslConfiguration; + this.sslProfile = sslProfile; this.hostnameVerificationEnabled = hostnameVerificationEnabled; this.sslService = sslService; this.serverName = serverName; @@ -328,9 +328,9 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, Sock if (hostnameVerificationEnabled) { InetSocketAddress inetSocketAddress = (InetSocketAddress) remoteAddress; // we create the socket based on the name given. don't reverse DNS - sslEngine = sslService.createSSLEngine(sslConfiguration, inetSocketAddress.getHostString(), inetSocketAddress.getPort()); + sslEngine = sslProfile.engine(inetSocketAddress.getHostString(), inetSocketAddress.getPort()); } else { - sslEngine = sslService.createSSLEngine(sslConfiguration, null, -1); + sslEngine = sslProfile.engine(null, -1); } sslEngine.setUseClientMode(true); @@ -341,7 +341,7 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, Sock } final ChannelPromise connectPromise = ctx.newPromise(); final SslHandler sslHandler = new SslHandler(sslEngine); - sslHandler.setHandshakeTimeoutMillis(sslConfiguration.handshakeTimeoutMillis()); + sslHandler.setHandshakeTimeoutMillis(sslProfile.configuration().handshakeTimeoutMillis()); ctx.pipeline().replace(this, "ssl", sslHandler); final Future handshakePromise = sslHandler.handshakeFuture(); Netty4Utils.addListener(connectPromise, result -> { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java index 0571ee831fe91..389622118832b 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -222,6 +222,7 @@ import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.core.ssl.TransportTLSBootstrapCheck; import org.elasticsearch.xpack.core.ssl.action.GetCertificateInfoAction; import org.elasticsearch.xpack.core.ssl.action.TransportGetCertificateInfoAction; @@ -2042,10 +2043,11 @@ public boolean test(String profile, InetSocketAddress peerAddress) { httpTransports.put(SecurityField.NAME4, () -> { final boolean ssl = HTTP_SSL_ENABLED.get(settings); final SSLService sslService = getSslService(); - final SslConfiguration sslConfiguration; final BiConsumer populateClientCertificate; + final TLSConfig tlsConfig; if (ssl) { - sslConfiguration = sslService.getHttpTransportSSLConfiguration(); + final SslProfile sslProfile = sslService.profile(XPackSettings.HTTP_SSL_PREFIX); + final SslConfiguration sslConfiguration = sslProfile.configuration(); if (SSLService.isConfigurationValidForServerUsage(sslConfiguration) == false) { throw new IllegalArgumentException( "a key must be provided to run as a server. the key should be configured using the " @@ -2057,8 +2059,9 @@ public boolean test(String profile, InetSocketAddress peerAddress) { } else { populateClientCertificate = (channel, threadContext) -> {}; } + tlsConfig = new TLSConfig(sslProfile::engine); } else { - sslConfiguration = null; + tlsConfig = TLSConfig.noTLS(); populateClientCertificate = (channel, threadContext) -> {}; } final AuthenticationService authenticationService = this.authcService.get(); @@ -2072,7 +2075,7 @@ public boolean test(String profile, InetSocketAddress peerAddress) { clusterSettings, getNettySharedGroupFactory(settings), telemetryProvider, - new TLSConfig(sslConfiguration, sslService::createSSLEngine), + tlsConfig, acceptPredicate, (httpRequest, channel, listener) -> { HttpPreRequest httpPreRequest = HttpHeadersAuthenticatorUtils.asHttpPreRequest(httpRequest); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/jwt/JwtUtil.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/jwt/JwtUtil.java index 02b2a3dfbe312..5a8127e7e6a36 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/jwt/JwtUtil.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/jwt/JwtUtil.java @@ -44,7 +44,6 @@ import org.elasticsearch.common.settings.RotatableSecret; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.SettingsException; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; import org.elasticsearch.xcontent.XContentBuilder; @@ -53,6 +52,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.jwt.JwtRealmSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.io.IOException; import java.io.InputStream; @@ -273,11 +273,13 @@ public static CloseableHttpAsyncClient createHttpClient(final RealmConfig realmC return AccessController.doPrivileged((PrivilegedExceptionAction) () -> { final ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(); final String sslKey = RealmSettings.realmSslPrefix(realmConfig.identifier()); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(sslKey); - final SSLContext clientContext = sslService.sslContext(sslConfiguration); - final HostnameVerifier verifier = SSLService.getHostnameVerifier(sslConfiguration); + + final SslProfile sslProfile = sslService.profile(sslKey); + final SSLContext clientContext = sslProfile.sslContext(); + final HostnameVerifier verifier = sslProfile.hostnameVerifier(); final Registry registry = RegistryBuilder.create() .register("http", NoopIOSessionStrategy.INSTANCE) + // TODO: Should this use profile.ioSessionStrategy4 ? .register("https", new SSLIOSessionStrategy(clientContext, verifier)) .build(); final PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, registry); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactory.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactory.java index b5e1343382b05..40b62935b158f 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactory.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactory.java @@ -27,6 +27,7 @@ import org.elasticsearch.xpack.core.security.authc.ldap.support.SessionFactorySettings; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.support.ReloadableSecurityComponent; import java.io.Closeable; @@ -213,9 +214,9 @@ private ServerSet serverSet(RealmConfig realmConfig, SSLService clientSSLService SocketFactory socketFactory = null; if (ldapServers.ssl()) { final String sslKey = RealmSettings.realmSslPrefix(config.identifier()); - final SslConfiguration ssl = clientSSLService.getSSLConfiguration(sslKey); - socketFactory = clientSSLService.sslSocketFactory(ssl); - if (ssl.verificationMode().isHostnameVerificationEnabled()) { + final SslProfile ssl = clientSSLService.profile(sslKey); + socketFactory = ssl.socketFactory(); + if (ssl.configuration().verificationMode().isHostnameVerificationEnabled()) { logger.debug("using encryption for LDAP connections with hostname verification"); } else { logger.debug("using encryption for LDAP connections without hostname verification"); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticator.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticator.java index 4bf93fc10e96c..2b01e17f25e48 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticator.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectAuthenticator.java @@ -80,7 +80,6 @@ import org.elasticsearch.SpecialPermission; import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.util.concurrent.ListenableFuture; import org.elasticsearch.core.CheckedRunnable; import org.elasticsearch.core.Nullable; @@ -93,6 +92,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.oidc.OpenIdConnectRealmSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.PrivilegedFileWatcher; import org.elasticsearch.xpack.security.authc.jwt.JwtUtil; @@ -707,11 +707,12 @@ private CloseableHttpAsyncClient createHttpClient() { IOReactorConfig.custom().setSoKeepAlive(realmConfig.getSetting(HTTP_TCP_KEEP_ALIVE)).build() ); final String sslKey = RealmSettings.realmSslPrefix(realmConfig.identifier()); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(sslKey); - final SSLContext clientContext = sslService.sslContext(sslConfiguration); - final HostnameVerifier verifier = SSLService.getHostnameVerifier(sslConfiguration); + final SslProfile sslProfile = sslService.profile(sslKey); + final SSLContext clientContext = sslProfile.sslContext(); + final HostnameVerifier verifier = sslProfile.hostnameVerifier(); Registry registry = RegistryBuilder.create() .register("http", NoopIOSessionStrategy.INSTANCE) + // TODO: Should this use profile.ioSessionStrategy4 ? .register("https", new SSLIOSessionStrategy(clientContext, verifier)) .build(); PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, registry); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java index e5c3b04e2707b..2bde993b71996 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/saml/SamlRealm.java @@ -24,7 +24,6 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.SettingsException; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.ssl.SslKeyConfig; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -50,6 +49,7 @@ import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.ssl.CertParsingUtils; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.PrivilegedFileWatcher; import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.TokenService; @@ -111,7 +111,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.X509KeyManager; import static org.elasticsearch.common.Strings.collectionToCommaDelimitedString; @@ -717,9 +716,8 @@ private static Tuple TransportRequestHandler interceptHandler( } private Map initializeProfileFilters(DestructiveOperations destructiveOperations) { - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, false); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, false); Map profileFilters = Maps.newMapWithExpectedSize(profileConfigurations.size() + 1); @@ -490,9 +491,11 @@ private Map initializeProfileFilters(DestructiveO final boolean remoteClusterPortEnabled = REMOTE_CLUSTER_SERVER_ENABLED.get(settings); final boolean remoteClusterServerSSLEnabled = XPackSettings.REMOTE_CLUSTER_SERVER_SSL_ENABLED.get(settings); - for (Map.Entry entry : profileConfigurations.entrySet()) { - final SslConfiguration profileConfiguration = entry.getValue(); + for (Map.Entry entry : profileConfigurations.entrySet()) { final String profileName = entry.getKey(); + final SslProfile sslProfile = entry.getValue(); + final SslConfiguration profileConfiguration = sslProfile.configuration(); + assert profileConfiguration != null : "Ssl Profile [" + sslProfile + "] for [" + profileName + "] has a null configuration"; final boolean useRemoteClusterProfile = remoteClusterPortEnabled && profileName.equals(REMOTE_CLUSTER_PROFILE); if (useRemoteClusterProfile) { profileFilters.put( diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransport.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransport.java index d851705e5bdd9..6dae043235f99 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransport.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransport.java @@ -13,7 +13,6 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.util.PageCacheRecycler; import org.elasticsearch.core.Nullable; import org.elasticsearch.indices.breaker.CircuitBreakerService; @@ -21,6 +20,7 @@ import org.elasticsearch.transport.netty4.SharedGroupFactory; import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.authc.CrossClusterAccessAuthenticationService; import org.elasticsearch.xpack.security.transport.filter.IPFilter; @@ -71,8 +71,8 @@ protected ChannelHandler getNoSslChannelInitializer(final String name) { } @Override - protected ServerChannelInitializer getSslChannelInitializer(final String name, final SslConfiguration configuration) { - return new SecurityServerChannelInitializer(name, configuration); + protected ServerChannelInitializer getSslChannelInitializer(final String name, final SslProfile profile) { + return new SecurityServerChannelInitializer(name, profile); } public class IPFilterServerChannelInitializer extends ServerChannelInitializer { @@ -90,8 +90,8 @@ protected void initChannel(final Channel ch) throws Exception { public class SecurityServerChannelInitializer extends SslChannelInitializer { - SecurityServerChannelInitializer(final String name, final SslConfiguration configuration) { - super(name, configuration); + SecurityServerChannelInitializer(final String name, final SslProfile profile) { + super(name, profile); } @Override diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java index 7c0d4154b9623..058a0f65f4e72 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java @@ -16,6 +16,7 @@ import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.hamcrest.Matchers; import java.nio.file.Path; @@ -39,12 +40,12 @@ public void testGetSecureTransportProfileConfigurations() { final Environment env = TestEnvironment.newEnvironment(settings); SSLService sslService = new SSLService(env); final SslConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); assertThat(profileConfigurations.size(), Matchers.equalTo(3)); assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("full", "cert", "default")); - assertThat(profileConfigurations.get("full").verificationMode(), Matchers.equalTo(SslVerificationMode.FULL)); - assertThat(profileConfigurations.get("cert").verificationMode(), Matchers.equalTo(SslVerificationMode.CERTIFICATE)); - assertThat(profileConfigurations.get("default"), Matchers.sameInstance(defaultConfig)); + assertThat(profileConfigurations.get("full").configuration().verificationMode(), Matchers.equalTo(SslVerificationMode.FULL)); + assertThat(profileConfigurations.get("cert").configuration().verificationMode(), Matchers.equalTo(SslVerificationMode.CERTIFICATE)); + assertThat(profileConfigurations.get("default").configuration(), Matchers.sameInstance(defaultConfig)); } public void testGetInsecureTransportProfileConfigurations() { @@ -56,11 +57,11 @@ public void testGetInsecureTransportProfileConfigurations() { final Environment env = TestEnvironment.newEnvironment(settings); SSLService sslService = new SSLService(env); final SslConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); assertThat(profileConfigurations.size(), Matchers.equalTo(2)); assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("none", "default")); - assertThat(profileConfigurations.get("none").verificationMode(), Matchers.equalTo(SslVerificationMode.NONE)); - assertThat(profileConfigurations.get("default"), Matchers.sameInstance(defaultConfig)); + assertThat(profileConfigurations.get("none").configuration().verificationMode(), Matchers.equalTo(SslVerificationMode.NONE)); + assertThat(profileConfigurations.get("default").configuration(), Matchers.sameInstance(defaultConfig)); } public void testTransportAndRemoteClusterSslCanBeEnabledIndependently() { @@ -81,27 +82,33 @@ public void testTransportAndRemoteClusterSslCanBeEnabledIndependently() { .build(); final Environment env = TestEnvironment.newEnvironment(settings); SSLService sslService = new SSLService(env); - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); if (transportSslEnabled && remoteClusterServerSslEnabled) { assertThat(profileConfigurations.size(), Matchers.equalTo(2)); assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("default", "_remote_cluster")); - assertThat(profileConfigurations.get("_remote_cluster").verificationMode(), Matchers.equalTo(SslVerificationMode.CERTIFICATE)); assertThat( - profileConfigurations.get("default"), + profileConfigurations.get("_remote_cluster").configuration().verificationMode(), + Matchers.equalTo(SslVerificationMode.CERTIFICATE) + ); + assertThat( + profileConfigurations.get("default").configuration(), Matchers.sameInstance(sslService.getSSLConfiguration("xpack.security.transport.ssl")) ); } else if (transportSslEnabled) { assertThat(profileConfigurations.size(), Matchers.equalTo(1)); assertThat(profileConfigurations.keySet(), contains("default")); assertThat( - profileConfigurations.get("default"), + profileConfigurations.get("default").configuration(), Matchers.sameInstance(sslService.getSSLConfiguration("xpack.security.transport.ssl")) ); } else if (remoteClusterServerSslEnabled) { assertThat(profileConfigurations.size(), Matchers.equalTo(1)); assertThat(profileConfigurations.keySet(), contains("_remote_cluster")); - assertThat(profileConfigurations.get("_remote_cluster").verificationMode(), Matchers.equalTo(SslVerificationMode.CERTIFICATE)); + assertThat( + profileConfigurations.get("_remote_cluster").configuration().verificationMode(), + Matchers.equalTo(SslVerificationMode.CERTIFICATE) + ); } else { assertThat(profileConfigurations, anEmptyMap()); } @@ -123,11 +130,11 @@ public void testNoProfileConfigurationForRemoteClusterIfFeatureIsDisabled() { .build(); final Environment env = TestEnvironment.newEnvironment(settings); SSLService sslService = new SSLService(env); - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, true); assertThat(profileConfigurations.size(), Matchers.equalTo(1)); assertThat(profileConfigurations.keySet(), contains("default")); assertThat( - profileConfigurations.get("default"), + profileConfigurations.get("default").configuration(), Matchers.sameInstance(sslService.getSSLConfiguration("xpack.security.transport.ssl")) ); } @@ -150,20 +157,23 @@ public void testGetProfileConfigurationsIrrespectiveToSslEnabled() { .build(); final Environment env = TestEnvironment.newEnvironment(settings); SSLService sslService = new SSLService(env); - final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, false); + final Map profileConfigurations = ProfileConfigurations.get(settings, sslService, false); if (remoteClusterPortEnabled) { assertThat(profileConfigurations.size(), Matchers.equalTo(3)); assertThat(profileConfigurations.keySet(), containsInAnyOrder("default", "client", "_remote_cluster")); - assertThat(profileConfigurations.get("_remote_cluster").verificationMode(), is(SslVerificationMode.CERTIFICATE)); + assertThat( + profileConfigurations.get("_remote_cluster").configuration().verificationMode(), + is(SslVerificationMode.CERTIFICATE) + ); } else { assertThat(profileConfigurations.size(), Matchers.equalTo(2)); assertThat(profileConfigurations.keySet(), containsInAnyOrder("default", "client")); } assertThat( - profileConfigurations.get("default"), + profileConfigurations.get("default").configuration(), Matchers.sameInstance(sslService.getSSLConfiguration("xpack.security.transport.ssl")) ); - assertThat(profileConfigurations.get("client").clientAuth(), is(SslClientAuthenticationMode.NONE)); + assertThat(profileConfigurations.get("client").configuration().clientAuth(), is(SslClientAuthenticationMode.NONE)); } private Settings.Builder getBaseSettings() { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapTestUtils.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapTestUtils.java index 6ae24b112d90c..7b8321f11200f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapTestUtils.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapTestUtils.java @@ -13,12 +13,12 @@ import org.apache.lucene.tests.util.LuceneTestCase; import org.elasticsearch.common.settings.MockSecureSettings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.ssl.SslVerificationMode; import org.elasticsearch.core.TimeValue; import org.elasticsearch.env.Environment; import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.authc.ldap.support.LdapUtils; import java.nio.file.Path; @@ -56,16 +56,9 @@ public static LDAPConnection openConnection(String url, String bindDN, String bi options.setConnectTimeoutMillis(Math.toIntExact(DEFAULT_LDAP_TIMEOUT.millis())); options.setResponseTimeoutMillis(DEFAULT_LDAP_TIMEOUT.millis()); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.authc.realms.ldap.foo.ssl"); + final SslProfile profile = sslService.profile("xpack.security.authc.realms.ldap.foo.ssl"); return LdapUtils.privilegedConnect( - () -> new LDAPConnection( - sslService.sslSocketFactory(sslConfiguration), - options, - ldapurl.getHost(), - ldapurl.getPort(), - bindDN, - bindPassword - ) + () -> new LDAPConnection(profile.socketFactory(), options, ldapurl.getHost(), ldapurl.getPort(), bindDN, bindPassword) ); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptorTests.java index 68586a973bc8a..655e4eba4a179 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptorTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptorTests.java @@ -21,6 +21,8 @@ import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.ssl.DefaultJdkTrustConfig; +import org.elasticsearch.common.ssl.EmptyKeyConfig; import org.elasticsearch.common.ssl.SslClientAuthenticationMode; import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.ssl.SslKeyConfig; @@ -59,6 +61,7 @@ import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.audit.AuditUtil; import org.elasticsearch.xpack.security.authc.ApiKeyService; @@ -148,7 +151,7 @@ public void testSendAsync() throws Exception { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -199,7 +202,7 @@ public void testSendAsyncSwitchToSystem() throws Exception { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -243,7 +246,7 @@ public void testSendWithoutUser() throws Exception { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -305,7 +308,7 @@ public void testSendToNewerVersionSetsCorrectVersion() throws Exception { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -373,7 +376,7 @@ public void testSendToOlderVersionSetsCorrectVersion() throws Exception { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -439,7 +442,7 @@ public void testSetUserBasedOnActionOrigin() { threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -606,7 +609,7 @@ public void testSendWithCrossClusterAccessHeadersWithUnsupportedLicense() throws threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -743,7 +746,7 @@ private void doTestSendWithCrossClusterAccessHeaders( threadPool, mock(AuthenticationService.class), authzService, - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -881,7 +884,7 @@ public void testSendWithUserIfCrossClusterAccessHeadersConditionNotMet() throws threadPool, mock(AuthenticationService.class), authzService, - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -940,7 +943,7 @@ public void testSendWithCrossClusterAccessHeadersThrowsOnOldConnection() throws threadPool, mock(AuthenticationService.class), mock(AuthorizationService.class), - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -1039,7 +1042,7 @@ public void testSendRemoteRequestFailsIfUserHasNoRemoteIndicesPrivileges() throw threadPool, mock(AuthenticationService.class), authzService, - mock(SSLService.class), + mockSslService(), securityContext, new DestructiveOperations( Settings.EMPTY, @@ -1107,9 +1110,9 @@ public void testProfileFiltersCreatedDifferentlyForDifferentTransportAndRemoteCl if (randomBoolean()) { builder.put("xpack.security.remote_cluster_client.ssl.enabled", randomBoolean()); // client SSL won't be processed } - final SSLService sslService = mock(SSLService.class); - when(sslService.getSSLConfiguration("xpack.security.transport.ssl.")).thenReturn( + final SslProfile defaultProfile = mock(SslProfile.class); + when(defaultProfile.configuration()).thenReturn( new SslConfiguration( "xpack.security.transport.ssl", randomBoolean(), @@ -1122,8 +1125,8 @@ public void testProfileFiltersCreatedDifferentlyForDifferentTransportAndRemoteCl randomLongBetween(1, 100000) ) ); - - when(sslService.getSSLConfiguration("xpack.security.remote_cluster_server.ssl.")).thenReturn( + final SslProfile remoteProfile = mock(SslProfile.class); + when(remoteProfile.configuration()).thenReturn( new SslConfiguration( "xpack.security.remote_cluster_server.ssl", randomBoolean(), @@ -1136,8 +1139,13 @@ public void testProfileFiltersCreatedDifferentlyForDifferentTransportAndRemoteCl randomLongBetween(1, 100000) ) ); + + final SSLService sslService = mock(SSLService.class); + when(sslService.profile("xpack.security.transport.ssl.")).thenReturn(defaultProfile); + + when(sslService.profile("xpack.security.remote_cluster_server.ssl.")).thenReturn(remoteProfile); doThrow(new AssertionError("profile filters should not be configured for remote cluster client")).when(sslService) - .getSSLConfiguration("xpack.security.remote_cluster_client.ssl."); + .profile("xpack.security.remote_cluster_client.ssl."); final var securityServerTransportInterceptor = new SecurityServerTransportInterceptor( builder.build(), @@ -1172,9 +1180,9 @@ public void testNoProfileFilterForRemoteClusterWhenTheFeatureIsDisabled() { if (randomBoolean()) { builder.put("xpack.security.remote_cluster_client.ssl.enabled", randomBoolean()); // client SSL won't be processed } - final SSLService sslService = mock(SSLService.class); - when(sslService.getSSLConfiguration("xpack.security.transport.ssl.")).thenReturn( + final SslProfile profile = mock(SslProfile.class); + when(profile.configuration()).thenReturn( new SslConfiguration( "xpack.security.transport.ssl", randomBoolean(), @@ -1187,11 +1195,15 @@ public void testNoProfileFilterForRemoteClusterWhenTheFeatureIsDisabled() { randomLongBetween(1, 100000) ) ); + + final SSLService sslService = mock(SSLService.class); + when(sslService.profile("xpack.security.transport.ssl.")).thenReturn(profile); + doThrow(new AssertionError("profile filters should not be configured for remote cluster server when the port is disabled")).when( sslService - ).getSSLConfiguration("xpack.security.remote_cluster_server.ssl."); + ).profile("xpack.security.remote_cluster_server.ssl."); doThrow(new AssertionError("profile filters should not be configured for remote cluster client")).when(sslService) - .getSSLConfiguration("xpack.security.remote_cluster_client.ssl."); + .profile("xpack.security.remote_cluster_client.ssl."); final var securityServerTransportInterceptor = new SecurityServerTransportInterceptor( builder.build(), @@ -1213,6 +1225,26 @@ public void testNoProfileFilterForRemoteClusterWhenTheFeatureIsDisabled() { assertThat(profileFilters.get("default").isExtractClientCert(), is(transportSslEnabled)); } + private static SSLService mockSslService() { + final SslConfiguration defaultConfiguration = new SslConfiguration( + "", + false, + DefaultJdkTrustConfig.DEFAULT_INSTANCE, + EmptyKeyConfig.INSTANCE, + SslVerificationMode.FULL, + SslClientAuthenticationMode.NONE, + List.of("TLS_AES_256_GCM_SHA384"), + List.of("TLSv1.3"), + randomLongBetween(1, 100000) + ); + final SslProfile defaultProfile = mock(SslProfile.class); + when(defaultProfile.configuration()).thenReturn(defaultConfiguration); + final SSLService sslService = mock(SSLService.class); + when(sslService.profile("xpack.security.transport.ssl")).thenReturn(defaultProfile); + when(sslService.profile("xpack.security.transport.ssl.")).thenReturn(defaultProfile); + return sslService; + } + private String[] randomRoles() { return generateRandomStringArray(3, 10, false, true); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportCloseNotifyTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportCloseNotifyTests.java index 8c96d05418ac8..e96415a848c17 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportCloseNotifyTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportCloseNotifyTests.java @@ -43,6 +43,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.netty4.SharedGroupFactory; import org.elasticsearch.transport.netty4.TLSConfig; +import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import java.security.cert.CertificateException; @@ -108,7 +109,7 @@ private HttpServer setupHttpServer(String tlsProtocols) throws CertificateExcept randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java index b64b127cae041..84f68b6dbcd2f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java @@ -52,6 +52,7 @@ import org.elasticsearch.transport.netty4.TLSConfig; import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.Security; import org.junit.Before; @@ -115,7 +116,7 @@ public void testDefaultClientAuth() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -142,7 +143,7 @@ public void testOptionalClientAuth() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -160,6 +161,7 @@ public void testRequiredClientAuth() throws Exception { .put("xpack.security.http.ssl.client_authentication", value) .build(); sslService = new SSLService(TestEnvironment.newEnvironment(settings)); + final SslProfile httpSslProfile = sslService.profile(XPackSettings.HTTP_SSL_PREFIX); Netty4HttpServerTransport transport = new Netty4HttpServerTransport( settings, new NetworkService(Collections.emptyList()), @@ -169,7 +171,7 @@ public void testRequiredClientAuth() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(httpSslProfile::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -196,7 +198,7 @@ public void testNoClientAuth() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -218,7 +220,7 @@ public void testCustomSSLConfiguration() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -241,7 +243,7 @@ public void testCustomSSLConfiguration() throws Exception { randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); @@ -273,7 +275,7 @@ public void testNoExceptionWhenConfiguredWithoutSslKeySSLDisabled() throws Excep randomClusterSettings(), new SharedGroupFactory(settings), TelemetryProvider.NOOP, - new TLSConfig(sslService.getHttpTransportSSLConfiguration(), sslService::createSSLEngine), + new TLSConfig(sslService.profile(XPackSettings.HTTP_SSL_PREFIX)::engine), null, randomFrom((httpPreRequest, channel, listener) -> listener.onResponse(null), null) ); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java index 7a7896eb08d83..c835ef7f81892 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java @@ -31,7 +31,6 @@ import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.ssl.SslClientAuthenticationMode; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.util.PageCacheRecycler; @@ -66,6 +65,7 @@ import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.security.authc.CrossClusterAccessAuthenticationService; import org.elasticsearch.xpack.security.transport.SSLEngineUtils; import org.elasticsearch.xpack.security.transport.filter.IPFilter; @@ -215,8 +215,8 @@ public void testRenegotiation() throws Exception { 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); + final SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + final SocketFactory factory = sslProfile.socketFactory(); try (SSLSocket socket = (SSLSocket) factory.createSocket()) { SocketAccess.doPrivileged(() -> socket.connect(serviceA.boundAddress().publishAddress().address())); @@ -267,8 +267,8 @@ public void testSNIServerNameIsPropagated() throws Exception { assumeFalse("Can't run in a FIPS JVM, TrustAllConfig is not a SunJSSE TrustManagers", inFipsJvm()); SSLService sslService = createSSLService(); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLContext sslContext = sslService.sslContext(sslConfiguration); + final SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + final SSLContext sslContext = sslProfile.sslContext(); final SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); final String sniIp = "sni-hostname"; final SNIHostName sniHostName = new SNIHostName(sniIp); @@ -332,8 +332,8 @@ public void testInvalidSNIServerName() throws Exception { assumeFalse("Can't run in a FIPS JVM, TrustAllConfig is not a SunJSSE TrustManagers", inFipsJvm()); SSLService sslService = createSSLService(); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLContext sslContext = sslService.sslContext(sslConfiguration); + final SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + final SSLContext sslContext = sslProfile.sslContext(); final SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); final String sniIp = "invalid_hostname"; @@ -859,8 +859,8 @@ public void testTcpHandshakeTimeout() throws IOException { assumeFalse("Can't run in a FIPS JVM, TrustAllConfig is not a SunJSSE TrustManagers", inFipsJvm()); SSLService sslService = createSSLService(); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLContext sslContext = sslService.sslContext(sslConfiguration); + final SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + final SSLContext sslContext = sslProfile.sslContext(); final SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); // use latch to to ensure that the accepted socket below isn't closed before the handshake times out final CountDownLatch doneLatch = new CountDownLatch(1); @@ -996,8 +996,8 @@ public void testTcpHandshakeConnectionReset() throws IOException, InterruptedExc assumeFalse("Can't run in a FIPS JVM, TrustAllConfig is not a SunJSSE TrustManagers", inFipsJvm()); SSLService sslService = createSSLService(); - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.security.transport.ssl"); - SSLContext sslContext = sslService.sslContext(sslConfiguration); + final SslProfile sslProfile = sslService.profile("xpack.security.transport.ssl"); + final SSLContext sslContext = sslProfile.sslContext(); final SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory(); try (ServerSocket socket = serverSocketFactory.createServerSocket()) { socket.bind(getLocalEphemeral(), 1); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageCertificateVerificationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageCertificateVerificationTests.java index ccb73c9ead210..37a09357d56c6 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageCertificateVerificationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageCertificateVerificationTests.java @@ -19,7 +19,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.ssl.DiagnosticTrustManager; import org.elasticsearch.common.ssl.SslClientAuthenticationMode; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.ssl.SslVerificationMode; import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.env.TestEnvironment; @@ -29,6 +28,7 @@ import org.elasticsearch.test.http.MockWebServer; import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import java.io.FileNotFoundException; import java.io.IOException; @@ -112,8 +112,8 @@ public void testDiagnosticTrustManagerForHostnameVerificationFailure() throws Ex null ).putList("xpack.http.ssl.certificate_authorities", getPath("ca1.crt")).build(); final SSLService sslService = new SSLService(TestEnvironment.newEnvironment(buildEnvSettings(settings))); - final SslConfiguration clientSslConfig = sslService.getSSLConfiguration(HTTP_CLIENT_SSL); - final SSLSocketFactory clientSocketFactory = sslService.sslSocketFactory(clientSslConfig); + final SslProfile clientSslProfile = sslService.profile(HTTP_CLIENT_SSL); + final SSLSocketFactory clientSocketFactory = clientSslProfile.socketFactory(); // Apache clients implement their own hostname checking, but we don't want that. // We use a raw socket so we get the builtin JDK checking (which is what we use for transport protocol SSL checks) @@ -170,18 +170,18 @@ private void connect(SSLSocket clientSocket, MockWebServer webServer) throws IOE } private CloseableHttpClient buildHttpClient(SSLService sslService) { - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(HTTP_CLIENT_SSL); - final HostnameVerifier verifier = SSLService.getHostnameVerifier(sslConfiguration); - final SSLSocketFactory socketFactory = sslService.sslSocketFactory(sslConfiguration); + final SslProfile profile = sslService.profile(HTTP_CLIENT_SSL); + final HostnameVerifier verifier = profile.hostnameVerifier(); + final SSLSocketFactory socketFactory = profile.socketFactory(); final SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(socketFactory, verifier); return HttpClientBuilder.create().setSSLSocketFactory(connectionSocketFactory).build(); } private RestClient buildRestClient(SSLService sslService, MockWebServer webServer) { - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(HTTP_CLIENT_SSL); + final SslProfile profile = sslService.profile(HTTP_CLIENT_SSL); final HttpHost httpHost = new HttpHost(webServer.getHostName(), webServer.getPort(), "https"); return RestClient.builder(httpHost) - .setHttpClientConfigCallback(client -> client.setSSLStrategy(sslService.sslIOSessionStrategy(sslConfiguration))) + .setHttpClientConfigCallback(client -> client.setSSLStrategy(profile.ioSessionStrategy4())) .build(); } @@ -227,8 +227,8 @@ private static String randomCapitalization(Enum enumValue) { } private MockWebServer initWebServer(SSLService sslService) throws IOException { - final SslConfiguration httpSslConfig = sslService.getSSLConfiguration(HTTP_SERVER_SSL); - final MockWebServer webServer = new MockWebServer(sslService.sslContext(httpSslConfig), false); + final SslProfile httpSslProfile = sslService.profile(HTTP_SERVER_SSL); + final MockWebServer webServer = new MockWebServer(httpSslProfile.sslContext(), false); webServer.enqueue(new MockResponse().setBody("{}").setResponseCode(200)); webServer.start(); diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java index 327d345af864e..9a53906c6f66d 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/common/http/HttpClient.java @@ -48,7 +48,6 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.util.Maps; import org.elasticsearch.core.Streams; @@ -76,8 +75,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import javax.net.ssl.HostnameVerifier; - public class HttpClient implements Closeable { private static final String SETTINGS_SSL_PREFIX = "xpack.http.ssl."; @@ -117,9 +114,7 @@ private CloseableHttpClient createHttpClient() { HttpClientBuilder clientBuilder = HttpClientBuilder.create(); // ssl setup - SslConfiguration sslConfiguration = sslService.getSSLConfiguration(SETTINGS_SSL_PREFIX); - HostnameVerifier verifier = SSLService.getHostnameVerifier(sslConfiguration); - SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslService.sslSocketFactory(sslConfiguration), verifier); + SSLConnectionSocketFactory factory = sslService.profile(SETTINGS_SSL_PREFIX).connectionSocketFactory(); clientBuilder.setSSLSocketFactory(factory); final SocketConfig.Builder socketConfigBuilder = SocketConfig.custom(); diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/EmailService.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/EmailService.java index a979d614fe38f..03978bbe43e19 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/EmailService.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/EmailService.java @@ -15,11 +15,11 @@ import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.ssl.SslConfiguration; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.SslProfile; import org.elasticsearch.xpack.core.watcher.crypto.CryptoService; import org.elasticsearch.xpack.watcher.notification.NotificationService; @@ -281,11 +281,11 @@ protected Account createAccount(String name, Settings accountSettings) { @Nullable private SSLSocketFactory getSmtpSslSocketFactory() { - final SslConfiguration sslConfiguration = sslService.getSSLConfiguration(EMAIL_NOTIFICATION_SSL_PREFIX); - if (sslConfiguration == null || sslConfiguration.explicitlyConfigured() == false) { + final SslProfile profile = sslService.profile(EMAIL_NOTIFICATION_SSL_PREFIX); + if (profile == null || profile.configuration().explicitlyConfigured() == false) { return null; } - return sslService.sslSocketFactory(sslConfiguration); + return profile.socketFactory(); } public EmailSent send(Email email, Authentication auth, Profile profile, String accountName) throws MessagingException {