From 8fbe6e13b7843b88932b74f6e6d6ed6c55ad712f Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 7 May 2018 16:36:26 +1000 Subject: [PATCH 01/22] Refer to SSL contexts by name not settings Historically we have loaded SSL objects (such as SSLContext, SSLIOSessionStrategy) by passing in the SSL settings, constructing a new SSL configuration from those settings and then looking for a cached object that matches those settings. The primary issue with this approach is that it requires a fully configured Settings object to be available any time the SSL context needs to be loaded. If the Settings include SecureSettings (such as passwords for keys or keystores) then this is not true, and the cached SSL object cannot be loaded at runtime. This commit introduces an alternative approach of naming every cached ssl configuration, so that it is possible to load the SSL context for a named configuration (such as "xpack.http.ssl"). This means that the calling code does not need to have ongoing access to the secure settings that were used to load the configuration. --- .../xpack/core/ssl/SSLService.java | 96 +++++++++++++------ .../exporter/http/HttpExporter.java | 12 ++- 2 files changed, 76 insertions(+), 32 deletions(-) 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 c59a2889c28db..45cdb873f2b14 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 @@ -62,6 +62,7 @@ */ public class SSLService extends AbstractComponent { + private final Map sslConfigurations; private final Map sslContexts; private final SSLConfiguration globalSSLConfiguration; private final SetOnce transportSSLConfiguration = new SetOnce<>(); @@ -76,14 +77,16 @@ public SSLService(Settings settings, Environment environment) throws Certificate super(settings); this.env = environment; this.globalSSLConfiguration = new SSLConfiguration(settings.getByPrefix(XPackSettings.GLOBAL_SSL_PREFIX)); + this.sslConfigurations = new HashMap<>(); this.sslContexts = loadSSLConfigurations(); } private SSLService(Settings settings, Environment environment, SSLConfiguration globalSSLConfiguration, - Map sslContexts) { + Map sslConfigurations, Map sslContexts) { super(settings); this.env = environment; this.globalSSLConfiguration = globalSSLConfiguration; + this.sslConfigurations = sslConfigurations; this.sslContexts = sslContexts; } @@ -93,7 +96,7 @@ private SSLService(Settings settings, Environment environment, SSLConfiguration * have been created during initialization */ public SSLService createDynamicSSLService() { - return new SSLService(settings, env, globalSSLConfiguration, sslContexts) { + return new SSLService(settings, env, globalSSLConfiguration, sslConfigurations, sslContexts) { @Override Map loadSSLConfigurations() { @@ -124,9 +127,17 @@ SSLContextHolder sslContextHolder(SSLConfiguration sslConfiguration) { * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. An empty settings will 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 public SSLIOSessionStrategy sslIOSessionStrategy(Settings settings) { SSLConfiguration config = sslConfiguration(settings); + return sslIOSessionStrategy(config); + } + + public SSLIOSessionStrategy sslIOSessionStrategy(SSLConfiguration config) { SSLContext sslContext = sslContext(config); String[] ciphers = supportedCiphers(sslParameters(sslContext).getCipherSuites(), config.cipherSuites(), false); String[] supportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); @@ -436,30 +447,44 @@ private SSLContextHolder createSslContext(ReloadableX509KeyManager keyManager, R /** * Parses the settings to load all SSLConfiguration objects that will be used. */ - Map loadSSLConfigurations() throws CertificateException, - UnrecoverableKeyException, NoSuchAlgorithmException, IOException, DestroyFailedException, KeyStoreException, - OperatorCreationException { - Map sslConfigurations = new HashMap<>(); - sslConfigurations.put(globalSSLConfiguration, createSslContext(globalSSLConfiguration)); + Map loadSSLConfigurations() { + Map sslContextHolders = new HashMap<>(); + sslContextHolders.put(globalSSLConfiguration, createSslContext(globalSSLConfiguration)); + this.sslConfigurations.put("_global", globalSSLConfiguration); final Settings transportSSLSettings = settings.getByPrefix(XPackSettings.TRANSPORT_SSL_PREFIX); - List sslSettingsList = new ArrayList<>(); - sslSettingsList.add(getHttpTransportSSLSettings(settings)); - sslSettingsList.add(settings.getByPrefix("xpack.http.ssl.")); - sslSettingsList.addAll(getRealmsSSLSettings(settings)); - sslSettingsList.addAll(getMonitoringExporterSettings(settings)); - - sslSettingsList.forEach((sslSettings) -> - sslConfigurations.computeIfAbsent(new SSLConfiguration(sslSettings, globalSSLConfiguration), this::createSslContext)); + Map sslSettingsMap = new HashMap<>(); + sslSettingsMap.put(XPackSettings.HTTP_SSL_PREFIX, getHttpTransportSSLSettings(settings)); + sslSettingsMap.put("xpack.http.ssl", settings.getByPrefix("xpack.http.ssl.")); + sslSettingsMap.putAll(getRealmsSSLSettings(settings)); + sslSettingsMap.putAll(getMonitoringExporterSettings(settings)); + + sslSettingsMap.forEach((key, sslSettings) -> { + final SSLConfiguration configuration = new SSLConfiguration(sslSettings, globalSSLConfiguration); + storeSSlConfiguration(key, configuration); + sslContextHolders.computeIfAbsent(configuration, this::createSslContext); + }); // transport is special because we want to use a auto-generated key when there isn't one final SSLConfiguration transportSSLConfiguration = new SSLConfiguration(transportSSLSettings, globalSSLConfiguration); this.transportSSLConfiguration.set(transportSSLConfiguration); - List profileSettings = getTransportProfileSSLSettings(settings); - sslConfigurations.computeIfAbsent(transportSSLConfiguration, this::createSslContext); - profileSettings.forEach((profileSetting) -> - sslConfigurations.computeIfAbsent(new SSLConfiguration(profileSetting, transportSSLConfiguration), this::createSslContext)); - return Collections.unmodifiableMap(sslConfigurations); + this.sslConfigurations.put("_transport", transportSSLConfiguration); + Map profileSettings = getTransportProfileSSLSettings(settings); + sslContextHolders.computeIfAbsent(transportSSLConfiguration, this::createSslContext); + profileSettings.forEach((key, profileSetting) -> { + final SSLConfiguration configuration = new SSLConfiguration(profileSetting, transportSSLConfiguration); + storeSSlConfiguration(key, configuration); + sslContextHolders.computeIfAbsent(configuration, this::createSslContext); + }); + + return Collections.unmodifiableMap(sslContextHolders); + } + + private void storeSSlConfiguration(String key, SSLConfiguration configuration) { + if (key.endsWith(".")) { + key = key.substring(0, key.length() - 1); + } + sslConfigurations.put(key, configuration); } @@ -815,25 +840,29 @@ public X509Certificate[] getAcceptedIssuers() { } } - private static List getRealmsSSLSettings(Settings settings) { - List sslSettings = new ArrayList<>(); - Settings realmsSettings = settings.getByPrefix(SecurityField.setting("authc.realms.")); + /** + * @return A map of Settings prefix to Settings object + */ + private static Map getRealmsSSLSettings(Settings settings) { + Map sslSettings = new HashMap<>(); + final String prefix = SecurityField.setting("authc.realms."); + Settings realmsSettings = settings.getByPrefix(prefix); for (String name : realmsSettings.names()) { Settings realmSSLSettings = realmsSettings.getAsSettings(name).getByPrefix("ssl."); if (realmSSLSettings.isEmpty() == false) { - sslSettings.add(realmSSLSettings); + sslSettings.put(prefix + name + ".ssl", realmSSLSettings); } } return sslSettings; } - private static List getTransportProfileSSLSettings(Settings settings) { - List sslSettings = new ArrayList<>(); + private static Map getTransportProfileSSLSettings(Settings settings) { + Map sslSettings = new HashMap<>(); Map profiles = settings.getGroups("transport.profiles.", true); for (Entry entry : profiles.entrySet()) { Settings profileSettings = entry.getValue().getByPrefix("xpack.security.ssl."); if (profileSettings.isEmpty() == false) { - sslSettings.add(profileSettings); + sslSettings.put("transport.profiles." + entry.getKey() + "xpack.security.ssl", profileSettings); } } return sslSettings; @@ -852,18 +881,25 @@ public static Settings getHttpTransportSSLSettings(Settings settings) { return builder.build(); } - private static List getMonitoringExporterSettings(Settings settings) { - List sslSettings = new ArrayList<>(); + private static Map getMonitoringExporterSettings(Settings settings) { + Map sslSettings = new HashMap<>(); Map exportersSettings = settings.getGroups("xpack.monitoring.exporters."); for (Entry entry : exportersSettings.entrySet()) { Settings exporterSSLSettings = entry.getValue().getByPrefix("ssl."); if (exporterSSLSettings.isEmpty() == false) { - sslSettings.add(exporterSSLSettings); + sslSettings.put("xpack.monitoring.exporters." + entry.getKey() + ".ssl", exporterSSLSettings); } } return sslSettings; } + public SSLConfiguration getSSLConfiguration(String contextName) { + if (contextName.endsWith(".")) { + contextName = contextName.substring(0, contextName.length() - 1); + } + return sslConfigurations.get(contextName); + } + /** * Maps the supported protocols to an appropriate ssl context algorithm. We make an attempt to use the "best" algorithm when * possible. The names in this method are taken from the 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 88b1a8a9db18f..24260c25a1894 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 @@ -35,6 +35,7 @@ import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringTemplateUtils; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.monitoring.exporter.ClusterAlertsUtil; import org.elasticsearch.xpack.monitoring.exporter.Exporter; @@ -445,8 +446,15 @@ private static void configureHeaders(final RestClientBuilder builder, final Conf * @throws SettingsException if any setting causes issues */ private static void configureSecurity(final RestClientBuilder builder, final Config config, final SSLService sslService) { - final Settings sslSettings = SSL_SETTING.getConcreteSettingForNamespace(config.name()).get(config.settings()); - final SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(sslSettings); + final Setting concreteSetting = SSL_SETTING.getConcreteSettingForNamespace(config.name()); + final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(concreteSetting.getKey()); + final SSLIOSessionStrategy sslStrategy; + if (sslConfiguration == null) { + final Settings sslSettings = concreteSetting.get(config.settings()); + sslStrategy = sslService.sslIOSessionStrategy(sslSettings); + } else { + sslStrategy = sslService.sslIOSessionStrategy(sslConfiguration); + } final CredentialsProvider credentialsProvider = createCredentialsProvider(config); List hostList = HOST_SETTING.getConcreteSettingForNamespace(config.name()).get(config.settings());; // sending credentials in plaintext! From a360d228beb844a64e754dcf762eb21a0f13531f Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 14 May 2018 13:53:05 +1000 Subject: [PATCH 02/22] [WIP] Use named SSL context in LDAP --- .../xpack/core/ssl/SSLService.java | 18 ++++++++++++++---- .../authc/ldap/support/SessionFactory.java | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) 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 45cdb873f2b14..82571cb2cea01 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 @@ -30,7 +30,6 @@ import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; import javax.security.auth.DestroyFailedException; - import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -188,9 +187,20 @@ SSLIOSessionStrategy sslIOSessionStrategy(SSLContext sslContext, String[] protoc */ public SSLSocketFactory sslSocketFactory(Settings settings) { SSLConfiguration sslConfiguration = sslConfiguration(settings); - SSLSocketFactory socketFactory = sslContext(sslConfiguration).getSocketFactory(); - return new SecuritySSLSocketFactory(socketFactory, sslConfiguration.supportedProtocols().toArray(Strings.EMPTY_ARRAY), - supportedCiphers(socketFactory.getSupportedCipherSuites(), sslConfiguration.cipherSuites(), false)); + return sslSocketFactory(sslConfiguration); + } + + /** + * Create a new {@link SSLSocketFactory} based on the provided settings. The settings are used to identify the ssl configuration that + * should be used to create the socket factory. 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) { + SSLSocketFactory socketFactory = sslContext(configuration).getSocketFactory(); + return new SecuritySSLSocketFactory(socketFactory, configuration.supportedProtocols().toArray(Strings.EMPTY_ARRAY), + supportedCiphers(socketFactory.getSupportedCipherSuites(), configuration.cipherSuites(), false)); } /** 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 aabea2eb854e7..3780741b5941f 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 @@ -21,6 +21,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig; import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.ldap.support.SessionFactorySettings; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.core.ssl.VerificationMode; @@ -180,7 +181,8 @@ private ServerSet serverSet(RealmConfig realmConfig, SSLService clientSSLService Settings settings = realmConfig.settings(); SocketFactory socketFactory = null; if (ldapServers.ssl()) { - socketFactory = clientSSLService.sslSocketFactory(settings.getByPrefix("ssl.")); + SSLConfiguration ssl = clientSSLService.getSSLConfiguration(RealmSettings.getFullSettingKey(realmConfig, "ssl")); + socketFactory = clientSSLService.sslSocketFactory(ssl); if (settings.getAsBoolean(SessionFactorySettings.HOSTNAME_VERIFICATION_SETTING, true)) { logger.debug("using encryption for LDAP connections with hostname verification"); } else { From 9ea7a52bf208d033118318d62464692489aa710a Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 28 May 2018 17:16:06 +1000 Subject: [PATCH 03/22] Update openldap QA tests for named SSL contexts --- .../xpack/core/ssl/SSLService.java | 12 ++- .../org/elasticsearch/test/OpenLdapTests.java | 78 ++++++++++--------- ...OpenLdapUserSearchSessionFactoryTests.java | 9 ++- 3 files changed, 54 insertions(+), 45 deletions(-) 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 5e0c5c58b2070..bfd0add081ad6 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 @@ -30,8 +30,6 @@ import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; -import javax.security.auth.DestroyFailedException; - import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -50,6 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -332,7 +331,7 @@ SSLContext sslContext(SSLConfiguration configuration) { * @throws IllegalArgumentException if not found */ SSLContextHolder sslContextHolder(SSLConfiguration sslConfiguration) { - SSLContextHolder holder = sslContexts.get(sslConfiguration); + SSLContextHolder holder = sslContexts.get(Objects.requireNonNull(sslConfiguration, "SSL Configuration cannot be null")); if (holder == null) { throw new IllegalArgumentException("did not find a SSLContext for [" + sslConfiguration.toString() + "]"); } @@ -714,7 +713,12 @@ public SSLConfiguration getSSLConfiguration(String contextName) { if (contextName.endsWith(".")) { contextName = contextName.substring(0, contextName.length() - 1); } - return sslConfigurations.get(contextName); + final SSLConfiguration configuration = sslConfigurations.get(contextName); + if (configuration == null && logger.isTraceEnabled()) { + logger.trace("Cannot find SSL configuration for context {}. Known contexts are: {}", contextName, + Strings.collectionToCommaDelimitedString(sslConfigurations.keySet())); + } + return configuration; } /** diff --git a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java index eced8a1b39ae8..b2d7b9490e6cc 100644 --- a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java +++ b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java @@ -16,6 +16,7 @@ import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException; import org.elasticsearch.env.Environment; import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.authc.RealmConfig; @@ -55,6 +56,7 @@ public class OpenLdapTests extends ESTestCase { private static final String HAWKEYE_DN = "uid=hawkeye,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; public static final String LDAPTRUST_PATH = "/idptrust.jks"; private static final SecureString PASSWORD_SECURE_STRING = new SecureString(PASSWORD.toCharArray()); + public static final String REALM_NAME = "oldap-test"; private boolean useGlobalSSL; private SSLService sslService; @@ -91,18 +93,18 @@ public void initializeSslSocketFactory() throws Exception { builder.put("xpack.ssl.truststore.path", truststore); mockSecureSettings.setString("xpack.ssl.truststore.secure_password", "changeit"); - // fake realm to load config with certificate verification mode - builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore); - mockSecureSettings.setString("xpack.security.authc.realms.bar.ssl.truststore.secure_password", "changeit"); - builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE); + // configure realm to load config with certificate verification mode + builder.put("xpack.security.authc.realms." + REALM_NAME + ".ssl.truststore.path", truststore); + mockSecureSettings.setString("xpack.security.authc.realms." + REALM_NAME + ".ssl.truststore.secure_password", "changeit"); + builder.put("xpack.security.authc.realms." + REALM_NAME + ".ssl.verification_mode", VerificationMode.CERTIFICATE); } else { // fake realms so ssl will get loaded builder.put("xpack.security.authc.realms.foo.ssl.truststore.path", truststore); mockSecureSettings.setString("xpack.security.authc.realms.foo.ssl.truststore.secure_password", "changeit"); builder.put("xpack.security.authc.realms.foo.ssl.verification_mode", VerificationMode.FULL); - builder.put("xpack.security.authc.realms.bar.ssl.truststore.path", truststore); - mockSecureSettings.setString("xpack.security.authc.realms.bar.ssl.truststore.secure_password", "changeit"); - builder.put("xpack.security.authc.realms.bar.ssl.verification_mode", VerificationMode.CERTIFICATE); + builder.put("xpack.security.authc.realms." + REALM_NAME + ".ssl.truststore.path", truststore); + mockSecureSettings.setString("xpack.security.authc.realms." + REALM_NAME + ".ssl.truststore.secure_password", "changeit"); + builder.put("xpack.security.authc.realms." + REALM_NAME + ".ssl.verification_mode", VerificationMode.CERTIFICATE); } globalSettings = builder.setSecureSettings(mockSecureSettings).build(); Environment environment = TestEnvironment.newEnvironment(globalSettings); @@ -114,8 +116,8 @@ public void testConnect() throws Exception { String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; RealmConfig config = new RealmConfig("oldap-test", buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, - LdapSearchScope.ONE_LEVEL), globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(Settings.EMPTY)); + LdapSearchScope.ONE_LEVEL), globalSettings, TestEnvironment.newEnvironment(globalSettings), + new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" }; @@ -132,8 +134,8 @@ public void testGroupSearchScopeBase() throws Exception { String groupSearchBase = "cn=Avengers,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; - RealmConfig config = new RealmConfig("oldap-test", buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, - LdapSearchScope.BASE), globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(Settings.EMPTY)); + RealmConfig config = new RealmConfig(REALM_NAME, buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, + LdapSearchScope.BASE), globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); String[] users = new String[] { "blackwidow", "cap", "hawkeye", "hulk", "ironman", "thor" }; @@ -148,12 +150,12 @@ public void testCustomFilter() throws Exception { String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; Settings settings = Settings.builder() - .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) - .put("group_search.filter", "(&(objectclass=posixGroup)(memberUid={0}))") - .put("group_search.user_attribute", "uid") - .build(); + .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) + .put("group_search.filter", "(&(objectclass=posixGroup)(memberUid={0}))") + .put("group_search.user_attribute", "uid") + .build(); RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(Settings.EMPTY)); + new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); try (LdapSession ldap = session(sessionFactory, "selvig", PASSWORD_SECURE_STRING)) { @@ -166,17 +168,17 @@ public void testTcpTimeout() throws Exception { String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; Settings settings = Settings.builder() - .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) - .put("group_search.filter", "(objectClass=*)") - .put("ssl.verification_mode", VerificationMode.CERTIFICATE) - .put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms") //1 millisecond - .build(); + .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) + .put("group_search.filter", "(objectClass=*)") + .put("ssl.verification_mode", VerificationMode.CERTIFICATE) + .put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms") //1 millisecond + .build(); RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(Settings.EMPTY)); + new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); LDAPException expected = expectThrows(LDAPException.class, - () -> session(sessionFactory, "thor", PASSWORD_SECURE_STRING).groups(new PlainActionFuture<>())); + () -> session(sessionFactory, "thor", PASSWORD_SECURE_STRING).groups(new PlainActionFuture<>())); assertThat(expected.getMessage(), containsString("A client-side timeout was encountered while waiting")); } @@ -185,22 +187,22 @@ public void testStandardLdapConnectionHostnameVerificationFailure() throws Excep String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; Settings settings = Settings.builder() - // The certificate used in the vagrant box is valid for "localhost", but not for "127.0.0.1" - .put(buildLdapSettings(OPEN_LDAP_IP_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) - .put("ssl.verification_mode", VerificationMode.FULL) - .build(); + // The certificate used in the vagrant box is valid for "localhost", but not for "127.0.0.1" + .put(buildLdapSettings(OPEN_LDAP_IP_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) + .put("ssl.verification_mode", VerificationMode.FULL) + .build(); RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(Settings.EMPTY)); + new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); String user = "blackwidow"; UncategorizedExecutionException e = expectThrows(UncategorizedExecutionException.class, - () -> session(sessionFactory, user, PASSWORD_SECURE_STRING)); + () -> session(sessionFactory, user, PASSWORD_SECURE_STRING)); assertThat(e.getCause(), instanceOf(ExecutionException.class)); assertThat(e.getCause().getCause(), instanceOf(LDAPException.class)); assertThat(e.getCause().getCause().getMessage(), - anyOf(containsString("Hostname verification failed"), containsString("peer not authenticated"))); + anyOf(containsString("Hostname verification failed"), containsString("peer not authenticated"))); } public void testStandardLdapConnectionHostnameVerificationSuccess() throws Exception { @@ -208,13 +210,13 @@ public void testStandardLdapConnectionHostnameVerificationSuccess() throws Excep String groupSearchBase = "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; String userTemplate = "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"; Settings settings = Settings.builder() - // The certificate used in the vagrant box is valid for "localhost" (but not for "127.0.0.1") - .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) - .put("ssl.verification_mode", VerificationMode.FULL) - .build(); + // The certificate used in the vagrant box is valid for "localhost" (but not for "127.0.0.1") + .put(buildLdapSettings(OPEN_LDAP_DNS_URL, userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) + .put("ssl.verification_mode", VerificationMode.FULL) + .build(); RealmConfig config = new RealmConfig("oldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(Settings.EMPTY)); + new ThreadContext(Settings.EMPTY)); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); final String user = "blackwidow"; @@ -260,9 +262,9 @@ private Settings buildLdapSettings(String ldapUrl, String userTemplate, String g return builder.build(); } return builder - .put("ssl.truststore.path", getDataPath(LDAPTRUST_PATH)) - .put("ssl.truststore.password", "changeit") - .build(); + .put("ssl.truststore.path", getDataPath(LDAPTRUST_PATH)) + .put("ssl.truststore.password", "changeit") + .build(); } private LdapSession session(SessionFactory factory, String username, SecureString password) { diff --git a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/xpack/security/authc/ldap/OpenLdapUserSearchSessionFactoryTests.java b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/xpack/security/authc/ldap/OpenLdapUserSearchSessionFactoryTests.java index c008b5260f82b..1c9d93873a493 100644 --- a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/xpack/security/authc/ldap/OpenLdapUserSearchSessionFactoryTests.java +++ b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/xpack/security/authc/ldap/OpenLdapUserSearchSessionFactoryTests.java @@ -15,6 +15,7 @@ import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.OpenLdapTests; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.authc.RealmConfig; @@ -39,6 +40,7 @@ import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; +@TestLogging("org.elasticsearch.xpack.core.ssl.SSLService:TRACE") public class OpenLdapUserSearchSessionFactoryTests extends ESTestCase { private Settings globalSettings; @@ -77,7 +79,8 @@ public void testUserSearchWithBindUserOpenLDAP() throws Exception { .put("user_search.base_dn", userSearchBase) .put("group_search.user_attribute", "uid") .put("bind_dn", "uid=blackwidow,ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com") - .put("user_search.pool.enabled", randomBoolean()); + .put("user_search.pool.enabled", randomBoolean()) + .put("ssl.verification_mode", "full"); if (useSecureBindPassword) { final MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.setString("secure_bind_password", OpenLdapTests.PASSWORD); @@ -89,11 +92,11 @@ public void testUserSearchWithBindUserOpenLDAP() throws Exception { TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); Settings.Builder builder = Settings.builder() .put(globalSettings, false); - builder.put(Settings.builder().put(config.settings(), false).normalizePrefix("xpack.security.authc.realms.ldap.").build()); + builder.put(Settings.builder().put(config.settings(), false).normalizePrefix("xpack.security.authc.realms.oldap-test.").build()); final MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.merge(globalSecureSettings); if (useSecureBindPassword) { - secureSettings.setString("xpack.security.authc.realms.ldap.secure_bind_password", OpenLdapTests.PASSWORD); + secureSettings.setString("xpack.security.authc.realms.oldap-test.secure_bind_password", OpenLdapTests.PASSWORD); } builder.setSecureSettings(secureSettings); Settings settings = builder.build(); From 997a1ec463f133fb7decbb9f572df745c7a3917f Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 28 May 2018 21:20:13 +1000 Subject: [PATCH 04/22] Remove sslSocketFactory(Settings) from SSLService --- .../xpack/core/ssl/SSLService.java | 22 +++++-------------- .../xpack/core/ssl/SSLServiceTests.java | 2 +- .../esnative/ESNativeRealmMigrateTool.java | 5 +++-- .../esnative/tool/CommandLineHttpClient.java | 11 +++++----- .../xpack/security/authc/saml/SamlRealm.java | 8 ++++--- .../security/authc/ldap/LdapTestUtils.java | 12 +++++----- .../nio/SimpleSecurityNioTransportTests.java | 5 +++-- .../transport/ssl/SslIntegrationTests.java | 4 +++- .../xpack/ssl/SSLReloadIntegTests.java | 4 +++- .../xpack/ssl/SSLTrustRestrictionsTests.java | 4 +++- .../xpack/watcher/common/http/HttpClient.java | 7 +++--- 11 files changed, 41 insertions(+), 43 deletions(-) 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 bfd0add081ad6..92a80e99cd748 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 @@ -174,22 +174,8 @@ SSLIOSessionStrategy sslIOSessionStrategy(SSLContext sslContext, String[] protoc } /** - * Create a new {@link SSLSocketFactory} based on the provided settings. The settings are used to identify the ssl configuration that - * should be used to create the socket factory. The socket factory will also properly configure the ciphers and protocols on each - * socket that is created - * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. An empty settings will return - * a factory created from the default configuration - * @return Never {@code null}. - */ - public SSLSocketFactory sslSocketFactory(Settings settings) { - SSLConfiguration sslConfiguration = sslConfiguration(settings); - return sslSocketFactory(sslConfiguration); - } - - /** - * Create a new {@link SSLSocketFactory} based on the provided settings. The settings are used to identify the ssl configuration that - * should be used to create the socket factory. The socket factory will also properly configure the ciphers and protocols on each - * socket that is created + * 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}. */ @@ -697,6 +683,10 @@ public static Settings getHttpTransportSSLSettings(Settings settings) { return builder.build(); } + public SSLConfiguration getHttpTransportSSLConfiguration() { + return getSSLConfiguration(XPackSettings.HTTP_SSL_PREFIX); + } + private static Map getMonitoringExporterSettings(Settings settings) { Map sslSettings = new HashMap<>(); Map exportersSettings = settings.getGroups("xpack.monitoring.exporters."); 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 bcb4b63865432..56af5e58be315 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 @@ -375,8 +375,8 @@ public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Except .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLSocketFactory factory = sslService.sslSocketFactory(Settings.EMPTY); SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLSocketFactory factory = sslService.sslSocketFactory(config); final String[] ciphers = sslService.supportedCiphers(factory.getSupportedCipherSuites(), config.cipherSuites(), false); assertThat(factory.getDefaultCipherSuites(), is(ciphers)); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateTool.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateTool.java index b149fec3d3db8..4226607f192f4 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateTool.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateTool.java @@ -41,6 +41,7 @@ import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.security.authz.store.FileRolesStore; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.authc.file.FileUserPasswdStore; @@ -148,12 +149,12 @@ private String postURL(Settings settings, Environment env, String method, String HttpURLConnection conn; // If using SSL, need a custom service because it's likely a self-signed certificate if ("https".equalsIgnoreCase(uri.getScheme())) { - Settings sslSettings = settings.getByPrefix(setting("http.ssl.")); final SSLService sslService = new SSLService(settings, env); + final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(setting("http.ssl")); final HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection(); AccessController.doPrivileged((PrivilegedAction) () -> { // Requires permission java.lang.RuntimePermission "setFactory"; - httpsConn.setSSLSocketFactory(sslService.sslSocketFactory(sslSettings)); + httpsConn.setSSLSocketFactory(sslService.sslSocketFactory(sslConfiguration)); return null; }); conn = httpsConn; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClient.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClient.java index f14911402d60f..f69c3f6893fd8 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClient.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClient.java @@ -19,9 +19,11 @@ import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.authc.esnative.tool.HttpResponse.HttpResponseBuilder; +import javax.net.ssl.HttpsURLConnection; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -35,8 +37,6 @@ import java.util.Collections; import java.util.List; -import javax.net.ssl.HttpsURLConnection; - import static org.elasticsearch.http.HttpTransportSettings.SETTING_HTTP_PORT; import static org.elasticsearch.http.HttpTransportSettings.SETTING_HTTP_PUBLISH_HOST; import static org.elasticsearch.http.HttpTransportSettings.SETTING_HTTP_PUBLISH_PORT; @@ -86,11 +86,10 @@ public HttpResponse execute(String method, URL url, String user, SecureString pa final SSLService sslService = new SSLService(settings, env); final HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection(); AccessController.doPrivileged((PrivilegedAction) () -> { - final Settings sslSettings = SSLService.getHttpTransportSSLSettings(settings); + final SSLConfiguration sslConfiguration = sslService.getHttpTransportSSLConfiguration(); // Requires permission java.lang.RuntimePermission "setFactory"; - httpsConn.setSSLSocketFactory(sslService.sslSocketFactory(sslSettings)); - final boolean isHostnameVerificationEnabled = - sslService.getVerificationMode(sslSettings, Settings.EMPTY).isHostnameVerificationEnabled(); + httpsConn.setSSLSocketFactory(sslService.sslSocketFactory(sslConfiguration)); + final boolean isHostnameVerificationEnabled = sslConfiguration.verificationMode().isHostnameVerificationEnabled(); if (isHostnameVerificationEnabled == false) { httpsConn.setHostnameVerifier((hostname, session) -> true); } 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 d7d231af68002..d3755f61baead 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 @@ -45,6 +45,7 @@ import org.elasticsearch.xpack.core.security.authc.saml.SamlRealmSettings; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.ssl.CertUtils; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.core.ssl.X509KeyPairSettings; import org.elasticsearch.xpack.security.authc.Realms; @@ -495,10 +496,11 @@ private static Tuple new LDAPConnection(sslService.sslSocketFactory(connectionSettings), options, + return LdapUtils.privilegedConnect(() -> new LDAPConnection(sslService.sslSocketFactory(sslConfiguration), options, ldapurl.getHost(), ldapurl.getPort(), bindDN, bindPassword)); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java index 0a7ee13b9e296..9bd4adb35fede 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java @@ -31,12 +31,12 @@ import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.core.common.socket.SocketAccess; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import javax.net.SocketFactory; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLSocket; - import java.io.IOException; import java.net.InetAddress; import java.net.SocketTimeoutException; @@ -159,7 +159,8 @@ public void testBindUnavailableAddress() { @SuppressForbidden(reason = "Need to open socket connection") public void testRenegotiation() throws Exception { SSLService sslService = createSSLService(); - SocketFactory factory = sslService.sslSocketFactory(Settings.EMPTY); + final SSLConfiguration sslConfiguration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SocketFactory factory = sslService.sslSocketFactory(sslConfiguration); try (SSLSocket socket = (SSLSocket) factory.createSocket()) { SocketAccess.doPrivileged(() -> socket.connect(serviceA.boundAddress().publishAddress().address())); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java index 075ce2772b394..a84feb5fb43b7 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java @@ -29,6 +29,7 @@ import org.elasticsearch.xpack.core.TestXPackTransportClient; import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.common.socket.SocketAccess; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.LocalStateSecurity; @@ -124,8 +125,9 @@ public void testThatConnectionToHTTPWorks() throws Exception { CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(nodeClientUsername(), new String(nodeClientPassword().getChars()))); + SSLConfiguration sslConfiguration = service.sslConfiguration(Settings.EMPTY, Settings.EMPTY); try (CloseableHttpClient client = HttpClients.custom() - .setSSLSocketFactory(new SSLConnectionSocketFactory(service.sslSocketFactory(Settings.EMPTY), + .setSSLSocketFactory(new SSLConnectionSocketFactory(service.sslSocketFactory(sslConfiguration), SSLConnectionSocketFactory.getDefaultHostnameVerifier())) .setDefaultCredentialsProvider(provider).build(); CloseableHttpResponse response = SocketAccess.doPrivileged(() -> client.execute(new HttpGet(getNodeUrl())))) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java index 3e05c88953aed..497ab46f03e4c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.test.SecuritySettingsSourceField; import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.core.ssl.CertUtils; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -115,7 +116,8 @@ public void testThatSSLConfigurationReloadsOnModification() throws Exception { .build(); String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(settings, TestEnvironment.newEnvironment(settings)); - SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(settings); + SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("_global"); + SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); TransportAddress address = internalCluster() .getInstance(Transport.class, node).boundAddress().publishAddress(); try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java index 4e76e59e5962f..bf22669f3c46b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.core.ssl.CertUtils; import org.elasticsearch.xpack.core.ssl.RestrictedTrustManager; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -195,7 +196,8 @@ private void tryConnect(CertificateInfo certificate) throws Exception { String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(settings, TestEnvironment.newEnvironment(settings)); - SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(settings); + SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("_global"); + SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); 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/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 80d12f5fbce4e..97d7779346fae 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 @@ -40,6 +40,7 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.core.internal.io.Streams; import org.elasticsearch.xpack.core.common.socket.SocketAccess; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.watcher.common.http.auth.ApplicableHttpAuth; import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry; @@ -83,10 +84,10 @@ public HttpClient(Settings settings, HttpAuthRegistry httpAuthRegistry, SSLServi HttpClientBuilder clientBuilder = HttpClientBuilder.create(); // ssl setup - Settings sslSettings = settings.getByPrefix(SETTINGS_SSL_PREFIX); - boolean isHostnameVerificationEnabled = sslService.getVerificationMode(sslSettings, Settings.EMPTY).isHostnameVerificationEnabled(); + SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(SETTINGS_SSL_PREFIX); + boolean isHostnameVerificationEnabled = sslConfiguration.verificationMode().isHostnameVerificationEnabled(); HostnameVerifier verifier = isHostnameVerificationEnabled ? new DefaultHostnameVerifier() : NoopHostnameVerifier.INSTANCE; - SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslService.sslSocketFactory(sslSettings), verifier); + SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslService.sslSocketFactory(sslConfiguration), verifier); clientBuilder.setSSLSocketFactory(factory); clientBuilder.evictExpiredConnections(); From 2999649a55398ed84281badc1e9a31af90f8433e Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 29 May 2018 13:47:29 +1000 Subject: [PATCH 05/22] Deprecate createSSLEngine(Settings) --- .../xpack/core/ssl/SSLService.java | 21 ++------- .../xpack/core/ssl/SSLServiceTests.java | 44 +++++++++++-------- 2 files changed, 29 insertions(+), 36 deletions(-) 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 92a80e99cd748..1bd8fe493cfc1 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 @@ -195,27 +195,12 @@ public SSLSocketFactory sslSocketFactory(SSLConfiguration configuration) { * @param fallbackSettings the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} * results in a fallback to the global configuration * @return {@link SSLEngine} + * @deprecated Use {@link #createSSLEngine(SSLConfiguration, String, int)} and {@link #getSSLConfiguration(String)} */ + @Deprecated public SSLEngine createSSLEngine(Settings settings, Settings fallbackSettings) { - return createSSLEngine(settings, fallbackSettings, null, -1); - } - - /** - * Creates an {@link SSLEngine} based on the provided settings. The settings are used to identify the ssl configuration that should be - * used to create the engine. 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 settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. An empty settings will return - * a SSLEngine created from the default configuration - * @param fallbackSettings the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} - * results in a fallback to the global 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} - */ - public SSLEngine createSSLEngine(Settings settings, Settings fallbackSettings, String host, int port) { SSLConfiguration configuration = sslConfiguration(settings, fallbackSettings); - return createSSLEngine(configuration, host, port); + return createSSLEngine(configuration, null, -1); } /** 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 56af5e58be315..da42a256dbddf 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 @@ -32,23 +32,17 @@ import org.mockito.ArgumentCaptor; import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedTrustManager; -import java.net.Socket; import java.nio.file.Path; import java.security.AccessController; -import java.security.KeyStore; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -117,10 +111,12 @@ public void testThatCustomTruststoreCanBeSpecified() throws Exception { .setSecureSettings(secureCustomSettings) .build(); - SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(customTruststoreSettings, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(customTruststoreSettings, Settings.EMPTY); + SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngineWithTruststore, is(not(nullValue()))); - SSLEngine sslEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration1 = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine sslEngine = sslService.createSSLEngine(configuration1, null, -1); assertThat(sslEngineWithTruststore, is(not(sameInstance(sslEngine)))); } @@ -150,7 +146,9 @@ public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { .put("xpack.ssl.keystore.path", differentPasswordsStore) .setSecureSettings(secureSettings) .build(); - new SSLService(settings, env).createSSLEngine(Settings.EMPTY, Settings.EMPTY); + final SSLService sslService = new SSLService(settings, env); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + sslService.createSSLEngine(configuration, null, -1); } public void testIncorrectKeyPasswordThrowsException() throws Exception { @@ -163,7 +161,9 @@ public void testIncorrectKeyPasswordThrowsException() throws Exception { .put("xpack.ssl.keystore.path", differentPasswordsStore) .setSecureSettings(secureSettings) .build(); - new SSLService(settings, env).createSSLEngine(Settings.EMPTY, Settings.EMPTY); + final SSLService sslService = new SSLService(settings, env); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + sslService.createSSLEngine(configuration, null, -1); fail("expected an exception"); } catch (ElasticsearchException e) { assertThat(e.getMessage(), containsString("failed to initialize a KeyManagerFactory")); @@ -179,13 +179,15 @@ public void testThatSSLv3IsNotEnabled() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(Arrays.asList(engine.getEnabledProtocols()), not(hasItem("SSLv3"))); } public void testThatCreateClientSSLEngineWithoutAnySettingsWorks() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - SSLEngine sslEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngine, notNullValue()); } @@ -197,7 +199,8 @@ public void testThatCreateSSLEngineWithOnlyTruststoreWorks() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLEngine sslEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngine, notNullValue()); } @@ -331,7 +334,8 @@ public void testCiphersAndInvalidCiphersWork() throws Exception { .putList("xpack.ssl.ciphers", ciphers.toArray(new String[ciphers.size()])) .build(); SSLService sslService = new SSLService(settings, env); - SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(engine, is(notNullValue())); String[] enabledCiphers = engine.getEnabledCipherSuites(); assertThat(Arrays.asList(enabledCiphers), not(contains("foo", "bar"))); @@ -361,7 +365,8 @@ public void testThatSSLEngineHasCipherSuitesOrderSet() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(engine, is(notNullValue())); assertTrue(engine.getSSLParameters().getUseCipherSuitesOrder()); } @@ -400,7 +405,8 @@ public void testThatSSLEngineHasProperCiphersAndProtocols() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); final String[] ciphers = sslService.supportedCiphers(engine.getSupportedCipherSuites(), config.cipherSuites(), false); final String[] supportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); @@ -589,7 +595,9 @@ public void testThatSSLContextTrustsJDKTrustedCAs() throws Exception { @Network public void testThatSSLIOSessionStrategyWithoutSettingsWorks() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(Settings.EMPTY); + SSLConfiguration sslConfiguration = sslService.sslConfiguration(Settings.EMPTY); + logger.info("SSL Configuration: {}", sslConfiguration); + SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(sslConfiguration); try (CloseableHttpAsyncClient client = getAsyncHttpClient(sslStrategy)) { client.start(); @@ -601,7 +609,7 @@ public void testThatSSLIOSessionStrategyWithoutSettingsWorks() throws Exception } @Network - public void testThatSSLIOSessionStrategytTrustsJDKTrustedCAs() throws Exception { + public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { MockSecureSettings secureSettings = new MockSecureSettings(); secureSettings.setString("xpack.ssl.keystore.secure_password", "testclient"); Settings settings = Settings.builder() From bcde8a5132803cef9dd2e3b5e7fe689472bfd087 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 29 May 2018 19:39:19 +1000 Subject: [PATCH 06/22] Remove createSSLEngine(Settings) --- .../xpack/core/ssl/SSLService.java | 18 ------------------ .../xpack/core/ssl/SSLServiceTests.java | 1 + .../SecurityNetty4ServerTransportTests.java | 5 ++++- 3 files changed, 5 insertions(+), 19 deletions(-) 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 1bd8fe493cfc1..cf9e1184f959c 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 @@ -185,24 +185,6 @@ public SSLSocketFactory sslSocketFactory(SSLConfiguration configuration) { supportedCiphers(socketFactory.getSupportedCipherSuites(), configuration.cipherSuites(), false)); } - /** - * Creates an {@link SSLEngine} based on the provided settings. The settings are used to identify the ssl configuration that should be - * used to create the engine. This SSLEngine cannot be used for hostname verification since the engine will not be created with the - * host and port. This method is useful to obtain an SSLEngine that will be used for server connections or client connections that - * will not use hostname verification. - * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. An empty settings will return - * a SSLEngine created from the default configuration - * @param fallbackSettings the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} - * results in a fallback to the global configuration - * @return {@link SSLEngine} - * @deprecated Use {@link #createSSLEngine(SSLConfiguration, String, int)} and {@link #getSSLConfiguration(String)} - */ - @Deprecated - public SSLEngine createSSLEngine(Settings settings, Settings fallbackSettings) { - SSLConfiguration configuration = sslConfiguration(settings, fallbackSettings); - return createSSLEngine(configuration, null, -1); - } - /** * Creates an {@link SSLEngine} based on the provided configuration. This SSLEngine can be used for a connection that requires * hostname verification assuming the provided 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 da42a256dbddf..127e5da8babc0 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 @@ -445,6 +445,7 @@ public void testSSLStrategy() { // ensure it actually goes through and calls the real method when(sslService.sslIOSessionStrategy(settings)).thenCallRealMethod(); + when(sslService.sslIOSessionStrategy(sslConfig)).thenCallRealMethod(); assertThat(sslService.sslIOSessionStrategy(settings), sameInstance(sslStrategy)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java index 3d9227319a870..33f47fe7a00ba 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport; import org.elasticsearch.xpack.core.ssl.SSLClientAuth; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.junit.Before; @@ -200,7 +201,9 @@ public void testTransportSSLOverridesGlobalSSL() throws Exception { assertFalse(engine.getWantClientAuth()); // get the global and verify that it is different in that it requires client auth - final SSLEngine globalEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = sslService.getSSLConfiguration("_global"); + assertNotNull(configuration); + final SSLEngine globalEngine = sslService.createSSLEngine(configuration, null, -1); assertTrue(globalEngine.getNeedClientAuth()); assertFalse(globalEngine.getWantClientAuth()); } From 6ce4d327042579ba45dd7f01eb1baacda7adeae0 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 30 May 2018 18:21:38 +1000 Subject: [PATCH 07/22] Reduce use of Settings in SSL --- .../xpack/core/ssl/SSLService.java | 4 +++- .../xpack/core/ssl/SSLServiceTests.java | 3 +-- .../security/PkiRealmBootstrapCheck.java | 2 +- .../xpack/security/Security.java | 19 ++++++++----------- .../SecurityNetty4HttpServerTransport.java | 4 +--- 5 files changed, 14 insertions(+), 18 deletions(-) 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 cf9e1184f959c..a9b7b295495a7 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 @@ -231,7 +231,9 @@ public boolean isConfigurationValidForServerUsage(SSLConfiguration sslConfigurat * Indicates whether client authentication is enabled for a particular configuration * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. The global configuration * will be used for fallback + * @deprecated Use {@link #isSSLClientAuthEnabled(SSLConfiguration)} with {@link #getSSLConfiguration(String)} */ + @Deprecated public boolean isSSLClientAuthEnabled(Settings settings) { return isSSLClientAuthEnabled(settings, Settings.EMPTY); } @@ -637,7 +639,7 @@ private static Map getTransportProfileSSLSettings(Settings set return sslSettings; } - public static Settings getHttpTransportSSLSettings(Settings settings) { + private Settings getHttpTransportSSLSettings(Settings settings) { Settings httpSSLSettings = settings.getByPrefix(XPackSettings.HTTP_SSL_PREFIX); if (httpSSLSettings.isEmpty()) { return httpSSLSettings; 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 127e5da8babc0..4105db4cbd3bc 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 @@ -291,8 +291,7 @@ public void testThatHttpClientAuthDefaultsToNone() throws Exception { final SSLConfiguration globalConfig = sslService.sslConfiguration(Settings.EMPTY); assertThat(globalConfig.sslClientAuth(), is(SSLClientAuth.OPTIONAL)); - final Settings httpSettings = SSLService.getHttpTransportSSLSettings(globalSettings); - final SSLConfiguration httpConfig = sslService.sslConfiguration(httpSettings); + final SSLConfiguration httpConfig = sslService.getHttpTransportSSLConfiguration(); assertThat(httpConfig.sslClientAuth(), is(SSLClientAuth.NONE)); } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java index dcc2308f9f0c1..0f4fc05b512e8 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java @@ -39,7 +39,7 @@ class PkiRealmBootstrapCheck implements BootstrapCheck { private List loadSslConfigurations(Settings settings) { final List list = new ArrayList<>(); if (HTTP_SSL_ENABLED.get(settings)) { - list.add(sslService.sslConfiguration(SSLService.getHttpTransportSSLSettings(settings), Settings.EMPTY)); + list.add(sslService.getHttpTransportSSLConfiguration()); } if (XPackSettings.TRANSPORT_SSL_ENABLED.get(settings)) { 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 6d12b6472f18f..12f1dcf157fd9 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 @@ -7,7 +7,6 @@ import org.apache.logging.log4j.Logger; import org.apache.lucene.util.SetOnce; -import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; @@ -17,7 +16,6 @@ import org.elasticsearch.bootstrap.BootstrapCheck; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; @@ -112,7 +110,6 @@ import org.elasticsearch.xpack.core.security.authc.DefaultAuthenticationFailureHandler; import org.elasticsearch.xpack.core.security.authc.Realm; import org.elasticsearch.xpack.core.security.authc.RealmSettings; -import org.elasticsearch.xpack.core.security.authc.TokenMetaData; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.authz.AuthorizationServiceField; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; @@ -121,16 +118,17 @@ import org.elasticsearch.xpack.core.security.authz.accesscontrol.SetSecurityUserProcessor; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; -import org.elasticsearch.xpack.security.authz.store.FileRolesStore; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; import org.elasticsearch.xpack.core.security.user.AnonymousUser; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.core.ssl.TLSLicenseBootstrapCheck; import org.elasticsearch.xpack.core.ssl.action.GetCertificateInfoAction; import org.elasticsearch.xpack.core.ssl.action.TransportGetCertificateInfoAction; import org.elasticsearch.xpack.core.ssl.rest.RestGetCertificateInfoAction; +import org.elasticsearch.xpack.core.template.TemplateUtils; import org.elasticsearch.xpack.security.action.filter.SecurityActionFilter; import org.elasticsearch.xpack.security.action.interceptor.BulkShardRequestInterceptor; import org.elasticsearch.xpack.security.action.interceptor.IndicesAliasesRequestInterceptor; @@ -176,6 +174,7 @@ import org.elasticsearch.xpack.security.authz.SecuritySearchOperationListener; import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; +import org.elasticsearch.xpack.security.authz.store.FileRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.rest.SecurityRestFilter; import org.elasticsearch.xpack.security.rest.action.RestAuthenticateAction; @@ -204,7 +203,6 @@ import org.elasticsearch.xpack.security.transport.filter.IPFilter; import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4HttpServerTransport; import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4ServerTransport; -import org.elasticsearch.xpack.core.template.TemplateUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -233,9 +231,9 @@ import static java.util.Collections.singletonList; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin, DiscoveryPlugin, MapperPlugin, ExtensiblePlugin { @@ -864,10 +862,9 @@ public UnaryOperator getRestHandlerWrapper(ThreadContext threadCont return null; } final boolean ssl = HTTP_SSL_ENABLED.get(settings); - Settings httpSSLSettings = SSLService.getHttpTransportSSLSettings(settings); - boolean extractClientCertificate = ssl && getSslService().isSSLClientAuthEnabled(httpSSLSettings); - return handler -> new SecurityRestFilter(getLicenseState(), threadContext, authcService.get(), handler, - extractClientCertificate); + final SSLConfiguration httpSSLConfig = getSslService().getHttpTransportSSLConfiguration(); + boolean extractClientCertificate = ssl && getSslService().isSSLClientAuthEnabled(httpSSLConfig); + return handler -> new SecurityRestFilter(getLicenseState(), threadContext, authcService.get(), handler, extractClientCertificate); } @Override diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransport.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransport.java index 01916b9138031..00c88fde743a7 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransport.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransport.java @@ -32,7 +32,6 @@ public class SecurityNetty4HttpServerTransport extends Netty4HttpServerTransport { private final IPFilter ipFilter; - private final Settings sslSettings; private final SSLService sslService; private final SSLConfiguration sslConfiguration; @@ -42,10 +41,9 @@ public SecurityNetty4HttpServerTransport(Settings settings, NetworkService netwo super(settings, networkService, bigArrays, threadPool, xContentRegistry, dispatcher); this.ipFilter = ipFilter; final boolean ssl = HTTP_SSL_ENABLED.get(settings); - this.sslSettings = SSLService.getHttpTransportSSLSettings(settings); this.sslService = sslService; if (ssl) { - this.sslConfiguration = sslService.sslConfiguration(sslSettings, Settings.EMPTY); + this.sslConfiguration = sslService.getHttpTransportSSLConfiguration(); 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 " + "[xpack.security.http.ssl.key] or [xpack.security.http.ssl.keystore.path] setting"); From bee987c4725f11b3fc01007897a12bafcc0cc101 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 12 Jun 2018 20:48:23 +1000 Subject: [PATCH 08/22] Improve SSLService tests --- .../xpack/core/ssl/SSLService.java | 6 +- .../xpack/core/ssl/SSLServiceTests.java | 60 +++++++++++++------ 2 files changed, 48 insertions(+), 18 deletions(-) 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 d6106d04faf27..e53360fc56518 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 @@ -12,6 +12,7 @@ import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.xpack.core.XPackSettings; @@ -30,6 +31,7 @@ import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; + import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -224,6 +226,7 @@ public SSLEngine createSSLEngine(SSLConfiguration configuration, String host, in * @param sslConfiguration the configuration to check */ public boolean isConfigurationValidForServerUsage(SSLConfiguration sslConfiguration) { + Objects.requireNonNull(sslConfiguration, "SSLConfiguration cannot be null"); return sslConfiguration.keyConfig() != KeyConfig.NONE; } @@ -253,6 +256,7 @@ public boolean isSSLClientAuthEnabled(Settings settings, Settings fallback) { * Indicates whether client authentication is enabled for a particular configuration */ public boolean isSSLClientAuthEnabled(SSLConfiguration sslConfiguration) { + Objects.requireNonNull(sslConfiguration, "SSLConfiguration cannot be null"); return sslConfiguration.sslClientAuth().enabled(); } @@ -634,7 +638,7 @@ private static Map getTransportProfileSSLSettings(Settings set for (Entry entry : profiles.entrySet()) { Settings profileSettings = entry.getValue().getByPrefix("xpack.security.ssl."); if (profileSettings.isEmpty() == false) { - sslSettings.put("transport.profiles." + entry.getKey() + "xpack.security.ssl", profileSettings); + sslSettings.put("transport.profiles." + entry.getKey() + ".xpack.security.ssl", profileSettings); } } return sslSettings; 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 3eaabc05d0500..9f2676d68ff2d 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 @@ -38,7 +38,6 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509ExtendedTrustManager; - import java.nio.file.Path; import java.security.AccessController; import java.security.PrivilegedActionException; @@ -118,6 +117,11 @@ public void testThatCustomTruststoreCanBeSpecified() throws Exception { SSLConfiguration configuration1 = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); SSLEngine sslEngine = sslService.createSSLEngine(configuration1, null, -1); assertThat(sslEngineWithTruststore, is(not(sameInstance(sslEngine)))); + + final SSLConfiguration profileConfiguration = sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl"); + assertThat(profileConfiguration, notNullValue()); + assertThat(profileConfiguration.trustConfig(), instanceOf(StoreTrustConfig.class)); + assertThat(((StoreTrustConfig) profileConfiguration.trustConfig()).trustStorePath, equalTo(testClientStore.toString())); } public void testThatSslContextCachingWorks() throws Exception { @@ -134,6 +138,10 @@ public void testThatSslContextCachingWorks() throws Exception { SSLContext cachedSslContext = sslService.sslContext(); assertThat(sslContext, is(sameInstance(cachedSslContext))); + + final SSLConfiguration configuration = sslService.getSSLConfiguration("_global"); + final SSLContext configContext = sslService.sslContext(configuration); + assertThat(configContext, is(sameInstance(sslContext))); } public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { @@ -149,6 +157,9 @@ public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { final SSLService sslService = new SSLService(settings, env); SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); sslService.createSSLEngine(configuration, null, -1); + + configuration = sslService.getSSLConfiguration("_global"); + sslService.createSSLEngine(configuration, null, -1); } public void testIncorrectKeyPasswordThrowsException() throws Exception { @@ -186,7 +197,7 @@ public void testThatSSLv3IsNotEnabled() throws Exception { public void testThatCreateClientSSLEngineWithoutAnySettingsWorks() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngine, notNullValue()); } @@ -199,7 +210,7 @@ public void testThatCreateSSLEngineWithOnlyTruststoreWorks() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngine, notNullValue()); } @@ -215,7 +226,7 @@ public void testCreateWithKeystoreIsValidForServer() throws Exception { .build(); SSLService sslService = new SSLService(settings, env); - assertTrue(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration(Settings.EMPTY))); + assertTrue(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); } public void testValidForServerWithFallback() throws Exception { @@ -227,7 +238,7 @@ public void testValidForServerWithFallback() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - assertFalse(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration(Settings.EMPTY))); + assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode"); settings = Settings.builder() @@ -238,10 +249,11 @@ public void testValidForServerWithFallback() throws Exception { .put("xpack.security.transport.ssl.keystore.type", testnodeStoreType) .build(); sslService = new SSLService(settings, env); - assertFalse(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration(Settings.EMPTY))); + assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); assertTrue(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration( settings.getByPrefix("xpack.security.transport.ssl.")))); - assertFalse(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration(Settings.EMPTY))); + assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); + assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("_transport"))); } public void testGetVerificationMode() throws Exception { @@ -279,6 +291,9 @@ public void testIsSSLClientAuthEnabled() throws Exception { assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("xpack.security.transport.ssl."), Settings.EMPTY)); assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("transport.profiles.foo.xpack.security.ssl."), settings.getByPrefix("xpack.security.transport.ssl."))); + + assertFalse(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("_global"))); + assertTrue(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("_transport"))); } public void testThatHttpClientAuthDefaultsToNone() throws Exception { @@ -288,7 +303,7 @@ public void testThatHttpClientAuthDefaultsToNone() throws Exception { .build(); final SSLService sslService = new SSLService(globalSettings, env); - final SSLConfiguration globalConfig = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration globalConfig = globalConfiguration(sslService); assertThat(globalConfig.sslClientAuth(), is(SSLClientAuth.OPTIONAL)); final SSLConfiguration httpConfig = sslService.getHttpTransportSSLConfiguration(); @@ -333,7 +348,7 @@ public void testCiphersAndInvalidCiphersWork() throws Exception { .putList("xpack.ssl.ciphers", ciphers.toArray(new String[ciphers.size()])) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(engine, is(notNullValue())); String[] enabledCiphers = engine.getEnabledCipherSuites(); @@ -364,7 +379,7 @@ public void testThatSSLEngineHasCipherSuitesOrderSet() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(engine, is(notNullValue())); assertTrue(engine.getSSLParameters().getUseCipherSuitesOrder()); @@ -379,7 +394,7 @@ public void testThatSSLSocketFactoryHasProperCiphersAndProtocols() throws Except .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + SSLConfiguration config = globalConfiguration(sslService); final SSLSocketFactory factory = sslService.sslSocketFactory(config); final String[] ciphers = sslService.supportedCiphers(factory.getSupportedCipherSuites(), config.cipherSuites(), false); assertThat(factory.getDefaultCipherSuites(), is(ciphers)); @@ -404,11 +419,10 @@ public void testThatSSLEngineHasProperCiphersAndProtocols() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); - SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); - final String[] ciphers = sslService.supportedCiphers(engine.getSupportedCipherSuites(), config.cipherSuites(), false); - final String[] supportedProtocols = config.supportedProtocols().toArray(Strings.EMPTY_ARRAY); + final String[] ciphers = sslService.supportedCiphers(engine.getSupportedCipherSuites(), configuration.cipherSuites(), false); + final String[] supportedProtocols = configuration.supportedProtocols().toArray(Strings.EMPTY_ARRAY); assertThat(engine.getEnabledCipherSuites(), is(ciphers)); assertArrayEquals(ciphers, engine.getSSLParameters().getCipherSuites()); // the order we set the protocols in is not going to be what is returned as internally the JDK may sort the versions @@ -613,7 +627,7 @@ public void testThatSSLContextTrustsJDKTrustedCAs() throws Exception { @Network public void testThatSSLIOSessionStrategyWithoutSettingsWorks() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - SSLConfiguration sslConfiguration = sslService.sslConfiguration(Settings.EMPTY); + SSLConfiguration sslConfiguration = globalConfiguration(sslService); logger.info("SSL Configuration: {}", sslConfiguration); SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(sslConfiguration); try (CloseableHttpAsyncClient client = getAsyncHttpClient(sslStrategy)) { @@ -634,7 +648,8 @@ public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { .put("xpack.ssl.keystore.path", testclientStore) .setSecureSettings(secureSettings) .build(); - SSLIOSessionStrategy sslStrategy = new SSLService(settings, env).sslIOSessionStrategy(Settings.EMPTY); + final SSLService sslService = new SSLService(settings, env); + SSLIOSessionStrategy sslStrategy = sslService.sslIOSessionStrategy(globalConfiguration(sslService)); try (CloseableHttpAsyncClient client = getAsyncHttpClient(sslStrategy)) { client.start(); @@ -644,6 +659,17 @@ public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { } } + private static SSLConfiguration globalConfiguration(SSLService sslService) { + if (randomBoolean()) { + return sslService.getSSLConfiguration("_global"); + } + if (randomBoolean()) { + return sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + } else { + return sslService.sslConfiguration(Settings.EMPTY); + } + } + class AssertionCallback implements FutureCallback { @Override From 7c060d74865b822ff6b3b1a88a2ccb11057b620f Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 12 Jun 2018 21:05:45 +1000 Subject: [PATCH 09/22] Small cleanup --- .../java/org/elasticsearch/xpack/core/ssl/SSLService.java | 4 ++-- .../org/elasticsearch/xpack/core/ssl/SSLServiceTests.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 e53360fc56518..296bff9a0177e 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 @@ -12,7 +12,6 @@ import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.xpack.core.XPackSettings; @@ -290,7 +289,8 @@ SSLContext sslContext(SSLConfiguration configuration) { * @throws IllegalArgumentException if not found */ SSLContextHolder sslContextHolder(SSLConfiguration sslConfiguration) { - SSLContextHolder holder = sslContexts.get(Objects.requireNonNull(sslConfiguration, "SSL Configuration cannot be null")); + Objects.requireNonNull(sslConfiguration, "SSL Configuration cannot be null"); + SSLContextHolder holder = sslContexts.get(sslConfiguration); if (holder == null) { throw new IllegalArgumentException("did not find a SSLContext for [" + sslConfiguration.toString() + "]"); } 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 9f2676d68ff2d..b7a3cd443fa2b 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 @@ -114,8 +114,8 @@ public void testThatCustomTruststoreCanBeSpecified() throws Exception { SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngineWithTruststore, is(not(nullValue()))); - SSLConfiguration configuration1 = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); - SSLEngine sslEngine = sslService.createSSLEngine(configuration1, null, -1); + SSLConfiguration globalConfig = globalConfiguration(sslService); + SSLEngine sslEngine = sslService.createSSLEngine(globalConfig, null, -1); assertThat(sslEngineWithTruststore, is(not(sameInstance(sslEngine)))); final SSLConfiguration profileConfiguration = sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl"); From 1aa0c14ea13f739fc24d7273cdf2f9adcff1b5e1 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 14 Jun 2018 16:10:06 +1000 Subject: [PATCH 10/22] Add additional test for named SSL configurations --- .../xpack/core/ssl/SSLServiceTests.java | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) 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 b7a3cd443fa2b..b23bfb22834fa 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 @@ -477,7 +477,74 @@ public void testEmptyTrustManager() throws Exception { assertThat(trustManager.getAcceptedIssuers(), emptyArray()); } - public void testReadCertificateInformation() throws Exception { + + public void testGetConfigurationByContextName() throws Exception { + final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, null, null); + final String[] cipherSuites = sslContext.getSupportedSSLParameters().getCipherSuites(); + + final MockSecureSettings secureSettings = new MockSecureSettings(); + secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.http.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.security.http.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("transport.profiles.prof1.xpack.security.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("transport.profiles.prof2.xpack.security.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("transport.profiles.prof3.xpack.security.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.security.authc.realms.realm1.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.security.authc.realms.realm2.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.monitoring.exporters.mon1.ssl.keystore.secure_password", "testnode"); + secureSettings.setString("xpack.monitoring.exporters.mon2.ssl.keystore.secure_password", "testnode"); + + // Here we use a different ciphers for each context, to we can check that the returned SSLConfiguration matches the + // provided settings + final Iterator cipher = Arrays.asList(cipherSuites).iterator(); + + final Settings settings = Settings.builder() + .put("xpack.ssl.keystore.path", testnodeStore) + .putList("xpack.ssl.cipher_suites", cipher.next()) + .put("xpack.http.ssl.keystore.path", testnodeStore) + .putList("xpack.http.ssl.cipher_suites", cipher.next()) + .put("xpack.security.http.ssl.keystore.path", testnodeStore) + .putList("xpack.security.http.ssl.cipher_suites", cipher.next()) + .put("xpack.security.transport.ssl.keystore.path", testnodeStore) + .putList("xpack.security.transport.ssl.cipher_suites", cipher.next()) + .put("transport.profiles.prof1.xpack.security.ssl.keystore.path", testnodeStore) + .putList("transport.profiles.prof1.xpack.security.ssl.cipher_suites", cipher.next()) + .put("transport.profiles.prof2.xpack.security.ssl.keystore.path", testnodeStore) + .putList("transport.profiles.prof2.xpack.security.ssl.cipher_suites", cipher.next()) + .put("transport.profiles.prof3.xpack.security.ssl.keystore.path", testnodeStore) + .putList("transport.profiles.prof3.xpack.security.ssl.cipher_suites", cipher.next()) + .put("xpack.security.authc.realms.realm1.ssl.keystore.path", testnodeStore) + .putList("xpack.security.authc.realms.realm1.ssl.cipher_suites", cipher.next()) + .put("xpack.security.authc.realms.realm2.ssl.keystore.path", testnodeStore) + .putList("xpack.security.authc.realms.realm2.ssl.cipher_suites", cipher.next()) + .put("xpack.monitoring.exporters.mon1.ssl.keystore.path", testnodeStore) + .putList("xpack.monitoring.exporters.mon1.ssl.cipher_suites", cipher.next()) + .put("xpack.monitoring.exporters.mon2.ssl.keystore.path", testnodeStore) + .putList("xpack.monitoring.exporters.mon2.ssl.cipher_suites", cipher.next()) + .setSecureSettings(secureSettings) + .build(); + SSLService sslService = new SSLService(settings, env); + + final String[] context = new String[]{"_global", + "xpack.http.ssl", "xpack.security.http.ssl", + "_transport", "transport.profiles.prof1.xpack.security.ssl", + "transport.profiles.prof2.xpack.security.ssl", "transport.profiles.prof3.xpack.security.ssl" + , "xpack.security.authc.realms.realm1.ssl", "xpack.security.authc.realms.realm2.ssl", + "xpack.monitoring.exporters.mon1.ssl", "xpack.monitoring.exporters.mon2.ssl"}; + for (int i = 0; i < context.length; i++) { + final String name = context[i]; + final SSLConfiguration configuration = sslService.getSSLConfiguration(name); + assertThat("Configuration for " + name, configuration, notNullValue()); + assertThat("KeyStore for " + name, configuration.keyConfig(), instanceOf(StoreKeyConfig.class)); + final StoreKeyConfig keyConfig = (StoreKeyConfig) configuration.keyConfig(); + assertThat("KeyStore Path for " + name, keyConfig.keyStorePath, equalTo(testnodeStore.toString())); + assertThat("Cipher for " + name, configuration.cipherSuites(), contains(cipherSuites[i])); + } + } + + public void testReadCertificateInformation () throws Exception { final Path jksPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"); final Path p12Path = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12"); final Path pemPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/active-directory-ca.crt"); From ee32357d409dc8fc07167a6c4d299bd2ed187dd3 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 14 Jun 2018 19:03:43 +1000 Subject: [PATCH 11/22] Remove unused imports --- .../xpack/security/transport/ssl/SslIntegrationTests.java | 1 - .../src/test/java/org/elasticsearch/test/OpenLdapTests.java | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java index 33019719f1285..c176a4a7fd69f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java @@ -29,7 +29,6 @@ import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.ssl.SSLConfiguration; -import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.LocalStateSecurity; diff --git a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java index b2d7b9490e6cc..c6d541b8064fd 100644 --- a/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java +++ b/x-pack/qa/openldap-tests/src/test/java/org/elasticsearch/test/OpenLdapTests.java @@ -16,7 +16,6 @@ import org.elasticsearch.common.util.concurrent.UncategorizedExecutionException; import org.elasticsearch.env.Environment; import org.elasticsearch.env.TestEnvironment; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.authc.RealmConfig; From 42e3aa17ced6a6f909897d39ac548d2c3bbddde2 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 18 Jun 2018 16:17:20 +1000 Subject: [PATCH 12/22] Fix test (feedback) --- .../org/elasticsearch/xpack/core/ssl/SSLServiceTests.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 b23bfb22834fa..186f8af8fd919 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 @@ -155,10 +155,7 @@ public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { .setSecureSettings(secureSettings) .build(); final SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); - sslService.createSSLEngine(configuration, null, -1); - - configuration = sslService.getSSLConfiguration("_global"); + SSLConfiguration configuration = globalConfiguration(sslService); sslService.createSSLEngine(configuration, null, -1); } From 2eb845a792a62776b51e735f15c643b84b639d10 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Mon, 9 Jul 2018 23:14:15 +1000 Subject: [PATCH 13/22] Fix monitoring to work with dynamic SSL settings - Prevent dynamic changes to SSL settings that also use secure settings - Dyanmically rebuild SSL context for exporters that don't use secure setting --- .../core/ssl/SSLConfigurationSettings.java | 8 + .../xpack/monitoring/exporter/Exporters.java | 1 + .../exporter/http/HttpExporter.java | 37 +++- .../exporter/http/HttpSslExporterIT.java | 186 ++++++++++++++++++ .../monitoring/exporter/http/testnode.jks | Bin 0 -> 9360 bytes 5 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java create mode 100644 x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationSettings.java index 8952619408b4a..0cc01270ced53 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationSettings.java @@ -22,6 +22,8 @@ import java.util.Locale; import java.util.Optional; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Bridges SSLConfiguration into the {@link Settings} framework, using {@link Setting} objects. @@ -221,4 +223,10 @@ public static Collection> getProfileSettings() { CLIENT_AUTH_SETTING_PROFILES, VERIFICATION_MODE_SETTING_PROFILES); } + public List> getSecureSettingsInUse(Settings settings) { + return Stream.of(this.truststorePassword, this.x509KeyPair.keystorePassword, + this.x509KeyPair.keystoreKeyPassword, this.x509KeyPair.keyPassword) + .filter(s -> s.exists(settings)) + .collect(Collectors.toList()); + } } diff --git a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java index 9333a2f81dbeb..40c95384d5349 100644 --- a/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java +++ b/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java @@ -55,6 +55,7 @@ public Exporters(Settings settings, Map factories, this.licenseState = Objects.requireNonNull(licenseState); clusterService.getClusterSettings().addSettingsUpdateConsumer(this::setExportersSetting, getSettings()); + HttpExporter.registerSettingValidators(clusterService); // this ensures, that logging is happening by adding an empty consumer per affix setting for (Setting.AffixSetting affixSetting : getSettings()) { clusterService.getClusterSettings().addAffixUpdateConsumer(affixSetting, (s, o) -> {}, (s, o) -> {}); 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 65da413f8a3b6..54447c1646370 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 @@ -35,6 +35,7 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.xpack.core.monitoring.exporter.MonitoringTemplateUtils; import org.elasticsearch.xpack.core.ssl.SSLConfiguration; +import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.monitoring.exporter.ClusterAlertsUtil; import org.elasticsearch.xpack.monitoring.exporter.Exporter; @@ -51,6 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; /** * {@code HttpExporter} uses the low-level {@link RestClient} to connect to a user-specified set of nodes for exporting Monitoring @@ -253,6 +255,30 @@ public HttpExporter(final Config config, final SSLService sslService, final Thre listener.setResource(resource); } + /** + * Adds a validator for the {@link #SSL_SETTING} to prevent dynamic updates when secure settings also exist within that setting + * groups (ssl context). + * Because it is not possible to re-read the secure settings during a dynamic update, we cannot rebuild the {@link SSLIOSessionStrategy} + * (see {@link #configureSecurity(RestClientBuilder, Config, SSLService)} if this exporter has been configured with secure settings + */ + public static void registerSettingValidators(ClusterService clusterService) { + clusterService.getClusterSettings().addAffixUpdateConsumer(SSL_SETTING, + (ignoreKey, ignoreSettings) -> { + // no-op update. We only care about the validator + }, + (namespace, settings) -> { + final List secureSettings = SSLConfigurationSettings.withoutPrefix() + .getSecureSettingsInUse(settings) + .stream() + .map(Setting::getKey) + .collect(Collectors.toList()); + if (secureSettings.isEmpty() == false) { + throw new IllegalStateException("Cannot dynamically update SSL settings for the exporter [" + namespace + + "] as it depends on the secure setting(s) [" + Strings.collectionToCommaDelimitedString(secureSettings) + "]"); + } + }); + } + /** * Create a {@link RestClientBuilder} from the HTTP Exporter's {@code config}. * @@ -445,12 +471,17 @@ private static void configureHeaders(final RestClientBuilder builder, final Conf */ private static void configureSecurity(final RestClientBuilder builder, final Config config, final SSLService sslService) { final Setting concreteSetting = SSL_SETTING.getConcreteSettingForNamespace(config.name()); - final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(concreteSetting.getKey()); + final Settings sslSettings = concreteSetting.get(config.settings()); final SSLIOSessionStrategy sslStrategy; - if (sslConfiguration == null) { - final Settings sslSettings = concreteSetting.get(config.settings()); + if (SSLConfigurationSettings.withoutPrefix().getSecureSettingsInUse(sslSettings).isEmpty()) { + // This configuration does not use secure settings, so it is possible that is has been dynamically updated. + // We need to load a new SSL strategy in case these settings differ from the ones that the SSL service was configured with. sslStrategy = sslService.sslIOSessionStrategy(sslSettings); } else { + // 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 CredentialsProvider credentialsProvider = createCredentialsProvider(config); diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java new file mode 100644 index 0000000000000..8ca8975165c4c --- /dev/null +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java @@ -0,0 +1,186 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.monitoring.exporter.http; + +import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; +import org.elasticsearch.common.settings.MockSecureSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.ESIntegTestCase.Scope; +import org.elasticsearch.test.http.MockWebServer; +import org.elasticsearch.xpack.core.ssl.TestsSSLService; +import org.elasticsearch.xpack.core.ssl.VerificationMode; +import org.elasticsearch.xpack.monitoring.exporter.Exporter; +import org.elasticsearch.xpack.monitoring.exporter.Exporters; +import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.notNullValue; + +@ESIntegTestCase.ClusterScope(scope = Scope.SUITE, + numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0, supportsDedicatedMasters = false) +public class HttpSslExporterIT extends MonitoringIntegTestCase { + + private final Settings globalSettings = Settings.builder().put("path.home", createTempDir()).build(); + private final Environment environment = TestEnvironment.newEnvironment(globalSettings); + + private static MockWebServer webServer; + private static Path keystore; + private MockSecureSettings secureSettings; + + + @After + public void stopWebServer() { + if (webServer != null) { + webServer.close(); + } + } + + @Override + protected boolean ignoreExternalCluster() { + return true; + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + if (keystore == null) { + keystore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); + assertThat(Files.exists(keystore), CoreMatchers.is(true)); + } + + if (webServer == null) { + try { + webServer = buildWebServer(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + final String address = "https://" + webServer.getHostName() + ":" + webServer.getPort(); + final Settings.Builder builder = Settings.builder() + .put(super.nodeSettings(nodeOrdinal)) + .put("xpack.monitoring.exporters.plaintext.type", "http") + .put("xpack.monitoring.exporters.plaintext.enabled", true) + .put("xpack.monitoring.exporters.plaintext.host", address) + .put("xpack.monitoring.exporters.plaintext.ssl.truststore.path", keystore) + .put("xpack.monitoring.exporters.plaintext.ssl.truststore.password", "testnode") + .put("xpack.monitoring.exporters.secure.type", "http") + .put("xpack.monitoring.exporters.secure.enabled", true) + .put("xpack.monitoring.exporters.secure.host", address) + .put("xpack.monitoring.exporters.secure.ssl.truststore.path", keystore); + + secureSettings = new MockSecureSettings(); + secureSettings.setString("xpack.monitoring.exporters.secure.ssl.truststore.secure_password", "testnode"); + builder.setSecureSettings(secureSettings); + + return builder.build(); + } + + private MockWebServer buildWebServer() throws IOException { + final Settings sslSettings = Settings.builder() + .put("xpack.ssl.keystore.path", keystore) + .put("xpack.ssl.keystore.password", "testnode") + .put(globalSettings) + .build(); + + TestsSSLService sslService = new TestsSSLService(sslSettings, environment); + final SSLContext sslContext = sslService.sslContext(Settings.EMPTY); + MockWebServer server = new MockWebServer(sslContext, false); + server.start(); + return server; + } + + @Before + // Force the exporters to be built from closed secure settings (as they would be in a production environment) + public void closeSecureSettings() throws IOException { + if (secureSettings != null) { + secureSettings.close(); + } + } + + public void testCannotUpdateSslSettingsWithSecureSettings() throws Exception { + // Verify that it was created even though it has a secure setting + assertExporterExists("secure"); + + // Verify that we cannot modify the SSL settings + final ActionFuture future = setVerificationMode("secure", VerificationMode.CERTIFICATE); + final IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, future::actionGet); + assertThat(iae.getCause(), instanceOf(IllegalStateException.class)); + assertThat(iae.getCause().getMessage(), containsString("secure_password")); + } + + public void testCanUpdateSslSettingsWithNoSecureSettings() { + final ActionFuture future = setVerificationMode("plaintext", VerificationMode.CERTIFICATE); + final ClusterUpdateSettingsResponse response = future.actionGet(); + assertThat(response, notNullValue()); + clearTransientSettings("plaintext"); + } + + public void testCanAddNewExporterWithSsl() { + Path truststore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); + assertThat(Files.exists(truststore), CoreMatchers.is(true)); + + final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); + final Settings settings = Settings.builder() + .put("xpack.monitoring.exporters._new.type", "http") + .put("xpack.monitoring.exporters._new.host", "https://" + webServer.getHostName() + ":" + webServer.getPort()) + .put("xpack.monitoring.exporters._new.ssl.truststore.path", truststore) + .put("xpack.monitoring.exporters._new.ssl.truststore.password", "testnode") + .put("xpack.monitoring.exporters._new.ssl.verification_mode", VerificationMode.NONE.name()) + .build(); + updateSettings.transientSettings(settings); + final ActionFuture future = client().admin().cluster().updateSettings(updateSettings); + final ClusterUpdateSettingsResponse response = future.actionGet(); + assertThat(response, notNullValue()); + + assertExporterExists("_new"); + clearTransientSettings("_new"); + } + + private void assertExporterExists(String secure) { + final Exporter httpExporter = getExporter(secure); + assertThat(httpExporter, notNullValue()); + assertThat(httpExporter, instanceOf(HttpExporter.class)); + } + + private Exporter getExporter(String name) { + final Exporters exporters = internalCluster().getInstance(Exporters.class); + assertThat(exporters, notNullValue()); + return exporters.getExporter(name); + } + + private ActionFuture setVerificationMode(String name, VerificationMode mode) { + final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); + final Settings settings = Settings.builder() + .put("xpack.monitoring.exporters." + name + ".ssl.verification_mode", mode.name()) + .build(); + updateSettings.transientSettings(settings); + return client().admin().cluster().updateSettings(updateSettings); + } + + private void clearTransientSettings(String... names) { + final ClusterUpdateSettingsRequest updateSettings = new ClusterUpdateSettingsRequest(); + final Settings.Builder builder = Settings.builder(); + for (String name : names) { + builder.put("xpack.monitoring.exporters." + name + ".*", (String) null); + } + updateSettings.transientSettings(builder.build()); + client().admin().cluster().updateSettings(updateSettings).actionGet(); + } +} diff --git a/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks b/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks new file mode 100644 index 0000000000000000000000000000000000000000..ebe6146124e8fd607e46a1a3129bdf9b4de0370d GIT binary patch literal 9360 zcmdUV2T)YowrzLQl93!F2SGC3WF$w)IfLYGK$2vT*iDigl`N7oh@eEt83BokWI;th zKok%V_zil_#dF{N=hmxN@83^VSMRxd)mp3enq$l{$L93&>1O}{0788*FTTk=VD28y zE;cYOYe##Svj^8*Hy60QBMbllY8=Nx4**vTxdk91003Gv1c?>_L4sT!qk(`R5Eh_) zU50G!4F3%T4;_m=TrvCr4+zA$0)Q|==^?b}XnJ5Y;(s+egq9o+ikg;}4=OCcDIVy2IuGcP39Gn>U% zK!zH|Y#zr76z$THNrVtl2Hz*duE|_x{SHKW=Wy9~#x0?_!WxzreKbBd_{B!%FFc+} z#hS1iA!Ph9s*KL}5ZCWMX)1FD)R@OQManE3e-@+qd0nOC5~I@Wvv)K719(Ez^^D!& zt6;h^oFHXs|H>4zGnJ%}f+`Pp>rEdE;=+o<-25$T9lIy1B0c;S!Z_r&_k6nwupM+P z`QIj_3i+10?X14(vmJKmiZElETC3=_VBSWbe19M>na%UTgjKu!)Hb0X5AJ>=1@Lw7vcxjN}1eMG&CU^70?>@)@Jj3w6do zK=}wbX`7exBW2Hy$yVaDo$ICp=}fYb@;nQCWlEe6F`UeJ?OsbuRMGQ zgd{VQ1`}qlEo37p4u-{8N|I&os?=jM_S_F93rh*dwGvc4>^v;F@<@1%AfI?JIxoOG#d{a^ zfIt8&OKT5%FPM$J8|t~~u}>Z;{sXMDD6qapfwk=?SP2aA8Y;D$$)co!mluiHCH4RE zP$7X(VhABRHdYc#Wb!Vj4e%Nnnzf4)lmZJVJR-@b8DwGjw9y}xw)Rb-X`tOZ@L?r7m{x$tD>pf-DK8J8PK&?Rve%UmMWfn zkY1J8$6e`6OS^j3!ZBdDpQ)-!J@JJ984?Dw%90 z9h9Kf+y~ zZ;X4CM_eV}GZ5(`=K*hqpZ8TuPP9ObD5GdI!|KXQ!DE#8?8q-!J#9& z<{0CP?#6ZZ#oFo@=oP4^3J28dh2~!eXSx~~6ipLu^f&9MPd~6p^1dZo&i#yysyksD zk}_18V>Qk~vQwzp^Jc<7;yAcH?9kbl>dg;vDb^QW7vRS}huY7Q{j*f_g#JtPV*wf` zQ+Jb8TG{^cI3dbVTnP3#FtLfzT-or(bOGc4(Y5{#j-5r{Ppfe;7RN>qhPm0{UaW%Vx1xCa5qm=3uM*tyDmx^f zYB_a@Gg~w4N2l?k$LGG^P!NIepM`u@h$CVHNvqI zC)X{Bme~#(ow!*Q{K^N&ikb6+rMH->KX;ZbN6hV7!(1Bu`qVw?;aP#3&Yrekzjpej zK?ev|N zXpSYGJX7Ur@l^_!fa=P>E&WMk1O|eS+U?%te$I}MSaKjCeWH%kki*#p`IR^ zVzx|rZ=W!gg0!F0H2VQ^^Fbof!}9le_))5Y=S5|6FO7Cv zbx_><@>*LeHI$ay>|Nv}{__#cG`gqE5HI=yy!zq2=%Sr>Y-uEp7wE@yxeIf4w6R19 z0pRVhFITw##6I{Y1PK;IRe#z)WcoxH4#%|zmFAbRe+4DeU7$D@vJi|;4ARs2BfumE z$x8ph0~o}3YA&A69w?nhuWt|Yh7v%o{$vY`Up(-~NEBoI#tcxx3+_iT2BrpTtEzI+ znim8i1QFsDfC}TOWK!IHlvq*$BEG}@fH_Cm@4K8Uq-IvD*m|7@F6Jq zuwGO-ZesCM!egNa*#)E@4QIrW8I23(sbgFL z-JqdF#j`8Vy}VmdE^%g2k0bzk-aO3BahcB5rNS zxl7R4(8SoexacwQK1c1P8)rsVPYAtP{l+gAnS>z5E){N%TZk`R&*4@b12lj~mK`oDh0NG!mg`Hy?PMdCk{$fc$gg@y}Zfu}F? zSu0-A5J<7i9~u3DF0|o^$U)%UsmE_ku>)^Gq%Eedjl|h!miFi4Sf0Lza4Yh$3`(a- zlSoW|GYZ|6+ksyVU2ZqAPbBTjepxQ8f5SX?^^wnbkC^~H#@eED&|5^5(CZW?&81lp zuK(Kl>+YUJ=bsA;AOPnN zL%!JXclJ}LX4jeGrIbUTc!v*~SOh1OiRa(L7uS+&TRqzL$=2m37@-?ugp z;<967zk5`#GF$mwu!!%bjbE#w?DiH;8#?Wzm57N|0FrE zn;pF<1Q#6>WkZaJqlDvMT!`PO>8EH>M_C>hj3f*ZfC@oG_ynO46eIBqKp_y`U*T^q z#J`%u2ttgGaj`B4_-g}bKnye)0C)>_&44m!Or)#1Ut8&;!v0wFl7XiLS&Hkpf6yQ+ zS$u^RL1(ei^U17X7FKiWIm_PUG%*qPkB-&%nj|U<+I{m8br3|&CFH3AtedxB3{(XP zEn%Zcf>g8WD}%`mB@~WM zp9uG(2Oy&6>W}bkjBJFW3kT}F6e9aa)BSXsD4RZ=aNVx{s&pychT8+Y$$l_!H^FaL z3LLd5q?EMk(g;f9FP8|X)yaCx6I!~n)nmu%`$=|;KQj#O^GGWI)jJJs z7>Ac9vNah6&K&AwA1hzS{iHejdVYVmZF*^BM|8K!2)nP`sY>CxeFi~sC&l{Y_0{O- zR3w-dQMDW`5;v=7NA6>dI8VL&`0&n)2=-n!aIaAxvy^GPc>jC8J0k!|&vN;X?e2o? zwky$-nw!ods}&g=K8Qr_j^(ku%x(XbPEm^7#X#04E>m|5a#SCvn|mjcA-(GfSo!6& zwo4GA-&byR`#aIaH8CYDzQA5wsTt$tD+m|9?pO*JTVtH)G_p-^rk-c&&hGLBJ0dr& z2HYnandk_~8S)LW z{)anZ&dF##-IbO!HlOrrA1oi$i|ZKRW2P#NW12=pa%4>IZtA*obM+ zUr`Tno4i}q5^Kd+o7JSL=5rZPlc46PloNW-aFxv_(_h*;*fV`daXfEiSnv3Vr)ub+ zGvw0>%{HX26_R#m)1Q}ov&mmtWdu>LrUjHJ2jK4u9jC@di^dq=M4hG)N(@7*Ibn94fDkgeZ1{bnK4+j=-Bc-b2kbl zB2~`9MlJg3nM9CMwMj#DMNZkY^(!}d=9l~B)2~-t=jY-H@fnybqV&{T6)llgafjWi zre8Oej@qni0pGukP;yElQPyUbR0vj64{6xhQ&{gaRu9*}FbDPDrKEY?oF2X`^?(_4 zmb)GR`9|N;k_xAaOKOcB-X5VI4lS)VpXq&hy5>;c=;P=Toe{dSmZd>q!5ROshhh@8 zezz8bnn9YgLPmvb&zHYGpx{ZvsYY(jgBa_`6ML+^wSF{M8|!4r?N-PPovp{FEv z=Pcib1<|(w1v)7kIBo9?+~*w?elzPllgNPEn;f9$IlZoM!$#4pBvCIflR?r-u)c6+ z(<;2~Ya?~aow*x1$ftJceu3cv-rdSCcqt5`!-iUS;QcI~^>3#oN1~~|xtRM0-|ar2 z-}HJmdu!h-8}h(C+}L*|A=$sKNQ*=nCXxLHm$0Of+U)vQ=e8;`-id27tf^>6nRV(o zD_35LMQCiXvc;2P5C$3ZExN#sI331)j7wM4?A}WR5y0vQHB4^!9Cb#LW2-5h8Wg_W zE?(7>&&`t(tsSfKU2gO8^6pwlf#)k(@H#E`*xxz}(ZGA`$b|V!H-7Eo_a;mxUQoaG z@iUWo&dy;${A)aMi66W&;E|)TL`@ITKe|!zaenPBdhYvMi9C1z&?Zn0VDle+KtrRW z&1xm~aLZ+Za#F!ldcDg52k7y8`+5HkKBT>PLT)EHQ+wS0?)^4H3rz7L`xRQ?0#5WuV4tJA^+R{Ul!N!Swi%8vAG}bX`+Jl z{oGbt`~Cx^#3hmbhxOmzd(GpA;JlOb?eHYV$_$QhVoRotB5vEjX~hRt_QbNfZtp`z zCa^jdlJCrmZdH&KP`Nvizsp}P9;bei0LINMRZ>umh z@wu?rUddcG(Rvf=W_VWZm(bV2C!R@~vHk=`B}z~dn3j-Xlqa^He3+oVCSlzhnr_T4 z7xI#}+RkP5Md<>pSR;^knyvj{LXvJ+Xj7FairmPhUH(WR%z8ECi!=5X-}D$9J9kN- zC$E~1Wqy*4yp5$n!!{%z@uufhdn+l@)27$nh~I1VmcvD^9)+Fcjc{mRqB-6n{4VXay+HKSqK6{!h@8K($I}H)GZL zd+vn7OSEuCTdiM0|B8QpC@%zZ-qoWKv;9Igy)4Yl!yayLZRr7{*L87mq?h*eaIu9s z!`x7JZ0LU(_QDWeC`vr@i$J00%{&wp^8X4Ugiw6cLKm~5yIVS0S@NUg`v3iXT_puI zWzN=ski(8IGp7|TpM;&i+%EXYl{BUj)_2s7CuR6q-a0@K^u0%!{YEWpYsrF1XERyZ zf$tMSTink}o&$ffH!`}Es;V{6M4j$g-H?#|zQ}jW+UO?yG=&aPZ`u&)cNLS#c$E%; zP1mx?uy^0lDm~1Sxl4AS3}fIGtsrpPzu9UsUFfLaHBjFbJbOC8(^<{SnS0n!StB#g zL}+<5vF5jPm0~0Vjt%Q?>}z(+kvmw*edbY` z@SqjXB|6rfvcCz`u_)Y;_+8ajHX`pJD&kNHczrrb!=?w{fiV124cV4iCdMz&zJwqK zE{Xo+XoqLy?Bk=64cI=0e(aTjm0Xe#m-AMZ32X;}2a~{K(-z>-Z{9+k8X@v&$i>E+ zQXRR%1%i z+gZhDOYfLI95J{tK}^7qxH4qdT=iwIXI;%~<(7x#tDq?=+?_Bwkrz$Q`TdVlR))UZ zB@j7mCy|Sc;&$|B7PbW~9eY=&!EdvD*IjQ)sB0(+cInMrs1{CN7*c3cOPQ|Rp{(Mt zOjz!_eLXl-Mnq|AsoQfh;NJug*Q+l)T z8)*rHeYv|M#Ut?%U?vsg>xas%hWwvYC#0-Sur)F2=FtkgqgCA#-e%z?+T?CPv=igi zT1bbmLe@F14M@f`Vd)CEd&TVRZ9lERix`Pv&Rj93@;7`u^|14k-pNBn{fTijp&Qtp z1B1q7E%*$Cjn_4DC1sJoqaH8jlQik)F@7bhGU9K_XgO4mt1xyV1wx@8p6R>!Z=zo} zJP|z{6Si_^2=pvzAdCS%KC?wD74V_1_=k2eaRNll~ zg_)0a(KkYGbiWo&D8{^z3der9T|L|venrzv_U)qcQ^$MFo;M|wFp-P!qEO(#sfdZ1oL-r?nXuCiHy2Qq0 ziM;!sUs2F`&Az?Mh;}V|OcB@zA_b&cXvUK=;k^R`-C{MPC+tX)V!8h%5RdT?@P(Uf7yaQA1qCnw{nH+*r>*BMBG9Ld(hllZ5Ey>&8FWz*Q!dPYoj zCzFk0KZGQUrz|3zXT|9#%3tEMsddw5y@{5+yMt>KbeorB%SpCOL#uM0uGFADE&g#g#^|1;Itr9?;L0YErGBwTfC_I{Rc$*iOkJ|A4=@L50Z x`UE0joFCFX(i+qD)1h^DcPJOtN>)kRbQgMUO*p!K@AKymmi%I+{Ip*({}0#og{%Mo literal 0 HcmV?d00001 From 255a42ece69d05d628c7d647eacd716a9e9efc9b Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 10 Jul 2018 17:30:52 +1000 Subject: [PATCH 14/22] Cleanup test static vars --- .../xpack/monitoring/exporter/http/HttpSslExporterIT.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java index 8ca8975165c4c..5bdc3655b38fe 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java @@ -22,6 +22,7 @@ import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; import org.hamcrest.CoreMatchers; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; import javax.net.ssl.SSLContext; @@ -45,11 +46,13 @@ public class HttpSslExporterIT extends MonitoringIntegTestCase { private MockSecureSettings secureSettings; - @After - public void stopWebServer() { + @AfterClass + public static void cleanUpStatics() { if (webServer != null) { webServer.close(); + webServer = null; } + keystore = null; } @Override From 8ea7e354629dc36493512b68f91fb9b2d729fa34 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 10 Jul 2018 18:25:37 +1000 Subject: [PATCH 15/22] Address feedback from @jaymode (round 1) --- .../xpack/core/ssl/SSLService.java | 42 ++++++---- .../xpack/core/ssl/SSLServiceTests.java | 76 ++++++++++--------- 2 files changed, 68 insertions(+), 50 deletions(-) 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 296bff9a0177e..a75cadfb041d7 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 @@ -30,7 +30,6 @@ import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509ExtendedTrustManager; - import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -59,8 +58,23 @@ */ public class SSLService extends AbstractComponent { + /** + * This is a mapping from "context name" (in general use, the name of a setting key) + * to a configuration. + * This allows us to easily answer the question "What is the configuration for ssl in realm XYZ?" + * Multiple "context names" may map to the same configuration (either by object-identity or by object-equality). + * For example "xpack.http.ssl" may exist as a name in this map and have the global ssl configuration as a value + */ private final Map sslConfigurations; + + /** + * A mapping from a SSLConfiguration to a pre-built context. + *

+ * This is managed separately to the {@link #sslConfigurations} map, so that a single configuration (by object equality) + * always maps to the same {@link SSLContextHolder}, even if it is being used within a different context-name. + */ private final Map sslContexts; + private final SSLConfiguration globalSSLConfiguration; private final SetOnce transportSSLConfiguration = new SetOnce<>(); private final Environment env; @@ -423,9 +437,13 @@ Map loadSSLConfigurations() { sslSettingsMap.putAll(getMonitoringExporterSettings(settings)); sslSettingsMap.forEach((key, sslSettings) -> { - final SSLConfiguration configuration = new SSLConfiguration(sslSettings, globalSSLConfiguration); - storeSSlConfiguration(key, configuration); - sslContextHolders.computeIfAbsent(configuration, this::createSslContext); + if (sslSettings.isEmpty()) { + storeSslConfiguration(key, globalSSLConfiguration); + } else { + final SSLConfiguration configuration = new SSLConfiguration(sslSettings, globalSSLConfiguration); + storeSslConfiguration(key, configuration); + sslContextHolders.computeIfAbsent(configuration, this::createSslContext); + } }); // transport is special because we want to use a auto-generated key when there isn't one @@ -436,14 +454,14 @@ Map loadSSLConfigurations() { sslContextHolders.computeIfAbsent(transportSSLConfiguration, this::createSslContext); profileSettings.forEach((key, profileSetting) -> { final SSLConfiguration configuration = new SSLConfiguration(profileSetting, transportSSLConfiguration); - storeSSlConfiguration(key, configuration); + storeSslConfiguration(key, configuration); sslContextHolders.computeIfAbsent(configuration, this::createSslContext); }); return Collections.unmodifiableMap(sslContextHolders); } - private void storeSSlConfiguration(String key, SSLConfiguration configuration) { + private void storeSslConfiguration(String key, SSLConfiguration configuration) { if (key.endsWith(".")) { key = key.substring(0, key.length() - 1); } @@ -625,9 +643,8 @@ private static Map getRealmsSSLSettings(Settings settings) { Settings realmsSettings = settings.getByPrefix(prefix); for (String name : realmsSettings.names()) { Settings realmSSLSettings = realmsSettings.getAsSettings(name).getByPrefix("ssl."); - if (realmSSLSettings.isEmpty() == false) { - sslSettings.put(prefix + name + ".ssl", realmSSLSettings); - } + // Put this even if empty, so that the name will be mapped to the global SSL configuration + sslSettings.put(prefix + name + ".ssl", realmSSLSettings); } return sslSettings; } @@ -666,9 +683,8 @@ private static Map getMonitoringExporterSettings(Settings sett Map exportersSettings = settings.getGroups("xpack.monitoring.exporters."); for (Entry entry : exportersSettings.entrySet()) { Settings exporterSSLSettings = entry.getValue().getByPrefix("ssl."); - if (exporterSSLSettings.isEmpty() == false) { - sslSettings.put("xpack.monitoring.exporters." + entry.getKey() + ".ssl", exporterSSLSettings); - } + // Put this even if empty, so that the name will be mapped to the global SSL configuration + sslSettings.put("xpack.monitoring.exporters." + entry.getKey() + ".ssl", exporterSSLSettings); } return sslSettings; } @@ -679,7 +695,7 @@ public SSLConfiguration getSSLConfiguration(String contextName) { } final SSLConfiguration configuration = sslConfigurations.get(contextName); if (configuration == null && logger.isTraceEnabled()) { - logger.trace("Cannot find SSL configuration for context {}. Known contexts are: {}", contextName, + logger.warn("Cannot find SSL configuration for context {}. Known contexts are: {}", contextName, Strings.collectionToCommaDelimitedString(sslConfigurations.keySet())); } return configuration; 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 186f8af8fd919..d33c033f531a3 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 @@ -480,46 +480,39 @@ public void testGetConfigurationByContextName() throws Exception { sslContext.init(null, null, null); final String[] cipherSuites = sslContext.getSupportedSSLParameters().getCipherSuites(); - final MockSecureSettings secureSettings = new MockSecureSettings(); - secureSettings.setString("xpack.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.http.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.security.http.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("transport.profiles.prof1.xpack.security.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("transport.profiles.prof2.xpack.security.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("transport.profiles.prof3.xpack.security.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.security.authc.realms.realm1.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.security.authc.realms.realm2.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.monitoring.exporters.mon1.ssl.keystore.secure_password", "testnode"); - secureSettings.setString("xpack.monitoring.exporters.mon2.ssl.keystore.secure_password", "testnode"); - - // Here we use a different ciphers for each context, to we can check that the returned SSLConfiguration matches the + final String[] settingPrefix = { + "xpack.ssl", + "xpack.http.ssl", + "xpack.security.http.ssl", + "xpack.security.transport.ssl", + "transport.profiles.prof1.xpack.security.ssl", + "transport.profiles.prof2.xpack.security.ssl", + "transport.profiles.prof3.xpack.security.ssl", + "xpack.security.authc.realms.realm1.ssl", + "xpack.security.authc.realms.realm2.ssl", + "xpack.monitoring.exporters.mon1.ssl", + "xpack.monitoring.exporters.mon2.ssl" + }; + + assumeTrue("Not enough cipher suites are available to support this test", cipherSuites.length >= settingPrefix.length); + + // Here we use a different ciphers for each context, so we can check that the returned SSLConfiguration matches the // provided settings final Iterator cipher = Arrays.asList(cipherSuites).iterator(); - final Settings settings = Settings.builder() - .put("xpack.ssl.keystore.path", testnodeStore) - .putList("xpack.ssl.cipher_suites", cipher.next()) - .put("xpack.http.ssl.keystore.path", testnodeStore) - .putList("xpack.http.ssl.cipher_suites", cipher.next()) - .put("xpack.security.http.ssl.keystore.path", testnodeStore) - .putList("xpack.security.http.ssl.cipher_suites", cipher.next()) - .put("xpack.security.transport.ssl.keystore.path", testnodeStore) - .putList("xpack.security.transport.ssl.cipher_suites", cipher.next()) - .put("transport.profiles.prof1.xpack.security.ssl.keystore.path", testnodeStore) - .putList("transport.profiles.prof1.xpack.security.ssl.cipher_suites", cipher.next()) - .put("transport.profiles.prof2.xpack.security.ssl.keystore.path", testnodeStore) - .putList("transport.profiles.prof2.xpack.security.ssl.cipher_suites", cipher.next()) - .put("transport.profiles.prof3.xpack.security.ssl.keystore.path", testnodeStore) - .putList("transport.profiles.prof3.xpack.security.ssl.cipher_suites", cipher.next()) - .put("xpack.security.authc.realms.realm1.ssl.keystore.path", testnodeStore) - .putList("xpack.security.authc.realms.realm1.ssl.cipher_suites", cipher.next()) - .put("xpack.security.authc.realms.realm2.ssl.keystore.path", testnodeStore) - .putList("xpack.security.authc.realms.realm2.ssl.cipher_suites", cipher.next()) - .put("xpack.monitoring.exporters.mon1.ssl.keystore.path", testnodeStore) - .putList("xpack.monitoring.exporters.mon1.ssl.cipher_suites", cipher.next()) - .put("xpack.monitoring.exporters.mon2.ssl.keystore.path", testnodeStore) - .putList("xpack.monitoring.exporters.mon2.ssl.cipher_suites", cipher.next()) + final MockSecureSettings secureSettings = new MockSecureSettings(); + final Settings.Builder builder = Settings.builder(); + for (String prefix : settingPrefix) { + secureSettings.setString(prefix + ".keystore.secure_password", "testnode"); + builder.put(prefix + ".keystore.path", testnodeStore) + .putList(prefix + ".cipher_suites", cipher.next()); + } + + final Settings settings = builder + // Add a realm without SSL settings. This context name should be mapped to the global configuration + .put("xpack.security.authc.realms.realm3.type", "file") + // Add an exporter without SSL settings. This context name should be mapped to the global configuration + .put("xpack.monitoring.exporters.mon3.type", "http") .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); @@ -538,7 +531,16 @@ public void testGetConfigurationByContextName() throws Exception { final StoreKeyConfig keyConfig = (StoreKeyConfig) configuration.keyConfig(); assertThat("KeyStore Path for " + name, keyConfig.keyStorePath, equalTo(testnodeStore.toString())); assertThat("Cipher for " + name, configuration.cipherSuites(), contains(cipherSuites[i])); + assertThat("Configuration for " + name + ".", sslService.getSSLConfiguration(name + "."), sameInstance(configuration)); } + + // These contexts have no SSL settings, but for convenience we want those components to be able to access their context + // by name, and get back the global configuration + final SSLConfiguration realm3Config = sslService.getSSLConfiguration("xpack.security.authc.realms.realm3.ssl"); + final SSLConfiguration mon3Config = sslService.getSSLConfiguration("xpack.monitoring.exporters.mon3.ssl."); + final SSLConfiguration global = sslService.getSSLConfiguration("_global"); + assertThat(realm3Config, sameInstance(global)); + assertThat(mon3Config, sameInstance(global)); } public void testReadCertificateInformation () throws Exception { From e8d82994a211a80af08b9ac6225c7e64df2f7097 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 10 Jul 2018 22:09:01 +1000 Subject: [PATCH 16/22] Fix import --- .../xpack/monitoring/exporter/http/HttpSslExporterIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java index 5bdc3655b38fe..09e9c1b3efd8a 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java @@ -21,7 +21,6 @@ import org.elasticsearch.xpack.monitoring.exporter.Exporters; import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; import org.hamcrest.CoreMatchers; -import org.junit.After; import org.junit.AfterClass; import org.junit.Before; From b11d61ba9dc8ee0eb41df08fc2a32e1900901ac5 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 11 Jul 2018 14:45:59 +1000 Subject: [PATCH 17/22] Rename test & context name --- .../xpack/core/ssl/SSLService.java | 9 +++--- .../xpack/core/ssl/SSLServiceTests.java | 28 ++++++++----------- ...ExporterIT.java => HttpExporterSslIT.java} | 2 +- 3 files changed, 16 insertions(+), 23 deletions(-) rename x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/{HttpSslExporterIT.java => HttpExporterSslIT.java} (99%) 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 a75cadfb041d7..2b2c75b64d9ea 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 @@ -427,9 +427,8 @@ private SSLContextHolder createSslContext(X509ExtendedKeyManager keyManager, X50 Map loadSSLConfigurations() { Map sslContextHolders = new HashMap<>(); sslContextHolders.put(globalSSLConfiguration, createSslContext(globalSSLConfiguration)); - this.sslConfigurations.put("_global", globalSSLConfiguration); + this.sslConfigurations.put("xpack.ssl", globalSSLConfiguration); - final Settings transportSSLSettings = settings.getByPrefix(XPackSettings.TRANSPORT_SSL_PREFIX); Map sslSettingsMap = new HashMap<>(); sslSettingsMap.put(XPackSettings.HTTP_SSL_PREFIX, getHttpTransportSSLSettings(settings)); sslSettingsMap.put("xpack.http.ssl", settings.getByPrefix("xpack.http.ssl.")); @@ -446,10 +445,10 @@ Map loadSSLConfigurations() { } }); - // transport is special because we want to use a auto-generated key when there isn't one + final Settings transportSSLSettings = settings.getByPrefix(XPackSettings.TRANSPORT_SSL_PREFIX); final SSLConfiguration transportSSLConfiguration = new SSLConfiguration(transportSSLSettings, globalSSLConfiguration); this.transportSSLConfiguration.set(transportSSLConfiguration); - this.sslConfigurations.put("_transport", transportSSLConfiguration); + storeSslConfiguration(XPackSettings.TRANSPORT_SSL_PREFIX, transportSSLConfiguration); Map profileSettings = getTransportProfileSSLSettings(settings); sslContextHolders.computeIfAbsent(transportSSLConfiguration, this::createSslContext); profileSettings.forEach((key, profileSetting) -> { @@ -694,7 +693,7 @@ public SSLConfiguration getSSLConfiguration(String contextName) { contextName = contextName.substring(0, contextName.length() - 1); } final SSLConfiguration configuration = sslConfigurations.get(contextName); - if (configuration == null && logger.isTraceEnabled()) { + if (configuration == null) { logger.warn("Cannot find SSL configuration for context {}. Known contexts are: {}", contextName, Strings.collectionToCommaDelimitedString(sslConfigurations.keySet())); } 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 d33c033f531a3..371548b19bcb3 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 @@ -139,7 +139,7 @@ public void testThatSslContextCachingWorks() throws Exception { assertThat(sslContext, is(sameInstance(cachedSslContext))); - final SSLConfiguration configuration = sslService.getSSLConfiguration("_global"); + final SSLConfiguration configuration = sslService.getSSLConfiguration("xpack.ssl"); final SSLContext configContext = sslService.sslContext(configuration); assertThat(configContext, is(sameInstance(sslContext))); } @@ -250,7 +250,7 @@ public void testValidForServerWithFallback() throws Exception { assertTrue(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration( settings.getByPrefix("xpack.security.transport.ssl.")))); assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); - assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("_transport"))); + assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.security.transport.ssl"))); } public void testGetVerificationMode() throws Exception { @@ -289,8 +289,8 @@ public void testIsSSLClientAuthEnabled() throws Exception { assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("transport.profiles.foo.xpack.security.ssl."), settings.getByPrefix("xpack.security.transport.ssl."))); - assertFalse(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("_global"))); - assertTrue(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("_transport"))); + assertFalse(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("xpack.ssl"))); + assertTrue(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("xpack.security.transport.ssl"))); } public void testThatHttpClientAuthDefaultsToNone() throws Exception { @@ -480,7 +480,7 @@ public void testGetConfigurationByContextName() throws Exception { sslContext.init(null, null, null); final String[] cipherSuites = sslContext.getSupportedSSLParameters().getCipherSuites(); - final String[] settingPrefix = { + final String[] contextNames = { "xpack.ssl", "xpack.http.ssl", "xpack.security.http.ssl", @@ -494,7 +494,7 @@ public void testGetConfigurationByContextName() throws Exception { "xpack.monitoring.exporters.mon2.ssl" }; - assumeTrue("Not enough cipher suites are available to support this test", cipherSuites.length >= settingPrefix.length); + assumeTrue("Not enough cipher suites are available to support this test", cipherSuites.length >= contextNames.length); // Here we use a different ciphers for each context, so we can check that the returned SSLConfiguration matches the // provided settings @@ -502,7 +502,7 @@ public void testGetConfigurationByContextName() throws Exception { final MockSecureSettings secureSettings = new MockSecureSettings(); final Settings.Builder builder = Settings.builder(); - for (String prefix : settingPrefix) { + for (String prefix : contextNames) { secureSettings.setString(prefix + ".keystore.secure_password", "testnode"); builder.put(prefix + ".keystore.path", testnodeStore) .putList(prefix + ".cipher_suites", cipher.next()); @@ -517,14 +517,8 @@ public void testGetConfigurationByContextName() throws Exception { .build(); SSLService sslService = new SSLService(settings, env); - final String[] context = new String[]{"_global", - "xpack.http.ssl", "xpack.security.http.ssl", - "_transport", "transport.profiles.prof1.xpack.security.ssl", - "transport.profiles.prof2.xpack.security.ssl", "transport.profiles.prof3.xpack.security.ssl" - , "xpack.security.authc.realms.realm1.ssl", "xpack.security.authc.realms.realm2.ssl", - "xpack.monitoring.exporters.mon1.ssl", "xpack.monitoring.exporters.mon2.ssl"}; - for (int i = 0; i < context.length; i++) { - final String name = context[i]; + for (int i = 0; i < contextNames.length; i++) { + final String name = contextNames[i]; final SSLConfiguration configuration = sslService.getSSLConfiguration(name); assertThat("Configuration for " + name, configuration, notNullValue()); assertThat("KeyStore for " + name, configuration.keyConfig(), instanceOf(StoreKeyConfig.class)); @@ -538,7 +532,7 @@ public void testGetConfigurationByContextName() throws Exception { // by name, and get back the global configuration final SSLConfiguration realm3Config = sslService.getSSLConfiguration("xpack.security.authc.realms.realm3.ssl"); final SSLConfiguration mon3Config = sslService.getSSLConfiguration("xpack.monitoring.exporters.mon3.ssl."); - final SSLConfiguration global = sslService.getSSLConfiguration("_global"); + final SSLConfiguration global = globalConfiguration(sslService); assertThat(realm3Config, sameInstance(global)); assertThat(mon3Config, sameInstance(global)); } @@ -727,7 +721,7 @@ public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { private static SSLConfiguration globalConfiguration(SSLService sslService) { if (randomBoolean()) { - return sslService.getSSLConfiguration("_global"); + return sslService.getSSLConfiguration("xpack.ssl"); } if (randomBoolean()) { return sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java similarity index 99% rename from x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java rename to x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java index 09e9c1b3efd8a..2a230720a33db 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpSslExporterIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java @@ -35,7 +35,7 @@ @ESIntegTestCase.ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0, supportsDedicatedMasters = false) -public class HttpSslExporterIT extends MonitoringIntegTestCase { +public class HttpExporterSslIT extends MonitoringIntegTestCase { private final Settings globalSettings = Settings.builder().put("path.home", createTempDir()).build(); private final Environment environment = TestEnvironment.newEnvironment(globalSettings); From f4bab91ee4c904e1244056570b593acd65918b9c Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 11 Jul 2018 16:17:26 +1000 Subject: [PATCH 18/22] Remove more uses of sslConfiguration from settings --- .../netty4/SecurityNetty4Transport.java | 38 +++++++------- .../xpack/core/ssl/SSLService.java | 50 +++++-------------- .../netty4/SecurityNetty4TransportTests.java | 43 ++++++++++++++++ .../xpack/core/ssl/SSLServiceTests.java | 27 ++++------ .../security/PkiRealmBootstrapCheck.java | 45 +++++++---------- .../xpack/security/Security.java | 2 +- .../authc/ldap/support/SessionFactory.java | 11 ++-- .../SecurityServerTransportInterceptor.java | 40 ++++++--------- .../transport/nio/SecurityNioTransport.java | 20 ++------ .../security/PkiRealmBootstrapCheckTests.java | 4 +- .../xpack/ssl/SSLReloadIntegTests.java | 2 +- .../xpack/ssl/SSLTrustRestrictionsTests.java | 2 +- 12 files changed, 129 insertions(+), 155 deletions(-) create mode 100644 x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4TransportTests.java diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java index b761439b15b6a..f828a82d95f6c 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4Transport.java @@ -28,12 +28,12 @@ import org.elasticsearch.xpack.core.ssl.SSLService; import javax.net.ssl.SSLEngine; - import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import static org.elasticsearch.xpack.core.security.SecurityField.setting; @@ -58,22 +58,9 @@ public SecurityNetty4Transport( super(settings, threadPool, networkService, bigArrays, namedWriteableRegistry, circuitBreakerService); this.sslService = sslService; this.sslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings); - final Settings transportSSLSettings = settings.getByPrefix(setting("transport.ssl.")); if (sslEnabled) { - this.sslConfiguration = sslService.sslConfiguration(transportSSLSettings, Settings.EMPTY); - Map profileSettingsMap = settings.getGroups("transport.profiles.", true); - Map profileConfiguration = new HashMap<>(profileSettingsMap.size() + 1); - for (Map.Entry entry : profileSettingsMap.entrySet()) { - Settings profileSettings = entry.getValue(); - final Settings profileSslSettings = profileSslSettings(profileSettings); - SSLConfiguration configuration = sslService.sslConfiguration(profileSslSettings, transportSSLSettings); - profileConfiguration.put(entry.getKey(), configuration); - } - - if (profileConfiguration.containsKey(TcpTransport.DEFAULT_PROFILE) == false) { - profileConfiguration.put(TcpTransport.DEFAULT_PROFILE, sslConfiguration); - } - + this.sslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl.")); + Map profileConfiguration = getTransportProfileConfigurations(settings, sslService, sslConfiguration); this.profileConfiguration = Collections.unmodifiableMap(profileConfiguration); } else { this.profileConfiguration = Collections.emptyMap(); @@ -81,6 +68,21 @@ public SecurityNetty4Transport( } } + public static Map getTransportProfileConfigurations(Settings settings, SSLService sslService, + SSLConfiguration defaultConfiguration) { + Set profileNames = settings.getGroups("transport.profiles.", true).keySet(); + Map profileConfiguration = new HashMap<>(profileNames.size() + 1); + for (String profileName : profileNames) { + SSLConfiguration configuration = sslService.getSSLConfiguration("transport.profiles." + profileName + "." + setting("ssl")); + profileConfiguration.put(profileName, configuration); + } + + if (profileConfiguration.containsKey(TcpTransport.DEFAULT_PROFILE) == false) { + profileConfiguration.put(TcpTransport.DEFAULT_PROFILE, defaultConfiguration); + } + return profileConfiguration; + } + @Override protected void doStart() { super.doStart(); @@ -209,8 +211,4 @@ public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, super.connect(ctx, remoteAddress, localAddress, promise); } } - - public static Settings profileSslSettings(Settings profileSettings) { - return profileSettings.getByPrefix(setting("ssl.")); - } } 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 2b2c75b64d9ea..d43f3d855ce73 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 @@ -51,6 +51,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; /** * Provides access to {@link SSLEngine} and {@link SSLSocketFactory} objects based on a provided configuration. All @@ -139,7 +140,7 @@ SSLContextHolder sslContextHolder(SSLConfiguration sslConfiguration) { * @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)} + * and {@link #sslIOSessionStrategy(SSLConfiguration)} (Deprecated, but not removed because monitoring uses dynamic SSL settings) */ @Deprecated public SSLIOSessionStrategy sslIOSessionStrategy(Settings settings) { @@ -209,7 +210,7 @@ public SSLSocketFactory sslSocketFactory(SSLConfiguration configuration) { * certificate * @param port the port of the remote endpoint * @return {@link SSLEngine} - * @see #sslConfiguration(Settings, Settings) + * @see #getSSLConfiguration(String) */ public SSLEngine createSSLEngine(SSLConfiguration configuration, String host, int port) { SSLContext sslContext = sslContext(configuration); @@ -243,28 +244,6 @@ public boolean isConfigurationValidForServerUsage(SSLConfiguration sslConfigurat return sslConfiguration.keyConfig() != KeyConfig.NONE; } - /** - * Indicates whether client authentication is enabled for a particular configuration - * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix. The global configuration - * will be used for fallback - * @deprecated Use {@link #isSSLClientAuthEnabled(SSLConfiguration)} with {@link #getSSLConfiguration(String)} - */ - @Deprecated - public boolean isSSLClientAuthEnabled(Settings settings) { - return isSSLClientAuthEnabled(settings, Settings.EMPTY); - } - - /** - * Indicates whether client authentication is enabled for a particular configuration - * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix - * @param fallback the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} - * results in a fallback to the global configuration - */ - public boolean isSSLClientAuthEnabled(Settings settings, Settings fallback) { - SSLConfiguration sslConfiguration = sslConfiguration(settings, fallback); - return isSSLClientAuthEnabled(sslConfiguration); - } - /** * Indicates whether client authentication is enabled for a particular configuration */ @@ -273,17 +252,6 @@ public boolean isSSLClientAuthEnabled(SSLConfiguration sslConfiguration) { return sslConfiguration.sslClientAuth().enabled(); } - /** - * Returns the {@link VerificationMode} that is specified in the settings (or the default) - * @param settings the settings used to identify the ssl configuration, typically under a *.ssl. prefix - * @param fallback the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} - * results in a fallback to the global configuration - */ - public VerificationMode getVerificationMode(Settings settings, Settings fallback) { - SSLConfiguration sslConfiguration = sslConfiguration(settings, fallback); - return sslConfiguration.verificationMode(); - } - /** * Returns the {@link SSLContext} for the global configuration. Mainly used for testing */ @@ -339,6 +307,14 @@ public SSLConfiguration sslConfiguration(Settings settings, Settings fallbackSet return new SSLConfiguration(settings, fallback); } + public Set getTransportProfileContextNames() { + return Collections.unmodifiableSet(this.sslConfigurations + .keySet().stream() + .filter(k -> k.startsWith("transport.profiles.")) + .collect(Collectors.toSet())); + } + + /** * Accessor to the loaded ssl configuration objects at the current point in time. This is useful for testing */ @@ -653,9 +629,7 @@ private static Map getTransportProfileSSLSettings(Settings set Map profiles = settings.getGroups("transport.profiles.", true); for (Entry entry : profiles.entrySet()) { Settings profileSettings = entry.getValue().getByPrefix("xpack.security.ssl."); - if (profileSettings.isEmpty() == false) { - sslSettings.put("transport.profiles." + entry.getKey() + ".xpack.security.ssl", profileSettings); - } + sslSettings.put("transport.profiles." + entry.getKey() + ".xpack.security.ssl", profileSettings); } return sslSettings; } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4TransportTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4TransportTests.java new file mode 100644 index 0000000000000..3c4ebee2ac59c --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/netty4/SecurityNetty4TransportTests.java @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.core.security.transport.netty4; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; +import org.elasticsearch.xpack.core.ssl.SSLService; +import org.elasticsearch.xpack.core.ssl.VerificationMode; +import org.hamcrest.Matchers; + +import java.util.Map; + +import static org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport.getTransportProfileConfigurations; + +public class SecurityNetty4TransportTests extends ESTestCase { + + public void testGetTransportProfileConfigurations() { + final Settings settings = Settings.builder() + .put("path.home", createTempDir()) + .put("xpack.security.transport.ssl.verification_mode", VerificationMode.CERTIFICATE.name()) + .put("transport.profiles.full.xpack.security.ssl.verification_mode", VerificationMode.FULL.name()) + .put("transport.profiles.cert.xpack.security.ssl.verification_mode", VerificationMode.CERTIFICATE.name()) + .put("transport.profiles.none.xpack.security.ssl.verification_mode", VerificationMode.NONE.name()) + .build(); + final Environment env = TestEnvironment.newEnvironment(settings); + SSLService sslService = new SSLService(settings, env); + final SSLConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl"); + final Map profileConfigurations = getTransportProfileConfigurations(settings, sslService, defaultConfig); + assertThat(profileConfigurations.size(), Matchers.equalTo(4)); + assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("full", "cert", "none", "default")); + assertThat(profileConfigurations.get("full").verificationMode(), Matchers.equalTo(VerificationMode.FULL)); + assertThat(profileConfigurations.get("cert").verificationMode(), Matchers.equalTo(VerificationMode.CERTIFICATE)); + assertThat(profileConfigurations.get("none").verificationMode(), Matchers.equalTo(VerificationMode.NONE)); + assertThat(profileConfigurations.get("default"), Matchers.sameInstance(defaultConfig)); + } +} 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 371548b19bcb3..8b5cfd06f3ef6 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 @@ -255,7 +255,7 @@ public void testValidForServerWithFallback() throws Exception { public void testGetVerificationMode() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - assertThat(sslService.getVerificationMode(Settings.EMPTY, Settings.EMPTY), is(XPackSettings.VERIFICATION_MODE_DEFAULT)); + assertThat(globalConfiguration(sslService).verificationMode(), is(XPackSettings.VERIFICATION_MODE_DEFAULT)); Settings settings = Settings.builder() .put("xpack.ssl.verification_mode", "none") @@ -263,34 +263,25 @@ public void testGetVerificationMode() throws Exception { .put("transport.profiles.foo.xpack.security.ssl.verification_mode", "full") .build(); sslService = new SSLService(settings, env); - assertThat(sslService.getVerificationMode(Settings.EMPTY, Settings.EMPTY), is(VerificationMode.NONE)); - assertThat(sslService.getVerificationMode(settings.getByPrefix("xpack.security.transport.ssl."), Settings.EMPTY), - is(VerificationMode.CERTIFICATE)); - assertThat(sslService.getVerificationMode(settings.getByPrefix("transport.profiles.foo.xpack.security.ssl."), - settings.getByPrefix("xpack.security.transport.ssl.")), is(VerificationMode.FULL)); - assertThat(sslService.getVerificationMode(Settings.EMPTY, settings.getByPrefix("xpack.security.transport.ssl.")), - is(VerificationMode.CERTIFICATE)); + assertThat(globalConfiguration(sslService).verificationMode(), is(VerificationMode.NONE)); + assertThat(sslService.getSSLConfiguration("xpack.security.transport.ssl.").verificationMode(), is(VerificationMode.CERTIFICATE)); + assertThat(sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl.").verificationMode(), + is(VerificationMode.FULL)); } public void testIsSSLClientAuthEnabled() throws Exception { SSLService sslService = new SSLService(Settings.EMPTY, env); - assertTrue(sslService.isSSLClientAuthEnabled(Settings.EMPTY)); - assertTrue(sslService.isSSLClientAuthEnabled(Settings.EMPTY, Settings.EMPTY)); + assertTrue(globalConfiguration(sslService).sslClientAuth().enabled()); Settings settings = Settings.builder() .put("xpack.ssl.client_authentication", "none") .put("xpack.security.transport.ssl.client_authentication", "optional") + .put("transport.profiles.foo.port", "9400-9410") .build(); sslService = new SSLService(settings, env); - assertFalse(sslService.isSSLClientAuthEnabled(Settings.EMPTY)); - assertFalse(sslService.isSSLClientAuthEnabled(Settings.EMPTY, Settings.EMPTY)); - assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("xpack.security.transport.ssl."))); - assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("xpack.security.transport.ssl."), Settings.EMPTY)); - assertTrue(sslService.isSSLClientAuthEnabled(settings.getByPrefix("transport.profiles.foo.xpack.security.ssl."), - settings.getByPrefix("xpack.security.transport.ssl."))); - - assertFalse(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("xpack.ssl"))); + assertFalse(sslService.isSSLClientAuthEnabled(globalConfiguration(sslService))); assertTrue(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("xpack.security.transport.ssl"))); + assertTrue(sslService.isSSLClientAuthEnabled(sslService.getSSLConfiguration("transport.profiles.foo.xpack.security.ssl"))); } public void testThatHttpClientAuthDefaultsToNone() throws Exception { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java index 52e286f3f316a..fc5962d705c94 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheck.java @@ -11,7 +11,6 @@ import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.pki.PkiRealmSettings; -import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport; import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; @@ -24,34 +23,9 @@ class PkiRealmBootstrapCheck implements BootstrapCheck { private final SSLService sslService; - private final List sslConfigurations; - PkiRealmBootstrapCheck(Settings settings, SSLService sslService) { + PkiRealmBootstrapCheck(SSLService sslService) { this.sslService = sslService; - this.sslConfigurations = loadSslConfigurations(settings); - } - - /** - * {@link SSLConfiguration} may depend on {@link org.elasticsearch.common.settings.SecureSettings} that can only be read during startup. - * We need to preload these during component configuration. - */ - private List loadSslConfigurations(Settings settings) { - final List list = new ArrayList<>(); - if (HTTP_SSL_ENABLED.get(settings)) { - list.add(sslService.getHttpTransportSSLConfiguration()); - } - - if (XPackSettings.TRANSPORT_SSL_ENABLED.get(settings)) { - final Settings transportSslSettings = settings.getByPrefix(setting("transport.ssl.")); - list.add(sslService.sslConfiguration(transportSslSettings, Settings.EMPTY)); - - settings.getGroups("transport.profiles.").values().stream() - .map(SecurityNetty4Transport::profileSslSettings) - .map(s -> sslService.sslConfiguration(s, transportSslSettings)) - .forEach(list::add); - } - - return list; } /** @@ -65,7 +39,8 @@ public BootstrapCheckResult check(BootstrapContext context) { .filter(s -> PkiRealmSettings.TYPE.equals(s.get("type"))) .anyMatch(s -> s.getAsBoolean("enabled", true)); if (pkiRealmEnabled) { - for (SSLConfiguration configuration : this.sslConfigurations) { + for (String contextName : getSslContextNames(settings)) { + final SSLConfiguration configuration = sslService.getSSLConfiguration(contextName); if (sslService.isSSLClientAuthEnabled(configuration)) { return BootstrapCheckResult.success(); } @@ -77,6 +52,20 @@ public BootstrapCheckResult check(BootstrapContext context) { } } + private List getSslContextNames(Settings settings) { + final List list = new ArrayList<>(); + if (HTTP_SSL_ENABLED.get(settings)) { + list.add(setting("http.ssl")); + } + + if (XPackSettings.TRANSPORT_SSL_ENABLED.get(settings)) { + list.add(setting("transport.ssl")); + list.addAll(sslService.getTransportProfileContextNames()); + } + + return list; + } + @Override public boolean alwaysEnforce() { return true; 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 38e0bf072dacc..8d05db08e2274 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 @@ -286,7 +286,7 @@ public Security(Settings settings, final Path configPath) { final List checks = new ArrayList<>(); checks.addAll(Arrays.asList( new TokenSSLBootstrapCheck(), - new PkiRealmBootstrapCheck(settings, getSslService()), + new PkiRealmBootstrapCheck(getSslService()), new TLSLicenseBootstrapCheck(), new PasswordHashingAlgorithmBootstrapCheck())); checks.addAll(InternalRealms.getBootstrapChecks(settings, env)); 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 3780741b5941f..186a5ff771afa 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 @@ -134,20 +134,19 @@ protected static LDAPConnectionOptions connectionOptions(RealmConfig config, final Settings realmSSLSettings = realmSettings.getByPrefix("ssl."); final boolean verificationModeExists = sslConfigurationSettings.verificationMode.exists(realmSSLSettings); - final boolean hostnameVerficationExists = + final boolean hostnameVerificationExists = realmSettings.get(SessionFactorySettings.HOSTNAME_VERIFICATION_SETTING, null) != null; - if (verificationModeExists && hostnameVerficationExists) { + if (verificationModeExists && hostnameVerificationExists) { throw new IllegalArgumentException("[" + SessionFactorySettings.HOSTNAME_VERIFICATION_SETTING + "] and [" + sslConfigurationSettings.verificationMode.getKey() + "] may not be used at the same time"); } else if (verificationModeExists) { - VerificationMode verificationMode = sslService.getVerificationMode(realmSSLSettings, - Settings.EMPTY); - if (verificationMode == VerificationMode.FULL) { + final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(RealmSettings.getFullSettingKey(config, "ssl")); + if (sslConfiguration.verificationMode().isHostnameVerificationEnabled()) { options.setSSLSocketVerifier(new HostNameSSLSocketVerifier(true)); } - } else if (hostnameVerficationExists) { + } else if (hostnameVerificationExists) { new DeprecationLogger(logger).deprecated("the setting [{}] has been deprecated and " + "will be removed in a future version. use [{}] instead", RealmSettings.getFullSettingKey(config, SessionFactorySettings.HOSTNAME_VERIFICATION_SETTING), diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptor.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptor.java index 55287d5d50387..3b761522fa719 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptor.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/SecurityServerTransportInterceptor.java @@ -20,7 +20,6 @@ import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.tasks.Task; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TcpTransport; import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.TransportChannel; import org.elasticsearch.transport.TransportException; @@ -36,6 +35,7 @@ import org.elasticsearch.xpack.core.security.SecurityContext; import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport; import org.elasticsearch.xpack.core.security.user.SystemUser; +import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authz.AuthorizationService; @@ -51,17 +51,15 @@ public class SecurityServerTransportInterceptor extends AbstractComponent implements TransportInterceptor { - private static final Function> TRANSPORT_TYPE_SETTING_TEMPLATE = (key) -> new Setting<>(key, - "node", v - -> { - if (v.equals("node") || v.equals("client")) { - return v; - } - throw new IllegalArgumentException("type must be one of [client, node]"); + private static final Function> TRANSPORT_TYPE_SETTING_TEMPLATE = key -> new Setting<>(key, "node", v -> { + if (v.equals("node") || v.equals("client")) { + return v; + } + throw new IllegalArgumentException("type must be one of [client, node]"); }, Setting.Property.NodeScope); private static final String TRANSPORT_TYPE_SETTING_KEY = "xpack.security.type"; - public static final Setting TRANSPORT_TYPE_PROFILE_SETTING = Setting.affixKeySetting("transport.profiles.", + public static final Setting.AffixSetting TRANSPORT_TYPE_PROFILE_SETTING = Setting.affixKeySetting("transport.profiles.", TRANSPORT_TYPE_SETTING_KEY, TRANSPORT_TYPE_SETTING_TEMPLATE); private final AuthenticationService authcService; @@ -175,17 +173,17 @@ public TransportRequestHandler interceptHandler( } protected Map initializeProfileFilters(DestructiveOperations destructiveOperations) { - Map profileSettingsMap = settings.getGroups("transport.profiles.", true); - Map profileFilters = new HashMap<>(profileSettingsMap.size() + 1); + final SSLConfiguration transportSslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl")); + final Map profileConfigurations = SecurityNetty4Transport.getTransportProfileConfigurations(settings, + sslService, transportSslConfiguration); + + Map profileFilters = new HashMap<>(profileConfigurations.size() + 1); - final Settings transportSSLSettings = settings.getByPrefix(setting("transport.ssl.")); final boolean transportSSLEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings); - for (Map.Entry entry : profileSettingsMap.entrySet()) { - Settings profileSettings = entry.getValue(); - final Settings profileSslSettings = SecurityNetty4Transport.profileSslSettings(profileSettings); - final boolean extractClientCert = transportSSLEnabled && - sslService.isSSLClientAuthEnabled(profileSslSettings, transportSSLSettings); - String type = TRANSPORT_TYPE_SETTING_TEMPLATE.apply(TRANSPORT_TYPE_SETTING_KEY).get(entry.getValue()); + for (Map.Entry entry : profileConfigurations.entrySet()) { + final SSLConfiguration profileConfiguration = entry.getValue(); + final boolean extractClientCert = transportSSLEnabled && sslService.isSSLClientAuthEnabled(profileConfiguration); + final String type = TRANSPORT_TYPE_PROFILE_SETTING.getConcreteSettingForNamespace(entry.getKey()).get(settings); switch (type) { case "client": profileFilters.put(entry.getKey(), new ServerTransportFilter.ClientProfile(authcService, authzService, @@ -202,12 +200,6 @@ protected Map initializeProfileFilters(Destructiv } } - if (!profileFilters.containsKey(TcpTransport.DEFAULT_PROFILE)) { - final boolean extractClientCert = transportSSLEnabled && sslService.isSSLClientAuthEnabled(transportSSLSettings); - profileFilters.put(TcpTransport.DEFAULT_PROFILE, new ServerTransportFilter.NodeProfile(authcService, authzService, - threadPool.getThreadContext(), extractClientCert, destructiveOperations, reservedRealmEnabled, securityContext)); - } - return Collections.unmodifiableMap(profileFilters); } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioTransport.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioTransport.java index 874dc36a31cce..968ba991c9720 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioTransport.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioTransport.java @@ -33,7 +33,6 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Collections; -import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; import java.util.function.Supplier; @@ -62,23 +61,12 @@ public class SecurityNioTransport extends NioTransport { super(settings, threadPool, networkService, bigArrays, pageCacheRecycler, namedWriteableRegistry, circuitBreakerService); this.sslService = sslService; this.sslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings); - final Settings transportSSLSettings = settings.getByPrefix(setting("transport.ssl.")); if (sslEnabled) { - this.sslConfiguration = sslService.sslConfiguration(transportSSLSettings, Settings.EMPTY); - Map profileSettingsMap = settings.getGroups("transport.profiles.", true); - Map profileConfiguration = new HashMap<>(profileSettingsMap.size() + 1); - for (Map.Entry entry : profileSettingsMap.entrySet()) { - Settings profileSettings = entry.getValue(); - final Settings profileSslSettings = SecurityNetty4Transport.profileSslSettings(profileSettings); - SSLConfiguration configuration = sslService.sslConfiguration(profileSslSettings, transportSSLSettings); - profileConfiguration.put(entry.getKey(), configuration); - } - - if (profileConfiguration.containsKey(TcpTransport.DEFAULT_PROFILE) == false) { - profileConfiguration.put(TcpTransport.DEFAULT_PROFILE, sslConfiguration); - } - + this.sslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl.")); + Map profileConfiguration = SecurityNetty4Transport.getTransportProfileConfigurations(settings, + sslService, sslConfiguration); this.profileConfiguration = Collections.unmodifiableMap(profileConfiguration); + } else { throw new IllegalArgumentException("Currently only support SSL enabled."); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java index 5610da6f75c6b..f9b1be65736e1 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java @@ -83,7 +83,7 @@ public void testBootstrapCheckWithPkiRealm() throws Exception { } private BootstrapCheck.BootstrapCheckResult runCheck(Settings settings, Environment env) throws Exception { - return new PkiRealmBootstrapCheck(settings, new SSLService(settings, env)).check(new BootstrapContext(settings, null)); + return new PkiRealmBootstrapCheck(new SSLService(settings, env)).check(new BootstrapContext(settings, null)); } public void testBootstrapCheckWithDisabledRealm() throws Exception { @@ -112,7 +112,7 @@ public void testBootstrapCheckWithClosedSecuredSetting() throws Exception { .build(); Environment env = TestEnvironment.newEnvironment(settings); - final PkiRealmBootstrapCheck check = new PkiRealmBootstrapCheck(settings, new SSLService(settings, env)); + final PkiRealmBootstrapCheck check = new PkiRealmBootstrapCheck(new SSLService(settings, env)); secureSettings.close(); assertThat(check.check(new BootstrapContext(settings, null)).isFailure(), Matchers.equalTo(expectFail)); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java index 41e41e7170f21..4269d8a78eb7a 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java @@ -96,7 +96,7 @@ public void testThatSSLConfigurationReloadsOnModification() throws Exception { .build(); String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(settings, TestEnvironment.newEnvironment(settings)); - SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("_global"); + SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.ssl"); SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); TransportAddress address = internalCluster() .getInstance(Transport.class, node).boundAddress().publishAddress(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java index b441cba49a54a..beebf928fcf27 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java @@ -213,7 +213,7 @@ private void tryConnect(CertificateInfo certificate) throws Exception { String node = randomFrom(internalCluster().getNodeNames()); SSLService sslService = new SSLService(settings, TestEnvironment.newEnvironment(settings)); - SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("_global"); + SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.ssl"); SSLSocketFactory sslSocketFactory = sslService.sslSocketFactory(sslConfiguration); TransportAddress address = internalCluster().getInstance(Transport.class, node).boundAddress().publishAddress(); try (SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address.getAddress(), address.getPort())) { From f774e6d1d469fa429e40d8d501645bf8ac4a8876 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 11 Jul 2018 16:50:20 +1000 Subject: [PATCH 19/22] Remove remaining uses of deprecated methods There's a few places where the usage is difficult to remove, so I'm leaving them for now and we can tackle them another time. --- .../xpack/core/ssl/SSLService.java | 17 ----------------- .../ssl/SSLConfigurationReloaderTests.java | 10 +++++----- .../xpack/core/ssl/SSLServiceTests.java | 18 ++++-------------- .../authc/ldap/support/SessionFactory.java | 1 - .../nio/SimpleSecurityNioTransportTests.java | 2 +- .../transport/ssl/SslIntegrationTests.java | 2 +- 6 files changed, 11 insertions(+), 39 deletions(-) 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 d43f3d855ce73..07d438b243b5b 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 @@ -291,22 +291,6 @@ SSLConfiguration sslConfiguration(Settings settings) { return new SSLConfiguration(settings, globalSSLConfiguration); } - /** - * Returns the existing {@link SSLConfiguration} for the given settings and applies the provided fallback settings instead of the global - * configuration - * @param settings the settings for the ssl configuration - * @param fallbackSettings the settings that should be used for the fallback of the SSLConfiguration. Using {@link Settings#EMPTY} - * results in a fallback to the global configuration - * @return the ssl configuration for the provided settings. If the settings are empty, the global configuration is returned - */ - public SSLConfiguration sslConfiguration(Settings settings, Settings fallbackSettings) { - if (settings.isEmpty() && fallbackSettings.isEmpty()) { - return globalSSLConfiguration; - } - SSLConfiguration fallback = sslConfiguration(fallbackSettings); - return new SSLConfiguration(settings, fallback); - } - public Set getTransportProfileContextNames() { return Collections.unmodifiableSet(this.sslConfigurations .keySet().stream() @@ -314,7 +298,6 @@ public Set getTransportProfileContextNames() { .collect(Collectors.toSet())); } - /** * Accessor to the loaded ssl configuration objects at the current point in time. This is useful for testing */ diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java index 0946ad3ac51c0..72cd13471df1f 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java @@ -303,7 +303,7 @@ public void testReloadingKeyStoreException() throws Exception { .build(); Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings); final SSLService sslService = new SSLService(settings, env); - final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl"); new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) { @Override void reloadSSLContext(SSLConfiguration configuration) { @@ -344,7 +344,7 @@ public void testReloadingPEMKeyConfigException() throws Exception { .build(); Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings); final SSLService sslService = new SSLService(settings, env); - final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl"); new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) { @Override void reloadSSLContext(SSLConfiguration configuration) { @@ -379,7 +379,7 @@ public void testTrustStoreReloadException() throws Exception { .build(); Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings); final SSLService sslService = new SSLService(settings, env); - final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl"); new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) { @Override void reloadSSLContext(SSLConfiguration configuration) { @@ -411,7 +411,7 @@ public void testPEMTrustReloadException() throws Exception { .build(); Environment env = randomBoolean() ? null : TestEnvironment.newEnvironment(settings); final SSLService sslService = new SSLService(settings, env); - final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl"); new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) { @Override void reloadSSLContext(SSLConfiguration configuration) { @@ -440,7 +440,7 @@ private void validateSSLConfigurationIsReloaded(Settings settings, Environment e final CountDownLatch reloadLatch = new CountDownLatch(1); final SSLService sslService = new SSLService(settings, env); - final SSLConfiguration config = sslService.sslConfiguration(Settings.EMPTY); + final SSLConfiguration config = sslService.getSSLConfiguration("xpack.ssl"); new SSLConfigurationReloader(settings, env, sslService, resourceWatcherService) { @Override void reloadSSLContext(SSLConfiguration configuration) { 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 8b5cfd06f3ef6..df764bb3f4772 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 @@ -110,7 +110,7 @@ public void testThatCustomTruststoreCanBeSpecified() throws Exception { .setSecureSettings(secureCustomSettings) .build(); - SSLConfiguration configuration = sslService.sslConfiguration(customTruststoreSettings, Settings.EMPTY); + SSLConfiguration configuration = new SSLConfiguration(customTruststoreSettings, globalConfiguration(sslService)); SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(configuration, null, -1); assertThat(sslEngineWithTruststore, is(not(nullValue()))); @@ -170,7 +170,7 @@ public void testIncorrectKeyPasswordThrowsException() throws Exception { .setSecureSettings(secureSettings) .build(); final SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); sslService.createSSLEngine(configuration, null, -1); fail("expected an exception"); } catch (ElasticsearchException e) { @@ -187,7 +187,7 @@ public void testThatSSLv3IsNotEnabled() throws Exception { .setSecureSettings(secureSettings) .build(); SSLService sslService = new SSLService(settings, env); - SSLConfiguration configuration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration configuration = globalConfiguration(sslService); SSLEngine engine = sslService.createSSLEngine(configuration, null, -1); assertThat(Arrays.asList(engine.getEnabledProtocols()), not(hasItem("SSLv3"))); } @@ -247,9 +247,6 @@ public void testValidForServerWithFallback() throws Exception { .build(); sslService = new SSLService(settings, env); assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); - assertTrue(sslService.isConfigurationValidForServerUsage(sslService.sslConfiguration( - settings.getByPrefix("xpack.security.transport.ssl.")))); - assertFalse(sslService.isConfigurationValidForServerUsage(globalConfiguration(sslService))); assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.security.transport.ssl"))); } @@ -711,14 +708,7 @@ public void testThatSSLIOSessionStrategyTrustsJDKTrustedCAs() throws Exception { } private static SSLConfiguration globalConfiguration(SSLService sslService) { - if (randomBoolean()) { - return sslService.getSSLConfiguration("xpack.ssl"); - } - if (randomBoolean()) { - return sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); - } else { - return sslService.sslConfiguration(Settings.EMPTY); - } + return sslService.getSSLConfiguration("xpack.ssl"); } class AssertionCallback implements FutureCallback { 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 186a5ff771afa..e7a344555c98e 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 @@ -24,7 +24,6 @@ import org.elasticsearch.xpack.core.ssl.SSLConfiguration; import org.elasticsearch.xpack.core.ssl.SSLConfigurationSettings; import org.elasticsearch.xpack.core.ssl.SSLService; -import org.elasticsearch.xpack.core.ssl.VerificationMode; import javax.net.SocketFactory; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java index 87b445009419c..3e1b42a8261bc 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java @@ -160,7 +160,7 @@ public void testBindUnavailableAddress() { @SuppressForbidden(reason = "Need to open socket connection") public void testRenegotiation() throws Exception { SSLService sslService = createSSLService(); - final SSLConfiguration sslConfiguration = sslService.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration("xpack.ssl"); SocketFactory factory = sslService.sslSocketFactory(sslConfiguration); try (SSLSocket socket = (SSLSocket) factory.createSocket()) { SocketAccess.doPrivileged(() -> socket.connect(serviceA.boundAddress().publishAddress().address())); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java index c176a4a7fd69f..fa8fd00aeba61 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java @@ -122,7 +122,7 @@ public void testThatConnectionToHTTPWorks() throws Exception { CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(nodeClientUsername(), new String(nodeClientPassword().getChars()))); - SSLConfiguration sslConfiguration = service.sslConfiguration(Settings.EMPTY, Settings.EMPTY); + SSLConfiguration sslConfiguration = service.getSSLConfiguration("xpack.ssl"); try (CloseableHttpClient client = HttpClients.custom() .setSSLSocketFactory(new SSLConnectionSocketFactory(service.sslSocketFactory(sslConfiguration), SSLConnectionSocketFactory.getDefaultHostnameVerifier())) From d1f31475692e690f63dc07981484ba7ff8675cc1 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 11 Jul 2018 17:28:08 +1000 Subject: [PATCH 20/22] Don't use JKS keystore in test --- .../exporter/http/HttpExporterSslIT.java | 20 ++++++------- .../monitoring/exporter/http/testnode.crt | 23 ++++++++++++++ .../monitoring/exporter/http/testnode.pem | 30 +++++++++++++++++++ 3 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.crt create mode 100644 x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.pem diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java index 2a230720a33db..a0511dc17aa92 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterSslIT.java @@ -41,7 +41,6 @@ public class HttpExporterSslIT extends MonitoringIntegTestCase { private final Environment environment = TestEnvironment.newEnvironment(globalSettings); private static MockWebServer webServer; - private static Path keystore; private MockSecureSettings secureSettings; @@ -51,7 +50,6 @@ public static void cleanUpStatics() { webServer.close(); webServer = null; } - keystore = null; } @Override @@ -61,10 +59,8 @@ protected boolean ignoreExternalCluster() { @Override protected Settings nodeSettings(int nodeOrdinal) { - if (keystore == null) { - keystore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); - assertThat(Files.exists(keystore), CoreMatchers.is(true)); - } + final Path truststore = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.jks"); + assertThat(Files.exists(truststore), CoreMatchers.is(true)); if (webServer == null) { try { @@ -80,12 +76,12 @@ protected Settings nodeSettings(int nodeOrdinal) { .put("xpack.monitoring.exporters.plaintext.type", "http") .put("xpack.monitoring.exporters.plaintext.enabled", true) .put("xpack.monitoring.exporters.plaintext.host", address) - .put("xpack.monitoring.exporters.plaintext.ssl.truststore.path", keystore) + .put("xpack.monitoring.exporters.plaintext.ssl.truststore.path", truststore) .put("xpack.monitoring.exporters.plaintext.ssl.truststore.password", "testnode") .put("xpack.monitoring.exporters.secure.type", "http") .put("xpack.monitoring.exporters.secure.enabled", true) .put("xpack.monitoring.exporters.secure.host", address) - .put("xpack.monitoring.exporters.secure.ssl.truststore.path", keystore); + .put("xpack.monitoring.exporters.secure.ssl.truststore.path", truststore); secureSettings = new MockSecureSettings(); secureSettings.setString("xpack.monitoring.exporters.secure.ssl.truststore.secure_password", "testnode"); @@ -95,9 +91,13 @@ protected Settings nodeSettings(int nodeOrdinal) { } private MockWebServer buildWebServer() throws IOException { + final Path cert = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.crt"); + final Path key = getDataPath("/org/elasticsearch/xpack/monitoring/exporter/http/testnode.pem"); + final Settings sslSettings = Settings.builder() - .put("xpack.ssl.keystore.path", keystore) - .put("xpack.ssl.keystore.password", "testnode") + .put("xpack.ssl.certificate", cert) + .put("xpack.ssl.key", key) + .put("xpack.ssl.key_passphrase", "testnode") .put(globalSettings) .build(); diff --git a/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.crt b/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.crt new file mode 100644 index 0000000000000..08c160bcea5ff --- /dev/null +++ b/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID0zCCArugAwIBAgIJALi5bDfjMszLMA0GCSqGSIb3DQEBCwUAMEgxDDAKBgNV +BAoTA29yZzEWMBQGA1UECxMNZWxhc3RpY3NlYXJjaDEgMB4GA1UEAxMXRWxhc3Rp +Y3NlYXJjaCBUZXN0IE5vZGUwHhcNMTUwOTIzMTg1MjU3WhcNMTkwOTIyMTg1MjU3 +WjBIMQwwCgYDVQQKEwNvcmcxFjAUBgNVBAsTDWVsYXN0aWNzZWFyY2gxIDAeBgNV +BAMTF0VsYXN0aWNzZWFyY2ggVGVzdCBOb2RlMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3rGZ1QbsW0+MuyrSLmMfDFKtLBkIFW8V0gRuurFg1PUKKNR1 +Mq2tMVwjjYETAU/UY0iKZOzjgvYPKhDTYBTte/WHR1ZK4CYVv7TQX/gtFQG/ge/c +7u0sLch9p7fbd+/HZiLS/rBEZDIohvgUvzvnA8+OIYnw4kuxKo/5iboAIS41klMg +/lATm8V71LMY68inht71/ZkQoAHKgcR9z4yNYvQ1WqKG8DG8KROXltll3sTrKbl5 +zJhn660es/1ZnR6nvwt6xnSTl/mNHMjkfv1bs4rJ/py3qPxicdoSIn/KyojUcgHV +F38fuAy2CQTdjVG5fWj9iz+mQvLm3+qsIYQdFwIDAQABo4G/MIG8MAkGA1UdEwQC +MAAwHQYDVR0OBBYEFEMMWLWQi/g83PzlHYqAVnty5L7HMIGPBgNVHREEgYcwgYSC +CWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluggpsb2NhbGhvc3Q0ghds +b2NhbGhvc3Q0LmxvY2FsZG9tYWluNIIKbG9jYWxob3N0NoIXbG9jYWxob3N0Ni5s +b2NhbGRvbWFpbjaHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQEL +BQADggEBAMjGGXT8Nt1tbl2GkiKtmiuGE2Ej66YuZ37WSJViaRNDVHLlg87TCcHe +k2rdO+6sFqQbbzEfwQ05T7xGmVu7tm54HwKMRugoQ3wct0bQC5wEWYN+oMDvSyO6 +M28mZwWb4VtR2IRyWP+ve5DHwTM9mxWa6rBlGzsQqH6YkJpZojzqk/mQTug+Y8aE +mVoqRIPMHq9ob+S9qd5lp09+MtYpwPfTPx/NN+xMEooXWW/ARfpGhWPkg/FuCu4z +1tFmCqHgNcWirzMm3dQpF78muE9ng6OB2MXQwL4VgnVkxmlZNHbkR2v/t8MyZJxC +y4g6cTMM3S/UMt5/+aIB2JAuMKyuD+A= +-----END CERTIFICATE----- diff --git a/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.pem b/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.pem new file mode 100644 index 0000000000000..5a67e1033440d --- /dev/null +++ b/x-pack/plugin/monitoring/src/test/resources/org/elasticsearch/xpack/monitoring/exporter/http/testnode.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,9D867F7E0C94D013 + +dVoVCjPeg1wgS7rVtOvGfQcrZyLkx393aWRnFq45tbjKBVuITtJ9vI7o4QXOV/15 +Gnb6WhXGIdWrzsxEAd46K6hIuNSISd4Emsx6c2Q5hTqWXXfexbOZBNfTtXtdJPnJ +1jAaikhtztLo3JSLTKNY5sNxd+XbaQyYVUWvueK6zOaIIMETvB+VPVFd9i1ROibk +Sgdtyj01KjkoalifqK/tA0CIYNKL0S6/eoK3UhAlpIprlpV+cnXa940C6bjLeJPt +PMAGGp5RrplxSgrSerw3I9DOWkHGtpqzIka3XneNUXJP8k4HUJ+aZkGH2ZILKS8d +4KMIb+KZSpHEGn+6uGccWLtZZmAjWJrDw56JbQtSHdRYLBRSOjLbTvQoPu/2Hpli +7HOxbotlvjptMunncq5aqK57SHA1dh0cwF7J3LUmGFJ67eoz+VV3b5qMn4MopSeI +mS16Ydd3nGpjSrln/elM0CQxqWfcOAXRZpDpFUQoXcBrLVzvz2DBl/0CrTRLhgzi +CO+5/IVcBWRlYpRNGgjjP7q0j6URID3jk5J06fYQXmBiwQT5j+GZqqzpMCJ9mIy2 +1O9SN1hebJnIcEU+E0njn/MGjlYdPywhaCy8pqElp6Q8TUEJpwLRFO/owCoBet/n +ZmCXUjfCGhc1pWHufFcDEQ6xMgEWWY/tdwCZeSU7EhErTjCbfupg+55A5fpDml0m +3wH4CFcuRjlqyx6Ywixm1ATeitDtJl5HQTw6b8OtEXwSgRmZ0eSqSRVk9QbVS7gu +IpQe09/Zimb5HzjZqZ3fdqHlcW4xax8hyJeyIvF5ZJ57eY8CBvu/wP2GDn26QnvF +xQqdfDbq1H4JmpwUHpbFwBoQK4Q6WFd1z4EA9bRQeo3H9PoqoOwMDjzajwLRF7b7 +q6tYH/n9PyHwdf1c4fFwgSmL1toXGfKlA9hjIaLsRSDD6srT5EdUk78bsnddwI51 +tu7C7P4JG+h1VdRNMNTlqtileWsIE7Nn2A1OkcUxZdF5mamENpDpJcHePLto6c8q +FKiwyFMsxhgsj6HK2HqO+UA4sX5Ni4oHwiPmb//EZLn045M5i1AN26KosJmb8++D +sgR5reWRy+UqJCTYblVg+7Dx++ggUnfxVyQEsWmw5r5f4KU5wXBkvoVMGtPNa9DE +n/uLtObD1qkNL38pRsr2OGRchYCgEoKGqEISBP4knfGXLOlWiW/246j9QzI97r1u +tvy7fKg28G7AUz9l6bpewsPHefBUeRQeieP9eJINaEpxkF/w2RpKDLpQjWxwDDOM +s+D0mrBMJve17AmJ8rMw6dIQPZYNZ88/jz1uQuUwQ2YlbmtZbCG81k9YMFGEU9XS +cyhJxj8hvYnt2PR5Z9/cJPyWOs0m/ufOeeQQ8SnU/lzmrQnpzUd2Z6p5i/B7LdRP +n1kX+l1qynuPnjvBz4nJQE0p6nzW8RyCDSniC9mtYtZmhgC8icqxgbvS7uEOBIYJ +NbK+0bEETTO34iY/JVTIqLOw3iQZYMeUpxpj6Phgx/oooxMTquMecPKNgeVtaBst +qjTNPX0ti1/HYpZqzYi8SV8YjHSJWCVMsZjKPr3W/HIcCKqYoIfgzi83Ha2KMQx6 +-----END RSA PRIVATE KEY----- From 44c4cf1f5620c769e7d1c3505066f6bae2d836b5 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Wed, 11 Jul 2018 23:19:50 +1000 Subject: [PATCH 21/22] Fix broken test --- .../authc/ldap/support/SessionFactory.java | 7 ++- .../authc/ldap/ActiveDirectoryRealmTests.java | 52 +++++++++++-------- 2 files changed, 36 insertions(+), 23 deletions(-) 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 e7a344555c98e..d062e45889524 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 @@ -26,7 +26,6 @@ import org.elasticsearch.xpack.core.ssl.SSLService; import javax.net.SocketFactory; - import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; @@ -141,7 +140,11 @@ protected static LDAPConnectionOptions connectionOptions(RealmConfig config, sslConfigurationSettings.verificationMode.getKey() + "] may not be used at the same time"); } else if (verificationModeExists) { - final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(RealmSettings.getFullSettingKey(config, "ssl")); + final String sslKey = RealmSettings.getFullSettingKey(config, "ssl"); + final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(sslKey); + if (sslConfiguration == null) { + throw new IllegalStateException("cannot find SSL configuration for " + sslKey); + } if (sslConfiguration.verificationMode().isHostnameVerificationEnabled()) { options.setSSLSocketVerifier(new HostNameSSLSocketVerifier(true)); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java index 739523795e7c5..2c6756aada7ac 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.env.Environment; import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.TestThreadPool; @@ -140,9 +141,25 @@ public boolean enableWarningsCheck() { return false; } + /** + * Creates a realm with the provided settings, rebuilds the SSL Service to be aware of the new realm, and then returns + * the RealmConfig + */ + private RealmConfig setupRealm(String realmName, Settings settings) { + final Settings merged = Settings.builder() + .put(settings) + .normalizePrefix("xpack.security.authc.realms." + realmName + ".") + .put(globalSettings) + .build(); + + final Environment env = TestEnvironment.newEnvironment(merged); + this.sslService = new SSLService(merged, env); + return new RealmConfig(realmName, settings, merged, env, new ThreadContext(merged)); + } + public void testAuthenticateUserPrincipleName() throws Exception { Settings settings = settings(); - RealmConfig config = new RealmConfig("testAuthenticateUserPrincipleName", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testAuthenticateUserPrincipleName", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -158,7 +175,7 @@ public void testAuthenticateUserPrincipleName() throws Exception { public void testAuthenticateSAMAccountName() throws Exception { Settings settings = settings(); - RealmConfig config = new RealmConfig("testAuthenticateSAMAccountName", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testAuthenticateSAMAccountName", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -182,7 +199,7 @@ protected String[] ldapUrls() throws LDAPException { public void testAuthenticateCachesSuccessfulAuthentications() throws Exception { Settings settings = settings(); - RealmConfig config = new RealmConfig("testAuthenticateCachesSuccesfulAuthentications", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testAuthenticateCachesSuccesfulAuthentications", settings); ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService, threadPool)); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -200,7 +217,7 @@ public void testAuthenticateCachesSuccessfulAuthentications() throws Exception { public void testAuthenticateCachingCanBeDisabled() throws Exception { Settings settings = settings(Settings.builder().put(CachingUsernamePasswordRealmSettings.CACHE_TTL_SETTING.getKey(), -1).build()); - RealmConfig config = new RealmConfig("testAuthenticateCachingCanBeDisabled", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testAuthenticateCachingCanBeDisabled", settings); ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService, threadPool)); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -218,7 +235,7 @@ public void testAuthenticateCachingCanBeDisabled() throws Exception { public void testAuthenticateCachingClearsCacheOnRoleMapperRefresh() throws Exception { Settings settings = settings(); - RealmConfig config = new RealmConfig("testAuthenticateCachingClearsCacheOnRoleMapperRefresh", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testAuthenticateCachingClearsCacheOnRoleMapperRefresh", settings); ActiveDirectorySessionFactory sessionFactory = spy(new ActiveDirectorySessionFactory(config, sslService, threadPool)); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -266,8 +283,7 @@ private void doUnauthenticatedLookup(boolean pooled) throws Exception { builder.setSecureSettings(secureSettings); } Settings settings = settings(builder.build()); - RealmConfig config = new RealmConfig("testUnauthenticatedLookupWithConnectionPool", settings, globalSettings, - TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testUnauthenticatedLookupWithConnectionPool", settings); try (ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool)) { DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -284,7 +300,7 @@ public void testRealmMapsGroupsToRoles() throws Exception { Settings settings = settings(Settings.builder() .put(ROLE_MAPPING_FILE_SETTING, getDataPath("role_mapping.yml")) .build()); - RealmConfig config = new RealmConfig("testRealmMapsGroupsToRoles", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testRealmMapsGroupsToRoles", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -300,7 +316,7 @@ public void testRealmMapsUsersToRoles() throws Exception { Settings settings = settings(Settings.builder() .put(ROLE_MAPPING_FILE_SETTING, getDataPath("role_mapping.yml")) .build()); - RealmConfig config = new RealmConfig("testRealmMapsGroupsToRoles", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testRealmMapsGroupsToRoles", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -318,8 +334,7 @@ public void testRealmUsageStats() throws Exception { .put(ROLE_MAPPING_FILE_SETTING, getDataPath("role_mapping.yml")) .put("load_balance.type", loadBalanceType) .build()); - RealmConfig config = new RealmConfig("testRealmUsageStats", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testRealmUsageStats", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = new DnRoleMapper(config, resourceWatcherService); LdapRealm realm = new LdapRealm(LdapRealmSettings.AD_TYPE, config, sessionFactory, roleMapper, threadPool); @@ -337,8 +352,7 @@ public void testRealmUsageStats() throws Exception { public void testDefaultSearchFilters() throws Exception { Settings settings = settings(); - RealmConfig config = new RealmConfig("testDefaultSearchFilters", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testDefaultSearchFilters", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); assertEquals("(&(objectClass=user)(|(sAMAccountName={0})(userPrincipalName={0}@ad.test.elasticsearch.com)))", sessionFactory.defaultADAuthenticator.getUserSearchFilter()); @@ -352,8 +366,7 @@ public void testCustomSearchFilters() throws Exception { .put(ActiveDirectorySessionFactorySettings.AD_UPN_USER_SEARCH_FILTER_SETTING, "(objectClass=upn)") .put(ActiveDirectorySessionFactorySettings.AD_DOWN_LEVEL_USER_SEARCH_FILTER_SETTING, "(objectClass=down level)") .build()); - RealmConfig config = new RealmConfig("testDefaultSearchFilters", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), - new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testDefaultSearchFilters", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); assertEquals("(objectClass=default)", sessionFactory.defaultADAuthenticator.getUserSearchFilter()); assertEquals("(objectClass=upn)", sessionFactory.upnADAuthenticator.getUserSearchFilter()); @@ -364,8 +377,7 @@ public void testBuildUrlFromDomainNameAndDefaultPort() throws Exception { Settings settings = Settings.builder() .put(ActiveDirectorySessionFactorySettings.AD_DOMAIN_NAME_SETTING, "ad.test.elasticsearch.com") .build(); - RealmConfig config = new RealmConfig("testBuildUrlFromDomainNameAndDefaultPort", settings, globalSettings, - TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testBuildUrlFromDomainNameAndDefaultPort", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); assertSingleLdapServer(sessionFactory, "ad.test.elasticsearch.com", 389); } @@ -375,8 +387,7 @@ public void testBuildUrlFromDomainNameAndCustomPort() throws Exception { .put(ActiveDirectorySessionFactorySettings.AD_DOMAIN_NAME_SETTING, "ad.test.elasticsearch.com") .put(ActiveDirectorySessionFactorySettings.AD_LDAP_PORT_SETTING.getKey(), 10389) .build(); - RealmConfig config = new RealmConfig("testBuildUrlFromDomainNameAndCustomPort", settings, globalSettings, - TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testBuildUrlFromDomainNameAndCustomPort", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); assertSingleLdapServer(sessionFactory, "ad.test.elasticsearch.com", 10389); } @@ -386,8 +397,7 @@ public void testUrlConfiguredInSettings() throws Exception { .put(ActiveDirectorySessionFactorySettings.AD_DOMAIN_NAME_SETTING, "ad.test.elasticsearch.com") .put(SessionFactorySettings.URLS_SETTING, "ldap://ad01.testing.elastic.co:20389/") .build(); - RealmConfig config = new RealmConfig("testBuildUrlFromDomainNameAndCustomPort", settings, globalSettings, - TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = setupRealm("testBuildUrlFromDomainNameAndCustomPort", settings); ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); assertSingleLdapServer(sessionFactory, "ad01.testing.elastic.co", 20389); } From bc3095e446a1c26938e009f333c69e369e5094f7 Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Thu, 12 Jul 2018 13:49:16 +1000 Subject: [PATCH 22/22] Fix broken tests --- .../security/authc/ldap/LdapRealmTests.java | 68 +++++++++++++------ .../ldap/support/SessionFactoryTests.java | 38 +++++++---- .../SecurityNetty4ServerTransportTests.java | 2 +- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java index 2e79a45363b2d..4aff821217d14 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.env.Environment; import org.elasticsearch.env.TestEnvironment; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; @@ -19,6 +20,7 @@ import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; import org.elasticsearch.xpack.core.security.authc.Realm; import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.ldap.LdapRealmSettings; import org.elasticsearch.xpack.core.security.authc.ldap.LdapSessionFactorySettings; import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope; @@ -64,15 +66,15 @@ public class LdapRealmTests extends LdapTestCase { private ThreadPool threadPool; private ResourceWatcherService resourceWatcherService; - private Settings globalSettings; + private Settings defaultGlobalSettings; private SSLService sslService; @Before public void init() throws Exception { threadPool = new TestThreadPool("ldap realm tests"); resourceWatcherService = new ResourceWatcherService(Settings.EMPTY, threadPool); - globalSettings = Settings.builder().put("path.home", createTempDir()).build(); - sslService = new SSLService(globalSettings, TestEnvironment.newEnvironment(globalSettings)); + defaultGlobalSettings = Settings.builder().put("path.home", createTempDir()).build(); + sslService = new SSLService(defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings)); } @After @@ -85,7 +87,7 @@ public void testAuthenticateSubTreeGroupSearch() throws Exception { String groupSearchBase = "o=sevenSeas"; String userTemplate = VALID_USER_TEMPLATE; Settings settings = buildLdapSettings(ldapUrls(), userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); LdapRealm ldap = new LdapRealm(LdapRealmSettings.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool); @@ -109,7 +111,7 @@ public void testAuthenticateOneLevelGroupSearch() throws Exception { Settings settings = Settings.builder() .put(buildLdapSettings(ldapUrls(), userTemplate, groupSearchBase, LdapSearchScope.ONE_LEVEL)) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); LdapRealm ldap = @@ -134,7 +136,7 @@ public void testAuthenticateCaching() throws Exception { Settings settings = Settings.builder() .put(buildLdapSettings(ldapUrls(), userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); ldapFactory = spy(ldapFactory); @@ -159,7 +161,7 @@ public void testAuthenticateCachingRefresh() throws Exception { Settings settings = Settings.builder() .put(buildLdapSettings(ldapUrls(), userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); DnRoleMapper roleMapper = buildGroupAsRoleMapper(resourceWatcherService); @@ -192,7 +194,7 @@ public void testAuthenticateNoncaching() throws Exception { .put(buildLdapSettings(ldapUrls(), userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) .put(CachingUsernamePasswordRealmSettings.CACHE_TTL_SETTING.getKey(), -1) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); ldapFactory = spy(ldapFactory); @@ -219,8 +221,18 @@ public void testLdapRealmSelectsLdapSessionFactory() throws Exception { .put("group_search.scope", LdapSearchScope.SUB_TREE) .put("ssl.verification_mode", VerificationMode.CERTIFICATE) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); - SessionFactory sessionFactory = LdapRealm.sessionFactory(config, sslService, threadPool, LdapRealmSettings.LDAP_TYPE); + + final String realmName = "test-ldap-realm"; + final Settings globalSettings = Settings.builder() + .put(settings) + .normalizePrefix(RealmSettings.PREFIX + realmName + ".") + .put(defaultGlobalSettings) + .build(); + + final Environment env = TestEnvironment.newEnvironment(globalSettings); + final RealmConfig config = new RealmConfig(realmName, settings, globalSettings, env, new ThreadContext(globalSettings)); + SessionFactory sessionFactory = LdapRealm.sessionFactory(config, new SSLService(globalSettings, env), threadPool, + LdapRealmSettings.LDAP_TYPE); assertThat(sessionFactory, is(instanceOf(LdapSessionFactory.class))); } @@ -235,8 +247,16 @@ public void testLdapRealmSelectsLdapUserSearchSessionFactory() throws Exception .put("group_search.scope", LdapSearchScope.SUB_TREE) .put("ssl.verification_mode", VerificationMode.CERTIFICATE) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); - SessionFactory sessionFactory = LdapRealm.sessionFactory(config, sslService, threadPool, LdapRealmSettings.LDAP_TYPE); + final String realmName = "test-ldap-realm-user-search"; + final Settings globalSettings = Settings.builder() + .put(settings) + .normalizePrefix(RealmSettings.PREFIX + realmName + ".") + .put(defaultGlobalSettings) + .build(); + final Environment env = TestEnvironment.newEnvironment(globalSettings); + final RealmConfig config = new RealmConfig(realmName, settings, globalSettings, env, new ThreadContext(globalSettings)); + SessionFactory sessionFactory = LdapRealm.sessionFactory(config, new SSLService(globalSettings, env), threadPool, + LdapRealmSettings.LDAP_TYPE); try { assertThat(sessionFactory, is(instanceOf(LdapUserSearchSessionFactory.class))); } finally { @@ -259,7 +279,7 @@ public void testLdapRealmThrowsExceptionForUserTemplateAndSearchSettings() throw .put("group_search.scope", LdapSearchScope.SUB_TREE) .put("ssl.verification_mode", VerificationMode.CERTIFICATE) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> LdapRealm.sessionFactory(config, null, threadPool, LdapRealmSettings.LDAP_TYPE)); assertThat(e.getMessage(), @@ -275,7 +295,7 @@ public void testLdapRealmThrowsExceptionWhenNeitherUserTemplateNorSearchSettings .put("group_search.scope", LdapSearchScope.SUB_TREE) .put("ssl.verification_mode", VerificationMode.CERTIFICATE) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm-user-search", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> LdapRealm.sessionFactory(config, null, threadPool, LdapRealmSettings.LDAP_TYPE)); assertThat(e.getMessage(), @@ -292,7 +312,7 @@ public void testLdapRealmMapsUserDNToRole() throws Exception { .put(DnRoleMapperSettings.ROLE_MAPPING_FILE_SETTING.getKey(), getDataPath("/org/elasticsearch/xpack/security/authc/support/role_mapping.yml")) .build(); - RealmConfig config = new RealmConfig("test-ldap-realm-userdn", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm-userdn", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); LdapRealm ldap = new LdapRealm(LdapRealmSettings.LDAP_TYPE, config, ldapFactory, @@ -319,7 +339,7 @@ public void testLdapConnectionFailureIsTreatedAsAuthenticationFailure() throws E String groupSearchBase = "o=sevenSeas"; String userTemplate = VALID_USER_TEMPLATE; Settings settings = buildLdapSettings(new String[] { url.toString() }, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE); - RealmConfig config = new RealmConfig("test-ldap-realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); + RealmConfig config = new RealmConfig("test-ldap-realm", settings, defaultGlobalSettings, TestEnvironment.newEnvironment(defaultGlobalSettings), new ThreadContext(defaultGlobalSettings)); LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); LdapRealm ldap = new LdapRealm(LdapRealmSettings.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool); @@ -353,9 +373,17 @@ public void testUsageStats() throws Exception { settings.put("user_search.base_dn", ""); } - RealmConfig config = new RealmConfig("ldap-realm", settings.build(), globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); - - LdapSessionFactory ldapFactory = new LdapSessionFactory(config, sslService, threadPool); + final Settings realmSettings = settings.build(); + final String realmName = "ldap-realm"; + final Settings globalSettings = Settings.builder() + .put(realmSettings) + .normalizePrefix(RealmSettings.PREFIX + realmName + ".") + .put(defaultGlobalSettings) + .build(); + final Environment env = TestEnvironment.newEnvironment(globalSettings); + final RealmConfig config = new RealmConfig(realmName, realmSettings, globalSettings, env, new ThreadContext(globalSettings)); + + LdapSessionFactory ldapFactory = new LdapSessionFactory(config, new SSLService(globalSettings, env), threadPool); LdapRealm realm = new LdapRealm(LdapRealmSettings.LDAP_TYPE, config, ldapFactory, new DnRoleMapper(config, resourceWatcherService), threadPool); @@ -363,7 +391,7 @@ public void testUsageStats() throws Exception { realm.usageStats(future); Map stats = future.get(); assertThat(stats, is(notNullValue())); - assertThat(stats, hasEntry("name", "ldap-realm")); + assertThat(stats, hasEntry("name", realmName)); assertThat(stats, hasEntry("order", realm.order())); assertThat(stats, hasEntry("size", 0)); assertThat(stats, hasEntry("ssl", false)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryTests.java index 1a5fa6af5f8a3..d82eb520e9f18 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryTests.java @@ -19,12 +19,15 @@ import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; import org.elasticsearch.xpack.core.security.authc.ldap.support.SessionFactorySettings; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.core.ssl.VerificationMode; import org.junit.After; import org.junit.Before; +import java.util.function.Function; + import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; @@ -65,34 +68,39 @@ public void testConnectionFactoryReturnsCorrectLDAPConnectionOptions() throws Ex .put(SessionFactorySettings.FOLLOW_REFERRALS_SETTING, "false") .build(); - final Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build()); - RealmConfig realmConfig = new RealmConfig("conn settings", settings, environment.settings(), environment, new ThreadContext(Settings.EMPTY)); - LDAPConnectionOptions options = SessionFactory.connectionOptions(realmConfig, new SSLService(environment.settings(), environment), - logger); + final String realmName = "conn_settings"; + final Function globalSettings = realmSettings -> Settings.builder() + .put(realmSettings) + .normalizePrefix(RealmSettings.PREFIX + realmName + ".") + .put("path.home", createTempDir()) + .build(); + final Environment environment = TestEnvironment.newEnvironment(globalSettings.apply(settings)); + final Function sslService = realmSettings -> new SSLService(globalSettings.apply(realmSettings), environment); + + final ThreadContext threadContext = new ThreadContext(environment.settings()); + RealmConfig realmConfig = new RealmConfig(realmName, settings, environment.settings(), environment, threadContext); + LDAPConnectionOptions options = SessionFactory.connectionOptions(realmConfig, sslService.apply(settings), logger); assertThat(options.followReferrals(), is(equalTo(false))); assertThat(options.allowConcurrentSocketFactoryUse(), is(equalTo(true))); assertThat(options.getConnectTimeoutMillis(), is(equalTo(10))); assertThat(options.getResponseTimeoutMillis(), is(equalTo(20L))); assertThat(options.getSSLSocketVerifier(), is(instanceOf(TrustAllSSLSocketVerifier.class))); - assertWarnings("the setting [xpack.security.authc.realms.conn settings.hostname_verification] has been deprecated and will be " + - "removed in a future version. use [xpack.security.authc.realms.conn settings.ssl.verification_mode] instead"); + assertWarnings("the setting [xpack.security.authc.realms." + realmName + ".hostname_verification] has been deprecated" + + " and will be removed in a future version. use [xpack.security.authc.realms." + realmName + ".ssl.verification_mode] instead"); settings = Settings.builder().put("ssl.verification_mode", VerificationMode.CERTIFICATE).build(); - realmConfig = new RealmConfig("conn settings", settings, environment.settings(), environment, new ThreadContext(Settings.EMPTY)); - options = SessionFactory.connectionOptions(realmConfig, new SSLService(environment.settings(), environment), - logger); + realmConfig = new RealmConfig(realmName, settings, globalSettings.apply(settings), environment, threadContext); + options = SessionFactory.connectionOptions(realmConfig, sslService.apply(settings), logger); assertThat(options.getSSLSocketVerifier(), is(instanceOf(TrustAllSSLSocketVerifier.class))); settings = Settings.builder().put("ssl.verification_mode", VerificationMode.NONE).build(); - realmConfig = new RealmConfig("conn settings", settings, environment.settings(), environment, new ThreadContext(Settings.EMPTY)); - options = SessionFactory.connectionOptions(realmConfig, new SSLService(environment.settings(), environment), - logger); + realmConfig = new RealmConfig(realmName, settings, environment.settings(), environment, threadContext); + options = SessionFactory.connectionOptions(realmConfig, sslService.apply(settings), logger); assertThat(options.getSSLSocketVerifier(), is(instanceOf(TrustAllSSLSocketVerifier.class))); settings = Settings.builder().put("ssl.verification_mode", VerificationMode.FULL).build(); - realmConfig = new RealmConfig("conn settings", settings, environment.settings(), environment, new ThreadContext(Settings.EMPTY)); - options = SessionFactory.connectionOptions(realmConfig, new SSLService(environment.settings(), environment), - logger); + realmConfig = new RealmConfig(realmName, settings, environment.settings(), environment, threadContext); + options = SessionFactory.connectionOptions(realmConfig, sslService.apply(settings), logger); assertThat(options.getSSLSocketVerifier(), is(instanceOf(HostNameSSLSocketVerifier.class))); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java index 33f47fe7a00ba..f87ab36d3d574 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4ServerTransportTests.java @@ -201,7 +201,7 @@ public void testTransportSSLOverridesGlobalSSL() throws Exception { assertFalse(engine.getWantClientAuth()); // get the global and verify that it is different in that it requires client auth - SSLConfiguration configuration = sslService.getSSLConfiguration("_global"); + SSLConfiguration configuration = sslService.getSSLConfiguration("xpack.ssl"); assertNotNull(configuration); final SSLEngine globalEngine = sslService.createSSLEngine(configuration, null, -1); assertTrue(globalEngine.getNeedClientAuth());