diff --git a/src/main/java/org/elasticsearch/shield/ssl/SSLService.java b/src/main/java/org/elasticsearch/shield/ssl/SSLService.java index 038154042d1..0a347847948 100644 --- a/src/main/java/org/elasticsearch/shield/ssl/SSLService.java +++ b/src/main/java/org/elasticsearch/shield/ssl/SSLService.java @@ -23,24 +23,29 @@ import java.util.Arrays; * get SSLEngines and SocketFactories. */ public class SSLService extends AbstractComponent { - static final String[] DEFAULT_CIPHERS = new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" }; + + static final String[] DEFAULT_CIPHERS = new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}; public static final String SHIELD_TRANSPORT_SSL = "shield.transport.ssl"; public static final String SHIELD_HTTP_SSL = "shield.http.ssl"; public static final String SHIELD_AUTHC_LDAP_URL = "shield.authc.ldap.url"; + + private final TrustManagerFactory trustFactory; private final SSLContext sslContext; private final String[] ciphers; + private final KeyManagerFactory keyManagerFactory; + private final String sslProtocol; @Inject public SSLService(Settings settings) { super(settings); - String keyStorePath = componentSettings.get("keystore", System.getProperty("javax.net.ssl.keyStore")); - String keyStorePassword = componentSettings.get("keystore_password", System.getProperty("javax.net.ssl.keyStorePassword")); - String keyStoreAlgorithm = componentSettings.get("keystore_algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm", KeyManagerFactory.getDefaultAlgorithm())); + String keyStorePath = componentSettings.get("keystore.path", System.getProperty("javax.net.ssl.keyStore")); + String keyStorePassword = componentSettings.get("keystore.password", System.getProperty("javax.net.ssl.keyStorePassword")); + String keyStoreAlgorithm = componentSettings.get("keystore.algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm", KeyManagerFactory.getDefaultAlgorithm())); - String trustStorePath = componentSettings.get("truststore", System.getProperty("javax.net.ssl.trustStore")); - String trustStorePassword = componentSettings.get("truststore_password", System.getProperty("javax.net.ssl.trustStorePassword")); - String trustStoreAlgorithm = componentSettings.get("truststore_algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm())); + String trustStorePath = componentSettings.get("truststore.path", System.getProperty("javax.net.ssl.trustStore")); + String trustStorePassword = componentSettings.get("truststore.password", System.getProperty("javax.net.ssl.trustStorePassword")); + String trustStoreAlgorithm = componentSettings.get("truststore.algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm())); if (trustStorePath == null) { //the keystore will also be the truststore @@ -57,46 +62,14 @@ public class SSLService extends AbstractComponent { this.ciphers = componentSettings.getAsArray("ciphers", DEFAULT_CIPHERS); //protocols supported: https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext - String sslProtocol = componentSettings.get("protocol", "TLS"); + this.sslProtocol = componentSettings.get("protocol", "TLS"); logger.debug("using keyStore[{}], keyAlgorithm[{}], trustStore[{}], truststoreAlgorithm[{}], ciphersuites[{}], TLS protocol[{}]", keyStorePath, keyStoreAlgorithm, trustStorePath, trustStoreAlgorithm, ciphers, sslProtocol); - final TrustManagerFactory trustFactory; - try (FileInputStream in = new FileInputStream(trustStorePath)) { - // Load TrustStore - KeyStore trustStore = KeyStore.getInstance("jks"); - trustStore.load(in, trustStorePassword == null ? null : trustStorePassword.toCharArray()); - - // Initialize a trust manager factory with the trusted store - trustFactory = TrustManagerFactory.getInstance(trustStoreAlgorithm); - trustFactory.init(trustStore); - } catch (Exception e) { - throw new ElasticsearchException("Failed to initialize a TrustManagerFactory", e); - } - - KeyStore keyStore; - KeyManagerFactory keyManagerFactory; - try (FileInputStream in = new FileInputStream(keyStorePath)){ - // Load KeyStore - keyStore = KeyStore.getInstance("jks"); - keyStore.load(in, keyStorePassword.toCharArray()); - - // Initialize KeyManagerFactory - keyManagerFactory = KeyManagerFactory.getInstance(keyStoreAlgorithm); - keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); - - } catch (Exception e) { - throw new ElasticsearchSSLException("Failed to initialize a KeyManagerFactory", e); - } - - // Initialize sslContext - try { - sslContext = SSLContext.getInstance(sslProtocol); - sslContext.init(keyManagerFactory.getKeyManagers(), trustFactory.getTrustManagers(), null); - } catch (Exception e) { - throw new ElasticsearchSSLException("Failed to initialize the SSLContext", e); - } + this.trustFactory = getTrustFactory(trustStorePath, trustStorePassword, trustStoreAlgorithm); + this.keyManagerFactory = createKeyManagerFactory(keyStorePath, keyStorePassword, keyStoreAlgorithm); + this.sslContext = createSslContext(trustFactory); } /** @@ -110,26 +83,86 @@ public class SSLService extends AbstractComponent { * This engine is configured with a trust manager and a keystore that should have only one private key. * Four possible usages for elasticsearch exist: * Node-to-Node outbound: - * - sslEngine.setUseClientMode(true) + * - sslEngine.setUseClientMode(true) * Node-to-Node inbound: - * - sslEngine.setUseClientMode(false) - * - sslEngine.setNeedClientAuth(true) + * - sslEngine.setUseClientMode(false) + * - sslEngine.setNeedClientAuth(true) * Client-to-Node: - * - sslEngine.setUseClientMode(true) + * - sslEngine.setUseClientMode(true) * Http Client-to-Node (inbound): - * - sslEngine.setUserClientMode(false) - * - sslEngine.setNeedClientAuth(false) + * - sslEngine.setUserClientMode(false) + * - sslEngine.setNeedClientAuth(false) */ public SSLEngine createSSLEngine() { + return createSSLEngine(this.sslContext); + } + + public SSLEngine createSSLEngineWithTruststore(Settings settings) { + String trustStore = settings.get("truststore.path", System.getProperty("javax.net.ssl.trustStore")); + String trustStorePassword = settings.get("truststore.password", System.getProperty("javax.net.ssl.trustStorePassword")); + String trustStoreAlgorithm = settings.get("truststore.algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm())); + + // no truststore or password, return regular ssl engine + if (trustStore == null || trustStorePassword == null) { + return createSSLEngine(); + } + + TrustManagerFactory trustFactory = getTrustFactory(trustStore, trustStorePassword, trustStoreAlgorithm); + SSLContext customTruststoreSSLContext = createSslContext(trustFactory); + return createSSLEngine(customTruststoreSSLContext); + } + + private SSLEngine createSSLEngine(SSLContext sslContext) { SSLEngine sslEngine = sslContext.createSSLEngine(); try { sslEngine.setEnabledCipherSuites(ciphers); } catch (Throwable t) { - throw new ElasticsearchSSLException("Error loading cipher suites ["+ Arrays.asList(ciphers)+"]", t); + throw new ElasticsearchSSLException("Error loading cipher suites [" + Arrays.asList(ciphers) + "]", t); } return sslEngine; } + private KeyManagerFactory createKeyManagerFactory(String keyStore, String keyStorePassword, String keyStoreAlgorithm) { + try (FileInputStream in = new FileInputStream(keyStore)) { + // Load KeyStore + KeyStore ks = KeyStore.getInstance("jks"); + ks.load(in, keyStorePassword.toCharArray()); + + // Initialize KeyManagerFactory + KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyStoreAlgorithm); + kmf.init(ks, keyStorePassword.toCharArray()); + return kmf; + } catch (Exception e) { + throw new ElasticsearchSSLException("Failed to initialize a KeyManagerFactory", e); + } + } + + private SSLContext createSslContext(TrustManagerFactory trustFactory) { + // Initialize sslContext + try { + SSLContext sslContext = SSLContext.getInstance(sslProtocol); + sslContext.init(keyManagerFactory.getKeyManagers(), trustFactory.getTrustManagers(), null); + return sslContext; + } catch (Exception e) { + throw new ElasticsearchSSLException("Failed to initialize the SSLContext", e); + } + } + + private TrustManagerFactory getTrustFactory(String trustStore, String trustStorePassword, String trustStoreAlgorithm) { + try (FileInputStream in = new FileInputStream(trustStore)) { + // Load TrustStore + KeyStore ks = KeyStore.getInstance("jks"); + ks.load(in, trustStorePassword == null ? null : trustStorePassword.toCharArray()); + + // Initialize a trust manager factory with the trusted store + TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(trustStoreAlgorithm); + trustFactory.init(ks); + return trustFactory; + } catch (Exception e) { + throw new ElasticsearchException("Failed to initialize a TrustManagerFactory", e); + } + } + public static boolean isSSLEnabled(Settings settings) { return settings.getAsBoolean(SHIELD_TRANSPORT_SSL, false) || settings.getAsBoolean(SHIELD_HTTP_SSL, false) || diff --git a/src/main/java/org/elasticsearch/shield/transport/SecuredTransportModule.java b/src/main/java/org/elasticsearch/shield/transport/SecuredTransportModule.java index 15eed1e48e1..017d0ea8993 100644 --- a/src/main/java/org/elasticsearch/shield/transport/SecuredTransportModule.java +++ b/src/main/java/org/elasticsearch/shield/transport/SecuredTransportModule.java @@ -8,13 +8,11 @@ package org.elasticsearch.shield.transport; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.inject.PreProcessModule; -import org.elasticsearch.common.inject.util.Providers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.SecurityFilter; import org.elasticsearch.shield.plugin.ShieldPlugin; import org.elasticsearch.shield.support.AbstractShieldModule; import org.elasticsearch.shield.transport.n2n.IPFilteringN2NAuthenticator; -import org.elasticsearch.shield.transport.netty.N2NNettyUpstreamHandler; import org.elasticsearch.shield.transport.netty.NettySecuredHttpServerTransportModule; import org.elasticsearch.shield.transport.netty.NettySecuredTransportModule; import org.elasticsearch.transport.TransportModule; @@ -52,7 +50,6 @@ public class SecuredTransportModule extends AbstractShieldModule.Spawn implement if (clientMode) { // no ip filtering on the client - bind(N2NNettyUpstreamHandler.class).toProvider(Providers.of(null)); bind(ServerTransportFilter.class).toInstance(ServerTransportFilter.NOOP); return; } @@ -60,9 +57,6 @@ public class SecuredTransportModule extends AbstractShieldModule.Spawn implement bind(ServerTransportFilter.class).to(SecurityFilter.ServerTransport.class).asEagerSingleton(); if (settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true)) { bind(IPFilteringN2NAuthenticator.class).asEagerSingleton(); - bind(N2NNettyUpstreamHandler.class).asEagerSingleton(); - } else { - bind(N2NNettyUpstreamHandler.class).toProvider(Providers.of(null)); } } } diff --git a/src/main/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticator.java b/src/main/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticator.java index 19f1408c267..5da09bead09 100644 --- a/src/main/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticator.java +++ b/src/main/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticator.java @@ -41,11 +41,11 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 private static final Pattern COMMA_DELIM = Pattern.compile("\\s*,\\s*"); private static final String DEFAULT_FILE = "ip_filter.yml"; - private static final IpFilterRule[] NO_RULES = new IpFilterRule[0]; + private static final ProfileIpFilterRule[] NO_RULES = new ProfileIpFilterRule[0]; private final Path file; - private volatile IpFilterRule[] rules = NO_RULES; + private volatile ProfileIpFilterRule[] rules = NO_RULES; @Inject public IPFilteringN2NAuthenticator(Settings settings, Environment env, ResourceWatcherService watcherService) { @@ -65,12 +65,12 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 return Paths.get(location); } - public static IpFilterRule[] parseFile(Path path, ESLogger logger) { + public static ProfileIpFilterRule[] parseFile(Path path, ESLogger logger) { if (!Files.exists(path)) { return NO_RULES; } - List rules = new ArrayList<>(); + List rules = new ArrayList<>(); try (XContentParser parser = YamlXContent.yamlXContent.createParser(Files.newInputStream(path))) { XContentParser.Token token; @@ -78,8 +78,8 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT && token != null) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); - if (!"allow".equals(currentFieldName) && !"deny".equals(currentFieldName)) { - throw new ElasticsearchParseException("Field name [" + currentFieldName + "] not valid. Must be [allow] or [deny]"); + if (!currentFieldName.endsWith("allow") && !currentFieldName.endsWith("deny")) { + throw new ElasticsearchParseException("Field name [" + currentFieldName + "] not valid. Must be [allow] or [deny] or using a profile"); } } else if (token == XContentParser.Token.VALUE_STRING && currentFieldName != null) { String value = parser.text(); @@ -87,14 +87,15 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 throw new ElasticsearchParseException("Field value for fieldname [" + currentFieldName + "] must not be empty"); } - boolean isAllowRule = currentFieldName.equals("allow"); + boolean isAllowRule = currentFieldName.endsWith("allow"); + String profile = currentFieldName.contains(".") ? currentFieldName.substring(0, currentFieldName.indexOf(".")) : "default"; if (value.contains(",")) { for (String rule : COMMA_DELIM.split(parser.text().trim())) { - rules.add(getRule(isAllowRule, rule)); + rules.add(new ProfileIpFilterRule(profile, getRule(isAllowRule, rule))); } } else { - rules.add(getRule(isAllowRule, value)); + rules.add(new ProfileIpFilterRule(profile, getRule(isAllowRule, value))); } } @@ -108,7 +109,7 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 } logger.debug("Loaded {} ip filtering rules", rules.size()); - return rules.toArray(new IpFilterRule[rules.size()]); + return rules.toArray(new ProfileIpFilterRule[rules.size()]); } private static IpFilterRule getRule(boolean isAllowRule, String value) throws UnknownHostException { @@ -124,9 +125,9 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 } @Override - public boolean authenticate(@Nullable Principal peerPrincipal, InetAddress peerAddress, int peerPort) { - for (IpFilterRule rule : rules) { - if (rule.contains(peerAddress)) { + public boolean authenticate(@Nullable Principal peerPrincipal, String profile, InetAddress peerAddress, int peerPort) { + for (ProfileIpFilterRule rule : rules) { + if (rule.contains(profile, peerAddress)) { boolean isAllowed = rule.isAllowRule(); logger.trace("Authentication rule matched for host [{}]: {}", peerAddress, isAllowed); return isAllowed; diff --git a/src/main/java/org/elasticsearch/shield/transport/n2n/N2NAuthenticator.java b/src/main/java/org/elasticsearch/shield/transport/n2n/N2NAuthenticator.java index 27b50ed8d08..c12d9d67c83 100644 --- a/src/main/java/org/elasticsearch/shield/transport/n2n/N2NAuthenticator.java +++ b/src/main/java/org/elasticsearch/shield/transport/n2n/N2NAuthenticator.java @@ -15,32 +15,6 @@ import java.security.Principal; */ public interface N2NAuthenticator { - N2NAuthenticator NO_AUTH = new N2NAuthenticator() { - @Override - public boolean authenticate(@Nullable Principal peerPrincipal, InetAddress peerAddress, int peerPort) { - return true; - } - }; + boolean authenticate(@Nullable Principal peerPrincipal, @Nullable String profile, InetAddress peerAddress, int peerPort); - boolean authenticate(@Nullable Principal peerPrincipal, InetAddress peerAddress, int peerPort); - - - class Compound implements N2NAuthenticator { - - private N2NAuthenticator[] authenticators; - - public Compound(N2NAuthenticator... authenticators) { - this.authenticators = authenticators; - } - - @Override - public boolean authenticate(@Nullable Principal peerPrincipal, InetAddress peerAddress, int peerPort) { - for (int i = 0; i < authenticators.length; i++) { - if (!authenticators[i].authenticate(peerPrincipal, peerAddress, peerPort)) { - return false; - } - } - return true; - } - } } diff --git a/src/main/java/org/elasticsearch/shield/transport/n2n/ProfileIpFilterRule.java b/src/main/java/org/elasticsearch/shield/transport/n2n/ProfileIpFilterRule.java new file mode 100644 index 00000000000..8b9cde1030b --- /dev/null +++ b/src/main/java/org/elasticsearch/shield/transport/n2n/ProfileIpFilterRule.java @@ -0,0 +1,36 @@ +/* + * 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.shield.transport.n2n; + +import org.elasticsearch.common.netty.handler.ipfilter.IpFilterRule; + +import java.net.InetAddress; + +/** + * helper interface for filter rules, which takes a tcp transport profile into account + */ +public class ProfileIpFilterRule { + + private final String profile; + private final IpFilterRule ipFilterRule; + + public ProfileIpFilterRule(String profile, IpFilterRule ipFilterRule) { + this.profile = profile; + this.ipFilterRule = ipFilterRule; + } + + public boolean contains(String profile, InetAddress inetAddress) { + return this.profile.equals(profile) && ipFilterRule.contains(inetAddress); + } + + public boolean isAllowRule() { + return ipFilterRule.isAllowRule(); + } + + public boolean isDenyRule() { + return ipFilterRule.isDenyRule(); + } +} diff --git a/src/main/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandler.java b/src/main/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandler.java index 20f4e8059f1..2ad50dc8691 100644 --- a/src/main/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandler.java +++ b/src/main/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandler.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.shield.transport.netty; -import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.netty.channel.ChannelEvent; import org.elasticsearch.common.netty.channel.ChannelHandler; import org.elasticsearch.common.netty.channel.ChannelHandlerContext; @@ -20,17 +19,18 @@ import java.net.InetSocketAddress; @ChannelHandler.Sharable public class N2NNettyUpstreamHandler extends IpFilteringHandlerImpl { - private IPFilteringN2NAuthenticator authenticator; + private final IPFilteringN2NAuthenticator authenticator; + private final String profile; - @Inject - public N2NNettyUpstreamHandler(IPFilteringN2NAuthenticator authenticator) { + public N2NNettyUpstreamHandler(IPFilteringN2NAuthenticator authenticator, String profile) { this.authenticator = authenticator; + this.profile = profile; } @Override protected boolean accept(ChannelHandlerContext channelHandlerContext, ChannelEvent channelEvent, InetSocketAddress inetSocketAddress) throws Exception { // at this stage no auth has happened, so we do not have any principal anyway - return authenticator.authenticate(null, inetSocketAddress.getAddress(), inetSocketAddress.getPort()); + return authenticator.authenticate(null, profile, inetSocketAddress.getAddress(), inetSocketAddress.getPort()); } } diff --git a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredHttpServerTransport.java b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredHttpServerTransport.java index d40527e06a8..2cb1bbf054c 100644 --- a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredHttpServerTransport.java +++ b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredHttpServerTransport.java @@ -15,6 +15,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.http.netty.NettyHttpServerTransport; import org.elasticsearch.shield.ssl.SSLService; +import org.elasticsearch.shield.transport.n2n.IPFilteringN2NAuthenticator; import javax.net.ssl.SSLEngine; @@ -24,17 +25,19 @@ import javax.net.ssl.SSLEngine; public class NettySecuredHttpServerTransport extends NettyHttpServerTransport { private final boolean ssl; - private final N2NNettyUpstreamHandler shieldUpstreamHandler; + private final boolean ipFilterEnabled; + private final IPFilteringN2NAuthenticator authenticator; private final SSLService sslService; @Inject public NettySecuredHttpServerTransport(Settings settings, NetworkService networkService, BigArrays bigArrays, - @Nullable N2NNettyUpstreamHandler shieldUpstreamHandler, @Nullable SSLService sslService) { + @Nullable IPFilteringN2NAuthenticator authenticator, @Nullable SSLService sslService) { super(settings, networkService, bigArrays); + this.authenticator = authenticator; this.ssl = settings.getAsBoolean("shield.http.ssl", false); this.sslService = sslService; - this.shieldUpstreamHandler = shieldUpstreamHandler; assert !ssl || sslService != null : "ssl is enabled yet the ssl service is null"; + this.ipFilterEnabled = settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true); } @Override @@ -58,8 +61,8 @@ public class NettySecuredHttpServerTransport extends NettyHttpServerTransport { pipeline.addFirst("ssl", new SslHandler(engine)); } - if (shieldUpstreamHandler != null) { - pipeline.addFirst("ipfilter", shieldUpstreamHandler); + if (ipFilterEnabled) { + pipeline.addFirst("ipfilter", new N2NNettyUpstreamHandler(authenticator, "default")); } return pipeline; } diff --git a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java index 589c3b63e41..08fc8958044 100644 --- a/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java +++ b/src/main/java/org/elasticsearch/shield/transport/netty/NettySecuredTransport.java @@ -15,6 +15,7 @@ import org.elasticsearch.common.network.NetworkService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.shield.ssl.SSLService; +import org.elasticsearch.shield.transport.n2n.IPFilteringN2NAuthenticator; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.netty.NettyTransport; @@ -26,16 +27,18 @@ import javax.net.ssl.SSLEngine; public class NettySecuredTransport extends NettyTransport { private final boolean ssl; - private final N2NNettyUpstreamHandler shieldUpstreamHandler; private final SSLService sslService; + private final boolean ipFilterEnabled; + private final IPFilteringN2NAuthenticator authenticator; @Inject public NettySecuredTransport(Settings settings, ThreadPool threadPool, NetworkService networkService, BigArrays bigArrays, Version version, - @Nullable N2NNettyUpstreamHandler shieldUpstreamHandler, @Nullable SSLService sslService) { + @Nullable IPFilteringN2NAuthenticator authenticator, @Nullable SSLService sslService) { super(settings, threadPool, networkService, bigArrays, version); - this.shieldUpstreamHandler = shieldUpstreamHandler; - this.ssl = settings.getAsBoolean("shield.transport.ssl", false); + this.authenticator = authenticator; + this.ipFilterEnabled = settings.getAsBoolean("shield.transport.n2n.ip_filter.enabled", true); this.sslService = sslService; + this.ssl = settings.getAsBoolean("shield.transport.ssl", false); assert !ssl || sslService != null : "ssl is enabled yet the ssl service is null"; } @@ -51,23 +54,31 @@ public class NettySecuredTransport extends NettyTransport { private class SslServerChannelPipelineFactory extends ServerChannelPipelineFactory { + private final Settings profileSettings; + public SslServerChannelPipelineFactory(NettyTransport nettyTransport, String name, Settings settings, Settings profileSettings) { super(nettyTransport, name, settings); + this.profileSettings = profileSettings; } @Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = super.getPipeline(); if (ssl) { - SSLEngine serverEngine = sslService.createSSLEngine(); + SSLEngine serverEngine; + if (profileSettings.get("shield.truststore.path") != null) { + serverEngine = sslService.createSSLEngineWithTruststore(profileSettings.getByPrefix("shield.")); + } else { + serverEngine = sslService.createSSLEngine(); + } serverEngine.setUseClientMode(false); serverEngine.setNeedClientAuth(true); pipeline.addFirst("ssl", new SslHandler(serverEngine)); pipeline.replace("dispatcher", "dispatcher", new SecuredMessageChannelHandler(nettyTransport, logger)); } - if (shieldUpstreamHandler != null) { - pipeline.addFirst("ipfilter", shieldUpstreamHandler); + if (ipFilterEnabled) { + pipeline.addFirst("ipfilter", new N2NNettyUpstreamHandler(authenticator, name)); } return pipeline; } diff --git a/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java b/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java index b4f67e5f938..0acec428782 100644 --- a/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/active_directory/ActiveDirectoryFactoryTests.java @@ -37,8 +37,8 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase { public static void setTrustStore() throws URISyntaxException { File filename = new File(LdapConnectionTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).getAbsoluteFile(); LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder() - .put("shield.ssl.keystore", filename) - .put("shield.ssl.keystore_password", "changeit") + .put("shield.ssl.keystore.path", filename) + .put("shield.ssl.keystore.password", "changeit") .build())); } diff --git a/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java b/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java index b8f19d043e4..bbbd173e782 100644 --- a/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java @@ -7,8 +7,8 @@ package org.elasticsearch.shield.authc.ldap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.shield.authc.support.SecuredStringTests; -import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.shield.authc.support.ldap.LdapSslSocketFactory; +import org.elasticsearch.shield.ssl.SSLService; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.junit.annotations.Network; import org.junit.AfterClass; @@ -25,14 +25,13 @@ import static org.hamcrest.Matchers.hasItem; public class OpenLdapTests extends ElasticsearchTestCase { public static final String OPEN_LDAP_URL = "ldaps://54.200.235.244:636"; public static final String PASSWORD = "NickFuryHeartsES"; - public static final String SETTINGS_PREFIX = LdapRealm.class.getPackage().getName().substring("com.elasticsearch.".length()) + '.'; @BeforeClass public static void setTrustStore() throws URISyntaxException { File filename = new File(LdapConnectionTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).getAbsoluteFile(); LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder() - .put("shield.ssl.keystore", filename) - .put("shield.ssl.keystore_password", "changeit") + .put("shield.ssl.keystore.path", filename) + .put("shield.ssl.keystore.password", "changeit") .build())); } diff --git a/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactoryTests.java b/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactoryTests.java index a1162c233b4..7bbe1f354f9 100644 --- a/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactoryTests.java +++ b/src/test/java/org/elasticsearch/shield/authc/support/ldap/LdapSslSocketFactoryTests.java @@ -28,8 +28,8 @@ public class LdapSslSocketFactoryTests extends ElasticsearchTestCase { public static void setTrustStore() throws URISyntaxException { File filename = new File(LdapConnectionTests.class.getResource("../support/ldap/ldaptrust.jks").toURI()).getAbsoluteFile(); LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder() - .put("shield.ssl.keystore", filename) - .put("shield.ssl.keystore_password", "changeit") + .put("shield.ssl.keystore.path", filename) + .put("shield.ssl.keystore.password", "changeit") .build())); } diff --git a/src/test/java/org/elasticsearch/shield/plugin/ShieldPluginTests.java b/src/test/java/org/elasticsearch/shield/plugin/ShieldPluginTests.java index f1041f6b3d9..8b10d350c74 100644 --- a/src/test/java/org/elasticsearch/shield/plugin/ShieldPluginTests.java +++ b/src/test/java/org/elasticsearch/shield/plugin/ShieldPluginTests.java @@ -14,7 +14,6 @@ import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.node.internal.InternalNode; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.test.ShieldIntegrationTest; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.rest.client.http.HttpRequestBuilder; import org.elasticsearch.test.rest.client.http.HttpResponse; import org.junit.Test; diff --git a/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java b/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java index 5970495c2ce..7ff37c4b624 100644 --- a/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java +++ b/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java @@ -5,17 +5,18 @@ */ package org.elasticsearch.shield.ssl; +import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.ElasticsearchTestCase; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import javax.net.ssl.SSLEngine; import java.io.File; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; -import static org.hamcrest.Matchers.arrayContaining; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; public class SSLServiceTests extends ElasticsearchTestCase { @@ -30,10 +31,10 @@ public class SSLServiceTests extends ElasticsearchTestCase { public void testThatInvalidProtocolThrowsException() throws Exception { new SSLService(settingsBuilder() .put("shield.ssl.protocol", "non-existing") - .put("shield.ssl.keystore", testnodeStore.getPath()) - .put("shield.ssl.keystore_password", "testnode") - .put("shield.ssl.truststore", testnodeStore.getPath()) - .put("shield.ssl.truststore_password", "testnode") + .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.password", "testnode") + .put("shield.ssl.truststore.path", testnodeStore.getPath()) + .put("shield.ssl.truststore.password", "testnode") .build()); } @@ -41,10 +42,10 @@ public class SSLServiceTests extends ElasticsearchTestCase { public void testSpecificProtocol() { SSLService ssl = new SSLService(settingsBuilder() .put("shield.ssl.protocol", "TLSv1.2") - .put("shield.ssl.keystore", testnodeStore.getPath()) - .put("shield.ssl.keystore_password", "testnode") - .put("shield.ssl.truststore", testnodeStore.getPath()) - .put("shield.ssl.truststore_password", "testnode") + .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.password", "testnode") + .put("shield.ssl.truststore.path", testnodeStore.getPath()) + .put("shield.ssl.truststore.password", "testnode") .build()); assertThat(ssl.createSSLEngine().getSSLParameters().getProtocols(), arrayContaining("TLSv1.2")); } @@ -111,6 +112,23 @@ public class SSLServiceTests extends ElasticsearchTestCase { assertSSLEnabled(settings); } + @Test + public void testThatCustomTruststoreCanBeSpecified() throws Exception { + File testClientStore = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks").toURI()); + + SSLService sslService = new SSLService(settingsBuilder() + .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.password", "testnode") + .build()); + + ImmutableSettings.Builder settingsBuilder = settingsBuilder() + .put("truststore.path", testClientStore.getPath()) + .put("truststore.password", "testclient"); + + SSLEngine sslEngineWithTruststore = sslService.createSSLEngineWithTruststore(settingsBuilder.build()); + assertThat(sslEngineWithTruststore, is(not(nullValue()))); + } + private void assertSSLEnabled(Settings settings) { assertThat(SSLService.isSSLEnabled(settings), is(true)); } diff --git a/src/test/java/org/elasticsearch/shield/test/ShieldIntegrationTest.java b/src/test/java/org/elasticsearch/shield/test/ShieldIntegrationTest.java index d6ba70f7ea5..adf1256a120 100644 --- a/src/test/java/org/elasticsearch/shield/test/ShieldIntegrationTest.java +++ b/src/test/java/org/elasticsearch/shield/test/ShieldIntegrationTest.java @@ -9,6 +9,9 @@ import com.google.common.base.Charsets; import com.google.common.net.InetAddresses; import org.apache.lucene.util.AbstractRandomizedTest; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; +import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; +import org.elasticsearch.client.Client; import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.os.OsUtils; import org.elasticsearch.common.settings.ImmutableSettings; @@ -34,6 +37,7 @@ import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilde import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -158,13 +162,13 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest ImmutableSettings.Builder builder = settingsBuilder() .put("shield.transport.ssl", true) - .put("shield.ssl.keystore", store.getPath()) - .put("shield.ssl.keystore_password", password) + .put("shield.ssl.keystore.path", store.getPath()) + .put("shield.ssl.keystore.password", password) .put("shield.http.ssl", true); if (randomBoolean()) { - builder.put("shield.ssl.truststore", store.getPath()) - .put("shield.ssl.truststore_password", password); + builder.put("shield.ssl.truststore.path", store.getPath()) + .put("shield.ssl.truststore.password", password); } return builder.build(); @@ -179,4 +183,10 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest return null; } } + + protected void assertGreenClusterState(Client client) { + ClusterHealthResponse clusterHealthResponse = client.admin().cluster().prepareHealth().get(); + assertNoTimeout(clusterHealthResponse); + assertThat(clusterHealthResponse.getStatus(), is(ClusterHealthStatus.GREEN)); + } } diff --git a/src/test/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticatorTests.java b/src/test/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticatorTests.java index bb39e0a05aa..16d495fc033 100644 --- a/src/test/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticatorTests.java +++ b/src/test/java/org/elasticsearch/shield/transport/n2n/IPFilteringN2NAuthenticatorTests.java @@ -14,6 +14,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.junit.annotations.Network; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.watcher.ResourceWatcherService; import org.junit.After; @@ -141,6 +142,17 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase { assertAddressIsAllowed("127.0.0.1"); } + @Test + @TestLogging("_root:TRACE") + public void testThatProfilesAreSupported() throws Exception { + writeConfigFile("allow: localhost\ndeny: all\nclient.allow: 192.168.0.1\nclient.deny: all"); + + assertAddressIsAllowed("127.0.0.1"); + assertAddressIsDenied("192.168.0.1"); + assertAddressIsAllowedForProfile("client", "192.168.0.1"); + assertAddressIsDeniedForProfile("client", "192.168.0.2"); + } + @Test(expected = ElasticsearchParseException.class) public void testThatInvalidFileThrowsCorrectException() throws Exception { writeConfigFile("deny: all allow: all \n\n"); @@ -155,17 +167,25 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase { ipFilteringN2NAuthenticator = new IPFilteringN2NAuthenticator(settings, new Environment(), resourceWatcherService); } - private void assertAddressIsAllowed(String ... inetAddresses) { + private void assertAddressIsAllowedForProfile(String profile, String ... inetAddresses) { for (String inetAddress : inetAddresses) { String message = String.format(Locale.ROOT, "Expected address %s to be allowed", inetAddress); - assertThat(message, ipFilteringN2NAuthenticator.authenticate(NULL_PRINCIPAL, InetAddresses.forString(inetAddress), 1024), is(true)); + assertThat(message, ipFilteringN2NAuthenticator.authenticate(NULL_PRINCIPAL, profile, InetAddresses.forString(inetAddress), 1024), is(true)); + } + } + + private void assertAddressIsAllowed(String ... inetAddresses) { + assertAddressIsAllowedForProfile("default", inetAddresses); + } + + private void assertAddressIsDeniedForProfile(String profile, String ... inetAddresses) { + for (String inetAddress : inetAddresses) { + String message = String.format(Locale.ROOT, "Expected address %s to be denied", inetAddress); + assertThat(message, ipFilteringN2NAuthenticator.authenticate(NULL_PRINCIPAL, profile, InetAddresses.forString(inetAddress), 1024), is(false)); } } private void assertAddressIsDenied(String ... inetAddresses) { - for (String inetAddress : inetAddresses) { - String message = String.format(Locale.ROOT, "Expected address %s to be denied", inetAddress); - assertThat(message, ipFilteringN2NAuthenticator.authenticate(NULL_PRINCIPAL, InetAddresses.forString(inetAddress), 1024), is(false)); - } + assertAddressIsDeniedForProfile("default", inetAddresses); } } diff --git a/src/test/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandlerTests.java b/src/test/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandlerTests.java index 831ca27c631..bd679428bd6 100644 --- a/src/test/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandlerTests.java +++ b/src/test/java/org/elasticsearch/shield/transport/netty/N2NNettyUpstreamHandlerTests.java @@ -47,7 +47,7 @@ public class N2NNettyUpstreamHandlerTests extends ElasticsearchTestCase { Settings settings = settingsBuilder().put("shield.transport.n2n.ip_filter.file", configFile.getPath()).build(); IPFilteringN2NAuthenticator ipFilteringN2NAuthenticator = new IPFilteringN2NAuthenticator(settings, new Environment(), resourceWatcherService); - nettyUpstreamHandler = new N2NNettyUpstreamHandler(ipFilteringN2NAuthenticator); + nettyUpstreamHandler = new N2NNettyUpstreamHandler(ipFilteringN2NAuthenticator, "default"); } @After diff --git a/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java b/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java index ceb6c2aee4c..2016ff3e766 100644 --- a/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java +++ b/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java @@ -181,10 +181,4 @@ public class SslIntegrationTests extends ShieldIntegrationTest { String data = Streams.copyToString(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8)); assertThat(data, containsString("You Know, for Search")); } - - private void assertGreenClusterState(Client client) { - ClusterHealthResponse clusterHealthResponse = client.admin().cluster().prepareHealth().get(); - assertNoTimeout(clusterHealthResponse); - assertThat(clusterHealthResponse.getStatus(), is(ClusterHealthStatus.GREEN)); - } } diff --git a/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java b/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java new file mode 100644 index 00000000000..3fe16d0fac7 --- /dev/null +++ b/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java @@ -0,0 +1,116 @@ +/* + * 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.shield.transport.ssl; + +import org.elasticsearch.client.transport.NoNodeAvailableException; +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.InetSocketTransportAddress; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.plugins.PluginsService; +import org.elasticsearch.shield.test.ShieldIntegrationTest; +import org.elasticsearch.shield.transport.netty.NettySecuredTransport; +import org.elasticsearch.transport.Transport; +import org.elasticsearch.transport.TransportModule; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; +import static org.hamcrest.Matchers.is; + +/** + * + */ +public class SslMultiPortTests extends ShieldIntegrationTest { + + private ImmutableSettings.Builder builder; + private static int randomClientPort; + + @BeforeClass + public static void getRandomPort() { + randomClientPort = randomIntBetween(49000, 65500); // ephemeral port + } + + @Before + public void setupBuilder() { + builder = settingsBuilder() + .put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName()) + .put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false) + .put("node.mode", "network") + .put("cluster.name", internalCluster().getClusterName()); + + setUser(builder); + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + String randomClientPortRange = randomClientPort + "-" + (randomClientPort+100); + + File store; + try { + store = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks").toURI()); + assertThat(store.exists(), is(true)); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return settingsBuilder() + .put(super.nodeSettings(nodeOrdinal)) + // settings for default key profile + .put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode")) + // client set up here + .put("transport.profiles.client.port", randomClientPortRange) + .put("transport.profiles.client.bind_host", "localhost") // make sure this is "localhost", no matter if ipv4 or ipv6, but be consistent + .put("transport.profiles.client.shield.truststore.path", store.getAbsolutePath()) // settings for client truststore + .put("transport.profiles.client.shield.truststore.password", "testnode-client-profile") + .put("shield.audit.enabled", false ) + + .build(); + } + + @Test + public void testThatStandardTransportClientCanConnectToDefaultProfile() throws Exception { + builder.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient")); + try (TransportClient transportClient = new TransportClient(builder, false)) { + TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress(); + transportClient.addTransportAddress(transportAddress); + assertGreenClusterState(transportClient); + + } + } + + @Test(expected = NoNodeAvailableException.class) + public void testThatStandardTransportClientCannotConnectToClientProfile() throws Exception { + builder.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient")); + try (TransportClient transportClient = new TransportClient(builder, false)) { + transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", randomClientPort)); + transportClient.admin().cluster().prepareHealth().get(); + } + } + + @Test + public void testThatProfileTransportClientCanConnectToClientProfile() throws Exception { + builder.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks", "testclient-client-profile")); + try (TransportClient transportClient = new TransportClient(builder, false)) { + transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", randomClientPort)); + assertGreenClusterState(transportClient); + } + } + + @Test(expected = NoNodeAvailableException.class) + public void testThatProfileTransportClientCannotConnectToDefaultProfile() throws Exception { + builder.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks", "testclient-client-profile")); + try (TransportClient transportClient = new TransportClient(builder, false)) { + TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress(); + transportClient.addTransportAddress(transportAddress); + transportClient.admin().cluster().prepareHealth().get(); + } + } +} diff --git a/src/test/java/org/elasticsearch/test/ShieldRestTests.java b/src/test/java/org/elasticsearch/test/ShieldRestTests.java index 7a0dc3d88ef..cf4a560562f 100644 --- a/src/test/java/org/elasticsearch/test/ShieldRestTests.java +++ b/src/test/java/org/elasticsearch/test/ShieldRestTests.java @@ -109,10 +109,10 @@ public class ShieldRestTests extends ElasticsearchRestTests { .put("shield.authz.store.files.roles", createFile(folder, "roles.yml", CONFIG_ROLE_ALLOW_ALL)) .put("shield.transport.n2n.ip_filter.file", createFile(folder, "ip_filter.yml", CONFIG_IPFILTER_ALLOW_ALL)) .put("shield.transport.ssl", ENABLE_TRANSPORT_SSL) - .put("shield.ssl.keystore", store.getPath()) - .put("shield.ssl.keystore_password", password) - .put("shield.ssl.truststore", store.getPath()) - .put("shield.ssl.truststore_password", password) + .put("shield.ssl.keystore.path", store.getPath()) + .put("shield.ssl.keystore.password", password) + .put("shield.ssl.truststore.path", store.getPath()) + .put("shield.ssl.truststore.password", password) .put("shield.http.ssl", false) .put("transport.tcp.port", BASE_PORT_RANGE) .putArray("discovery.zen.ping.unicast.hosts", "127.0.0.1:" + BASE_PORT, "127.0.0.1:" + (BASE_PORT + 1), "127.0.0.1:" + (BASE_PORT + 2), "127.0.0.1:" + (BASE_PORT + 3)) @@ -146,10 +146,10 @@ public class ShieldRestTests extends ElasticsearchRestTests { .put("node.mode", "network") .put("shield.transport.n2n.ip_filter.file", createFile(folder, "ip_filter.yml", CONFIG_IPFILTER_ALLOW_ALL)) .put("shield.transport.ssl", ENABLE_TRANSPORT_SSL) - .put("shield.ssl.keystore", store.getPath()) - .put("shield.ssl.keystore_password", password) - .put("shield.ssl.truststore", store.getPath()) - .put("shield.ssl.truststore_password", password) + .put("shield.ssl.keystore.path", store.getPath()) + .put("shield.ssl.keystore.password", password) + .put("shield.ssl.truststore.path", store.getPath()) + .put("shield.ssl.truststore.password", password) .put("cluster.name", internalCluster().getClusterName()) .build(); } diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert new file mode 100644 index 00000000000..25c05c410b8 --- /dev/null +++ b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEWHpBBTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAw +DgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYD +VQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE0MTEwNTEwMzMxMVoXDTE1MDIwMzEw +MzMxMVowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5r +bm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93 +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANMk6NoZl5kbrt9ycsCAms/aivFvmd17 +OTwNPqVvsEa7/uCdaDAiYvUtdjs8LMh7uN5s/6DuimpmbKh/XmT9wljWGpT/zPQQhhontvxefXCr +Gp6z8Bs6z/xrbN8GU+M6D4AFOOnZ8YdlXEmFrCCdp7Nu6eqEUa5ui/1HLrTvey0xN2geZHwfHyPw +ZY9eRlLn2v9lzilzrd3H8AIJ4vBBUx44/CP90ocYUSArLOm8TFvRSOfp/vqz0j6gnGOebN9e4a0B +gAZVQmN8g+SrJsRNGgjGgLj7AjQxh9iThpWIWNeJ2UTeuswvANvxna0zRcr6fejmtaAYO9SST76c +oaZSvS0CAwEAAaMhMB8wHQYDVR0OBBYEFJnOrwiIIEz8XMVIXL8g3QRgtUafMA0GCSqGSIb3DQEB +CwUAA4IBAQCYQW+1efFngQbxDs1jZp+rBAeQ2rQFc4arWx4HOCaRyjlPCwNpjwlN3JM+OtqqR4Z/ +1HMRpPjgdayiTQ3HsVRWzMVm4NCVHx5LmahMCHv+1mru4Ut7BbbupgAlsQ3vtKcgKIdTVhO8vJlP +IYprm388k06/t3CuQJSaCNxElpe3kIldXMeFRKi2TcqOXjb/Nw2L+gZz/+XJLWLOmoAy+2Pq629f +bk1d/lG3pf0QV/X1kcMiHV320iI/CZJWvwuJK73Ukg1RG8CTYt649R1Trqns6bimFyOMMnBlNtD5 +PJiZ0+528XTNbA6Vhz/bXN2g7lDtedy6xJSO1ULFFE9/iUKX +-----END CERTIFICATE----- diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks new file mode 100644 index 00000000000..bcf510bddff Binary files /dev/null and b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks differ diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert new file mode 100644 index 00000000000..30ae6c12519 --- /dev/null +++ b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEHucrFzANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAw +DgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYD +VQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE0MTEwNDE3MTUxNVoXDTE1MDIwMjE3 +MTUxNVowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5r +bm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93 +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKrBa2XNWQUk8+TdwG1ZSiwGfQOKNQko +JoX7Cx977L3RQIEs9Q2JxsSRM3wh4uBZzrZ/NCnxKOtw3bKC6B9dUJLXXwZFc7YTtNfcZr8S2000 +UW6mre/4u54wnkJD/ahuoZ/FCUE7ETB+Jeg3uDhyoUCcySo96OPvZpy/ctXTmkDuai3h+0NvUgpY +yll2LcWBaottW0X6YveCwF78CNDVCSLRjGKqLa3QWFGFMQWdmYrzIaCb1e4U0/8WHM0ylw/vYuvz +u+BDXOsoIPUn4eDdeWtxXA/ZGhjDCfTb0GWSSBfmciMY6yIBpQalt/yRQ/2AL9t+G2fc0th2FzD6 +2UZOexMCAwEAAaMhMB8wHQYDVR0OBBYEFEL891TiYG3R/E5kGjxVY+SwAY5BMA0GCSqGSIb3DQEB +CwUAA4IBAQB372cFMKkLlnH2JbMMtVooXWjF40TJdUOU/ImB+i7rLdVUFX/HmexiL3nDziwOMhTH +N3iEDlxcBeVP+XxZouStwAZP0MmezoGiEjRG53w8gBHSkiWmkKBHYZe1JedeZxEWQCCI0zMh14PY +j5kmgD/sFSvWJCP8UpJnSKTj4ZKAiITmsgSJL/0A5R2Af2lTD5k5sQyvNt1im6atuKdnO96Iqthr +8WRpeyOh5xDZht/KGphZSQyjEpF/RVXWXstkqrKMZRZlKW0EcuBHX4EsTNuzRYC19ReD7d2/CM5M +u9u+iTR1Kws0r3YX4cMnlLXVzJPlAzUrbXmYAMYtpbbYT9QW +-----END CERTIFICATE----- diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks new file mode 100644 index 00000000000..8fabcdafd29 Binary files /dev/null and b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks differ diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks index a18fcbcad16..cd20e580a0f 100644 Binary files a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks and b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks differ