update the IPFilter to always allow traffic from a bound address

This change updates the IPFilter to always allow traffic from the bound addresses of the node
even if they have been explicitly disabled. This behavior can be disabled through a setting but
that could be dangerous if the blocking rule is added via a persistent setting stored in the cluster
state.

Closes elastic/elasticsearch#487

Original commit: elastic/x-pack-elasticsearch@4c1cf9455f
This commit is contained in:
jaymode 2015-09-16 12:44:13 -04:00
parent b219e9c496
commit 6a7462be3e
16 changed files with 241 additions and 85 deletions

View File

@ -12,12 +12,15 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -28,24 +31,34 @@ public class HttpESExporterUtils {
static final String VERSION_FIELD = "number";
public static String[] extractHostsFromAddress(BoundTransportAddress boundAddress, ESLogger logger) {
if (boundAddress == null || boundAddress.boundAddress() == null) {
if (boundAddress == null || boundAddress.boundAddresses() == null) {
logger.debug("local http server is not yet started. can't connect");
return null;
}
if (boundAddress.boundAddress().uniqueAddressTypeId() != 1) {
logger.error("local node is not bound via the http transport. can't connect");
return null;
TransportAddress[] boundAddresses = boundAddress.boundAddresses();
List<String> hosts = new ArrayList<>(boundAddresses.length);
for (TransportAddress transportAddress : boundAddresses) {
if (transportAddress.uniqueAddressTypeId() == 1) {
InetSocketTransportAddress address = (InetSocketTransportAddress) transportAddress;
InetSocketAddress inetSocketAddress = address.address();
InetAddress inetAddress = inetSocketAddress.getAddress();
if (inetAddress == null) {
logger.error("failed to extract the ip address of from transport address [{}]", transportAddress);
continue;
}
hosts.add(NetworkAddress.formatAddress(inetSocketAddress));
} else {
logger.error("local node http transport is not bound via a InetSocketTransportAddress. address is [{}] with typeId [{}]", transportAddress, transportAddress.uniqueAddressTypeId());
}
}
InetSocketTransportAddress address = (InetSocketTransportAddress) boundAddress.boundAddress();
InetSocketAddress inetSocketAddress = address.address();
InetAddress inetAddress = inetSocketAddress.getAddress();
if (inetAddress == null) {
logger.error("failed to extract the ip address of current node.");
if (hosts.isEmpty()) {
logger.error("could not extract any hosts from bound address. can't connect");
return null;
}
return new String[]{ NetworkAddress.formatAddress(inetSocketAddress) };
return hosts.toArray(new String[hosts.size()]);
}
public static URL parseHostWithPath(String host, String path) throws URISyntaxException, MalformedURLException {

View File

@ -15,8 +15,8 @@ import org.elasticsearch.common.component.LifecycleListener;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.util.ArrayUtils;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.settings.NodeSettingsService;
import org.elasticsearch.shield.audit.AuditTrail;
@ -66,6 +66,7 @@ public class IPFilter extends AbstractLifecycleComponent<IPFilter> {
private NodeSettingsService nodeSettingsService;
private final AuditTrail auditTrail;
private final Transport transport;
private final boolean alwaysAllowBoundAddresses;
private Map<String, ShieldIpFilterRule[]> rules = Collections.EMPTY_MAP;
private HttpServerTransport httpServerTransport = null;
@ -75,6 +76,7 @@ public class IPFilter extends AbstractLifecycleComponent<IPFilter> {
this.nodeSettingsService = nodeSettingsService;
this.auditTrail = auditTrail;
this.transport = transport;
this.alwaysAllowBoundAddresses = settings.getAsBoolean("shield.filter.always_allow_bound_address", true);
}
@Override
@ -144,27 +146,30 @@ public class IPFilter extends AbstractLifecycleComponent<IPFilter> {
Map<String, ShieldIpFilterRule[]> profileRules = new HashMap<>();
if (isHttpFilterEnabled && httpServerTransport != null && httpServerTransport.lifecycleState() == Lifecycle.State.STARTED) {
InetAddress localAddress = ((InetSocketTransportAddress) this.httpServerTransport.boundAddress().boundAddress()).address().getAddress();
TransportAddress[] localAddresses = this.httpServerTransport.boundAddress().boundAddresses();
String[] httpAllowed = settings.getAsArray("shield.http.filter.allow", settings.getAsArray("transport.profiles.default.shield.filter.allow", settings.getAsArray("shield.transport.filter.allow")));
String[] httpDdenied = settings.getAsArray("shield.http.filter.deny", settings.getAsArray("transport.profiles.default.shield.filter.deny", settings.getAsArray("shield.transport.filter.deny")));
profileRules.put(HTTP_PROFILE_NAME, ArrayUtils.concat(parseValue(httpAllowed, true, localAddress), parseValue(httpDdenied, false, localAddress), ShieldIpFilterRule.class));
String[] httpDenied = settings.getAsArray("shield.http.filter.deny", settings.getAsArray("transport.profiles.default.shield.filter.deny", settings.getAsArray("shield.transport.filter.deny")));
profileRules.put(HTTP_PROFILE_NAME, createRules(httpAllowed, httpDenied, localAddresses));
}
if (isIpFilterEnabled && this.transport.lifecycleState() == Lifecycle.State.STARTED) {
InetAddress localAddress = ((InetSocketTransportAddress) this.transport.boundAddress().boundAddress()).address().getAddress();
TransportAddress[] localAddresses = this.transport.boundAddress().boundAddresses();
String[] allowed = settings.getAsArray("shield.transport.filter.allow");
String[] denied = settings.getAsArray("shield.transport.filter.deny");
profileRules.put("default", ArrayUtils.concat(parseValue(allowed, true, localAddress), parseValue(denied, false, localAddress), ShieldIpFilterRule.class));
profileRules.put("default", createRules(allowed, denied, localAddresses));
Map<String, Settings> groupedSettings = settings.getGroups("transport.profiles.");
for (Map.Entry<String, Settings> entry : groupedSettings.entrySet()) {
String profile = entry.getKey();
BoundTransportAddress profileBoundTransportAddress = transport.profileBoundAddresses().get(profile);
if (profileBoundTransportAddress == null) {
// this could happen if a user updates the settings dynamically with a new profile
logger.warn("skipping ip filter rules for profile [{}] since the profile is not bound to any addresses", profile);
continue;
}
Settings profileSettings = entry.getValue().getByPrefix("shield.filter.");
profileRules.put(profile, ArrayUtils.concat(
parseValue(profileSettings.getAsArray("allow"), true, localAddress),
parseValue(profileSettings.getAsArray("deny"), false, localAddress),
ShieldIpFilterRule.class));
profileRules.put(profile, createRules(profileSettings.getAsArray("allow"), profileSettings.getAsArray("deny"), profileBoundTransportAddress.boundAddresses()));
}
}
@ -172,32 +177,23 @@ public class IPFilter extends AbstractLifecycleComponent<IPFilter> {
return ImmutableMap.copyOf(profileRules);
}
private ShieldIpFilterRule[] parseValue(String[] values, boolean isAllowRule, InetAddress localAddress) {
private ShieldIpFilterRule[] createRules(String[] allow, String[] deny, TransportAddress[] boundAddresses) {
List<ShieldIpFilterRule> rules = new ArrayList<>();
for (int i = 0; i < values.length; i++) {
// never ever deny on localhost, do not even add this rule
if (!isAllowRule && isLocalAddress(localAddress, values[i])) {
logger.warn("Configuration setting not applied to reject connections on [{}]. local connections are always allowed!", values[i]);
continue;
}
rules.add(new ShieldIpFilterRule(isAllowRule, values[i]));
// if we are always going to allow the bound addresses, then the rule for them should be the first rule in the list
if (alwaysAllowBoundAddresses) {
assert boundAddresses != null && boundAddresses.length > 0;
rules.add(new ShieldIpFilterRule(true, boundAddresses));
}
return rules.toArray(new ShieldIpFilterRule[]{});
}
/**
* Checks if a user provided address is the same address that we are bound to. This is to prevent denying
* connections from the machine we are running on
*
* @param localAddress the InetAddress that this node is bound to. This should come from the transport
* @param address the address that is being evaluated to be blocked
* @return true if the address is not the same as the localAddress
*/
private boolean isLocalAddress(InetAddress localAddress, String address) {
// FIXME add the correct behavior, see https://github.com/elastic/x-plugins/issues/487
return false;
// add all rules to the same list. Allow takes precedence so they must come first!
for (String value : allow) {
rules.add(new ShieldIpFilterRule(true, value));
}
for (String value : deny) {
rules.add(new ShieldIpFilterRule(false, value));
}
return rules.toArray(new ShieldIpFilterRule[rules.size()]);
}
private class ApplySettings implements NodeSettingsService.Listener {

View File

@ -7,12 +7,16 @@ package org.elasticsearch.shield.transport.filter;
import com.google.common.net.InetAddresses;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.jboss.netty.handler.ipfilter.IpFilterRule;
import org.jboss.netty.handler.ipfilter.IpSubnetFilterRule;
import org.jboss.netty.handler.ipfilter.PatternRule;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
/**
* decorator class to have a useful toString() method for an IpFilterRule
@ -38,6 +42,7 @@ public class ShieldIpFilterRule implements IpFilterRule {
};
public static final ShieldIpFilterRule DENY_ALL = new ShieldIpFilterRule(true, "deny_all") {
@Override
public boolean contains(InetAddress inetAddress) {
return true;
@ -62,6 +67,11 @@ public class ShieldIpFilterRule implements IpFilterRule {
this.ruleSpec = ruleSpec;
}
ShieldIpFilterRule(boolean isAllowRule, TransportAddress... addresses) {
this.ruleSpec = getRuleSpec(addresses);
this.ipFilterRule = getRule(isAllowRule, ruleSpec);
}
@Override
public boolean contains(InetAddress inetAddress) {
return ipFilterRule.contains(inetAddress);
@ -90,12 +100,21 @@ public class ShieldIpFilterRule implements IpFilterRule {
return builder.toString();
}
private static IpFilterRule getRule(boolean isAllowRule, String value) {
if ("_all".equals(value)) {
static IpFilterRule getRule(boolean isAllowRule, String value) {
String[] values = value.split(",");
int allRuleIndex = Arrays.binarySearch(values, 0, values.length, "_all");
if (allRuleIndex >= 0) {
// all rule was found. It should be the only rule!
if (values.length != 1) {
throw new IllegalArgumentException("rules that specify _all may not have other values!");
}
return isAllowRule ? ACCEPT_ALL : DENY_ALL;
}
if (value.contains("/")) {
if (values.length != 1) {
throw new IllegalArgumentException("multiple subnet filters cannot be specified in a single rule!");
}
try {
return new IpSubnetFilterRule(isAllowRule, value);
} catch (UnknownHostException e) {
@ -103,9 +122,40 @@ public class ShieldIpFilterRule implements IpFilterRule {
}
}
boolean isInetAddress = InetAddresses.isInetAddress(value);
String prefix = isInetAddress ? "i:" : "n:";
return new PatternRule(isAllowRule, prefix + value);
boolean firstAdded = false;
StringBuilder ruleSpec = new StringBuilder();
for (String singleValue : values) {
if (firstAdded) {
ruleSpec.append(",");
} else {
firstAdded = true;
}
boolean isInetAddress = InetAddresses.isInetAddress(singleValue);
if (isInetAddress) {
ruleSpec.append("i:");
} else {
ruleSpec.append("n:");
}
ruleSpec.append(singleValue);
}
return new PatternRule(isAllowRule, ruleSpec.toString());
}
static String getRuleSpec(TransportAddress... addresses) {
StringBuilder ruleSpec = new StringBuilder();
boolean firstAdded = false;
for (TransportAddress transportAddress : addresses) {
if (firstAdded) {
ruleSpec.append(",");
} else {
firstAdded = true;
}
assert transportAddress instanceof InetSocketTransportAddress;
ruleSpec.append(NetworkAddress.formatAddress(((InetSocketTransportAddress) transportAddress).address().getAddress()));
}
return ruleSpec.toString();
}
}

View File

@ -16,10 +16,7 @@ import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.DummyTransportAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.LocalTransportAddress;
import org.elasticsearch.common.transport.*;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.index.cache.IndexCacheModule;
@ -197,7 +194,7 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase {
when(authService.authenticate(mock(RestRequest.class))).thenThrow(new UnsupportedOperationException(""));
when(authService.authenticate("_action", new LocalHostMockMessage(), user.user())).thenThrow(new UnsupportedOperationException(""));
Transport transport = mock(Transport.class);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(DummyTransportAddress.INSTANCE, DummyTransportAddress.INSTANCE));
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { DummyTransportAddress.INSTANCE }, DummyTransportAddress.INSTANCE));
Environment env = new Environment(settings);
threadPool = new ThreadPool("index audit trail tests");

View File

@ -11,6 +11,7 @@ import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.DummyTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.authc.AuthenticationService;
import org.elasticsearch.test.*;
@ -48,7 +49,7 @@ public class IndexAuditTrailUpdateMappingTests extends ShieldIntegTestCase {
AuthenticationService authService = mock(AuthenticationService.class);
Settings settings = Settings.builder().put("shield.audit.index.rollover", rollover.name().toLowerCase(Locale.ENGLISH)).put("path.home", createTempDir()).build();
Transport transport = mock(Transport.class);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(DummyTransportAddress.INSTANCE, DummyTransportAddress.INSTANCE));
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { DummyTransportAddress.INSTANCE }, DummyTransportAddress.INSTANCE));
Environment env = new Environment(settings);
IndexAuditTrail auditor = new IndexAuditTrail(settings, new IndexAuditUserHolder(), env, authService, transport, Providers.of(client()), threadPool, mock(ClusterService.class));

View File

@ -109,7 +109,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
.put("shield.audit.logfile.prefix.emit_node_name", randomBoolean())
.build();
transport = mock(Transport.class);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(DummyTransportAddress.INSTANCE, DummyTransportAddress.INSTANCE));
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { DummyTransportAddress.INSTANCE }, DummyTransportAddress.INSTANCE));
prefix = LoggingAuditTrail.resolvePrefix(settings, transport);
}

View File

@ -71,7 +71,7 @@ public class AnonymousUserTests extends ShieldIntegTestCase {
}
private String getNodeUrl() {
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddresses());
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
return String.format(Locale.ROOT, "http://%s:%s/", "localhost", inetSocketTransportAddress.address().getPort());

View File

@ -71,7 +71,7 @@ public class PkiAuthenticationTests extends ShieldIntegTestCase {
public void testTransportClientCanAuthenticateViaPki() {
Settings settings = ShieldSettingsSource.getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode");
try (TransportClient client = createTransportClient(settings)) {
client.addTransportAddress(internalCluster().getInstance(Transport.class).boundAddress().boundAddress());
client.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
IndexResponse response = client.prepareIndex("foo", "bar").setSource("pki", "auth").get();
assertThat(response.isCreated(), is(true));
}
@ -84,7 +84,7 @@ public class PkiAuthenticationTests extends ShieldIntegTestCase {
@Test(expected = NoNodeAvailableException.class)
public void testTransportClientAuthenticationFailure() {
try (TransportClient client = createTransportClient(Settings.EMPTY)) {
client.addTransportAddress(internalCluster().getInstance(Transport.class).boundAddress().boundAddress());
client.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
client.prepareIndex("foo", "bar").setSource("pki", "auth").get();
fail("transport client should not have been able to authenticate");
}
@ -144,7 +144,7 @@ public class PkiAuthenticationTests extends ShieldIntegTestCase {
}
private String getNodeUrl() {
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddresses());
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
return String.format(Locale.ROOT, "https://localhost:%s/", inetSocketTransportAddress.address().getPort());

View File

@ -97,7 +97,7 @@ public class PkiOptionalClientAuthTests extends ShieldIntegTestCase {
@Test
public void testTransportClientWithoutClientCertificate() {
Transport transport = internalCluster().getDataNodeInstance(Transport.class);
int port = ((InetSocketTransportAddress)transport.profileBoundAddresses().get("want_client_auth").boundAddress()).address().getPort();
int port = ((InetSocketTransportAddress) randomFrom(transport.profileBoundAddresses().get("want_client_auth").boundAddresses())).address().getPort();
Settings settings = Settings.builder()
.put(ShieldSettingsSource.getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks", "truststore-testnode-only"))

View File

@ -7,9 +7,11 @@ package org.elasticsearch.shield.transport.filter;
import com.google.common.net.InetAddresses;
import org.elasticsearch.common.component.Lifecycle;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.settings.NodeSettingsService;
import org.elasticsearch.shield.audit.AuditTrail;
@ -21,7 +23,7 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.net.InetAddress;
import java.util.Locale;
import java.util.*;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.hamcrest.Matchers.is;
@ -45,13 +47,17 @@ public class IPFilterTests extends ESTestCase {
httpTransport = mock(HttpServerTransport.class);
InetSocketTransportAddress httpAddress = new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), 9200);
when(httpTransport.boundAddress()).thenReturn(new BoundTransportAddress(httpAddress, httpAddress));
when(httpTransport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { httpAddress }, httpAddress));
when(httpTransport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
transport = mock(Transport.class);
InetSocketTransportAddress address = new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), 9300);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(address, address));
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[]{ address }, address));
when(transport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
Map<String, BoundTransportAddress> profileBoundAddresses = Collections.singletonMap("client",
new BoundTransportAddress(new TransportAddress[]{ new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), 9500) }, address));
when(transport.profileBoundAddresses()).thenReturn(profileBoundAddresses);
}
@Test
@ -171,15 +177,25 @@ public class IPFilterTests extends ESTestCase {
}
@Test
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/487")
public void testThatLocalhostIsNeverRejected() throws Exception {
Settings settings = settingsBuilder()
.put("shield.transport.filter.deny", "127.0.0.1")
.build();
public void testThatBoundAddressIsNeverRejected() throws Exception {
List<String> addressStrings = new ArrayList<>();
for (TransportAddress address : transport.boundAddress().boundAddresses()) {
addressStrings.add(NetworkAddress.formatAddress(((InetSocketTransportAddress) address).address().getAddress()));
}
Settings settings;
if (randomBoolean()) {
settings = settingsBuilder().putArray("shield.transport.filter.deny", addressStrings.toArray(new String[addressStrings.size()])).build();
} else {
settings = settingsBuilder().put("shield.transport.filter.deny", "_all").build();
}
ipFilter = new IPFilter(settings, auditTrail, nodeSettingsService, transport).start();
ipFilter.setHttpServerTransport(httpTransport);
assertAddressIsAllowedForProfile(IPFilter.HTTP_PROFILE_NAME, "127.0.0.1");
for (String addressString : addressStrings) {
assertAddressIsAllowedForProfile(IPFilter.HTTP_PROFILE_NAME, addressString);
assertAddressIsAllowedForProfile("default", addressString);
}
}
private void assertAddressIsAllowedForProfile(String profile, String ... inetAddresses) {

View File

@ -52,7 +52,7 @@ public class IpFilteringIntegrationTests extends ShieldIntegTestCase {
@Test
public void testThatIpFilteringIsIntegratedIntoNettyPipelineViaHttp() throws Exception {
TransportAddress transportAddress = internalCluster().getDataNodeInstance(HttpServerTransport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getDataNodeInstance(HttpServerTransport.class).boundAddress().boundAddresses());
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
@ -88,7 +88,7 @@ public class IpFilteringIntegrationTests extends ShieldIntegTestCase {
}
private static int getProfilePort(String profile) {
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).profileBoundAddresses().get(profile).boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).profileBoundAddresses().get(profile).boundAddresses());
assert transportAddress instanceof InetSocketTransportAddress;
return ((InetSocketTransportAddress)transportAddress).address().getPort();
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.Node;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.ShieldIntegTestCase;
import org.junit.BeforeClass;
import org.junit.Test;
import java.net.InetAddress;
@ -24,14 +25,23 @@ import static org.hamcrest.Matchers.is;
@ClusterScope(scope = TEST, numDataNodes = 1)
public class IpFilteringUpdateTests extends ShieldIntegTestCase {
private static int randomClientPort;
private final boolean httpEnabled = randomBoolean();
@BeforeClass
public static void getRandomPort() {
randomClientPort = randomIntBetween(49000, 65500);
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
String randomClientPortRange = randomClientPort + "-" + (randomClientPort+100);
return settingsBuilder()
.put(super.nodeSettings(nodeOrdinal))
.put(Node.HTTP_ENABLED, httpEnabled)
.put("shield.transport.filter.deny", "127.0.0.200")
.put("transport.profiles.client.port", randomClientPortRange)
.build();
}
@ -127,16 +137,16 @@ public class IpFilteringUpdateTests extends ShieldIntegTestCase {
@Test
public void testThatDisablingIpFilterForProfilesWorksAsExpected() throws Exception {
Settings settings = settingsBuilder()
.put("transport.profiles.myprofile.shield.filter.deny", "127.0.0.8")
.put("transport.profiles.client.shield.filter.deny", "127.0.0.8")
.build();
updateSettings(settings);
assertConnectionRejected("myprofile", "127.0.0.8");
assertConnectionRejected("client", "127.0.0.8");
settings = settingsBuilder()
.put("shield.transport.filter.enabled", false)
.build();
updateSettings(settings);
assertConnectionAccepted("myprofile", "127.0.0.8");
assertConnectionAccepted("client", "127.0.0.8");
}

View File

@ -0,0 +1,72 @@
/*
* 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.filter;
import org.elasticsearch.test.ESTestCase;
import org.jboss.netty.handler.ipfilter.IpFilterRule;
import org.jboss.netty.handler.ipfilter.IpSubnetFilterRule;
import org.jboss.netty.handler.ipfilter.PatternRule;
import org.junit.Test;
import static org.elasticsearch.shield.transport.filter.ShieldIpFilterRule.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.sameInstance;
/**
* Unit tests for the {@link ShieldIpFilterRule}
*/
public class ShieldIpFilterRuleTests extends ESTestCase {
@Test
public void testParseAllRules() {
IpFilterRule rule = getRule(true, "_all");
assertThat(rule, sameInstance(ACCEPT_ALL));
rule = getRule(false, "_all");
assertThat(rule, sameInstance(DENY_ALL));
}
@Test
public void testParseAllRuleWithOtherValues() {
String ruleValue = "_all," + randomFrom("name", "127.0.0.1", "127.0.0.0/24");
try {
getRule(randomBoolean(), ruleValue);
fail("an illegal argument exception should have been thrown!");
} catch (IllegalArgumentException e) {
// expected
}
}
@Test
public void testParseIpSubnetFilterRule() throws Exception {
final boolean allow = randomBoolean();
IpFilterRule rule = getRule(allow, "127.0.0.0/24");
assertThat(rule, instanceOf(IpSubnetFilterRule.class));
assertThat(rule.isAllowRule(), equalTo(allow));
IpSubnetFilterRule ipSubnetFilterRule = (IpSubnetFilterRule) rule;
assertThat(ipSubnetFilterRule.contains("127.0.0.1"), equalTo(true));
}
@Test
public void testParseIpSubnetFilterRuleWithOtherValues() throws Exception {
try {
getRule(randomBoolean(), "127.0.0.0/24," + randomFrom("name", "127.0.0.1", "192.0.0.0/24"));
fail("expected an exception to be thrown because only one subnet can be specified at a time");
} catch (IllegalArgumentException e) {
//expected
}
}
@Test
public void testParsePatternRules() {
final boolean allow = randomBoolean();
String ruleSpec = "127.0.0.1,::1,192.168.0.*,name*,specific_name";
IpFilterRule rule = getRule(allow, ruleSpec);
assertThat(rule, instanceOf(PatternRule.class));
assertThat(rule.isAllowRule(), equalTo(allow));
}
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.component.Lifecycle;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.node.settings.NodeSettingsService;
import org.elasticsearch.shield.audit.AuditTrail;
@ -47,7 +48,7 @@ public class IPFilterNettyUpstreamHandlerTests extends ESTestCase {
Transport transport = mock(Transport.class);
InetSocketTransportAddress address = new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), 9300);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(address, address));
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { address }, address));
when(transport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
NodeSettingsService nodeSettingsService = mock(NodeSettingsService.class);
@ -56,7 +57,7 @@ public class IPFilterNettyUpstreamHandlerTests extends ESTestCase {
if (isHttpEnabled) {
HttpServerTransport httpTransport = mock(HttpServerTransport.class);
InetSocketTransportAddress httpAddress = new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), 9200);
when(httpTransport.boundAddress()).thenReturn(new BoundTransportAddress(httpAddress, httpAddress));
when(httpTransport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { httpAddress }, httpAddress));
when(httpTransport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
ipFilter.setHttpServerTransport(httpTransport);
}

View File

@ -65,7 +65,7 @@ public class SslIntegrationTests extends ShieldIntegTestCase {
.putArray("shield.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"})
.build()).build()) {
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses());
transportClient.addTransportAddress(transportAddress);
transportClient.admin().cluster().prepareHealth().get();
@ -82,7 +82,7 @@ public class SslIntegrationTests extends ShieldIntegTestCase {
.putArray("shield.ssl.supported_protocols", new String[]{"SSLv3"})
.build()).build()) {
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses());
transportClient.addTransportAddress(transportAddress);
transportClient.admin().cluster().prepareHealth().get();
@ -121,7 +121,7 @@ public class SslIntegrationTests extends ShieldIntegTestCase {
}
private String getNodeUrl() {
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddresses());
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
return String.format(Locale.ROOT, "https://%s:%s/", "localhost", inetSocketTransportAddress.address().getPort());

View File

@ -186,7 +186,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase {
public void testThatProfileTransportClientCannotConnectToDefaultProfile() throws Exception {
Settings settings = ShieldSettingsSource.getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks", "testclient-client-profile");
try (TransportClient transportClient = createTransportClient(settings)) {
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses());
transportClient.addTransportAddress(transportAddress);
transportClient.admin().cluster().prepareHealth().get();
}
@ -232,7 +232,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase {
.put("cluster.name", internalCluster().getClusterName())
.build();
try (TransportClient transportClient = TransportClient.builder().settings(settings).build()) {
transportClient.addTransportAddress(internalCluster().getInstance(Transport.class).boundAddress().boundAddress());
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
assertGreenClusterState(transportClient);
}
}
@ -326,7 +326,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase {
.put("shield.ssl.truststore.password", "truststore-testnode-only")
.build();
try (TransportClient transportClient = TransportClient.builder().settings(settings).build()) {
transportClient.addTransportAddress(internalCluster().getInstance(Transport.class).boundAddress().boundAddress());
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
assertGreenClusterState(transportClient);
}
}
@ -364,7 +364,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase {
.put("shield.transport.ssl", true)
.build();
try (TransportClient transportClient = TransportClient.builder().settings(settings).build()) {
transportClient.addTransportAddress(internalCluster().getInstance(Transport.class).boundAddress().boundAddress());
transportClient.addTransportAddress(randomFrom(internalCluster().getInstance(Transport.class).boundAddress().boundAddresses()));
assertGreenClusterState(transportClient);
}
}
@ -424,7 +424,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase {
}
private static int getProfilePort(String profile) {
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).profileBoundAddresses().get(profile).boundAddress();
TransportAddress transportAddress = randomFrom(internalCluster().getInstance(Transport.class).profileBoundAddresses().get(profile).boundAddresses());
assert transportAddress instanceof InetSocketTransportAddress;
return ((InetSocketTransportAddress)transportAddress).address().getPort();
}