From 25d2480e78b3e4e4e2b1f8e23736b5c8e2508369 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Fri, 29 Aug 2014 08:59:05 +0200 Subject: [PATCH] Ip filtering: Check correct path for default file Also added logging, so that on start up a message is logged, if all connections are rejected or the config file is not found. Closes elastic/elasticsearch#48 Original commit: elastic/x-pack-elasticsearch@51f16d75baef22602443741cee652f7f4fb2c1fe --- .../n2n/IPFilteringN2NAuthenticator.java | 26 ++++++++----- .../n2n/IPFilteringN2NAuthenticatorTests.java | 5 ++- .../n2n/IpFilteringIntegrationTests.java | 37 ++++++++++--------- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticator.java b/src/main/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticator.java index 1a6c3db477a..1508cc736e1 100644 --- a/src/main/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticator.java +++ b/src/main/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticator.java @@ -5,13 +5,13 @@ */ package org.elasticsearch.shield.n2n; -import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.jackson.dataformat.yaml.snakeyaml.error.YAMLException; +import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.net.InetAddresses; import org.elasticsearch.common.netty.handler.ipfilter.IpFilterRule; import org.elasticsearch.common.netty.handler.ipfilter.IpSubnetFilterRule; @@ -20,6 +20,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.yaml.YamlXContent; import org.elasticsearch.env.Environment; +import org.elasticsearch.shield.plugin.SecurityPlugin; import org.elasticsearch.watcher.FileChangesListener; import org.elasticsearch.watcher.FileWatcher; import org.elasticsearch.watcher.ResourceWatcherService; @@ -51,7 +52,7 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 public IPFilteringN2NAuthenticator(Settings settings, Environment env, ResourceWatcherService watcherService) { super(settings); file = resolveFile(componentSettings, env); - rules = parseFile(file); + rules = parseFile(file, logger); watcher = new FileWatcher(file.getParent().toFile()); watcher.addListener(new FileListener()); watcherService.add(watcher); @@ -60,13 +61,15 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 private Path resolveFile(Settings settings, Environment env) { String location = settings.get("file"); if (location == null) { - return env.configFile().toPath().resolve(DEFAULT_FILE); + File shieldDirectory = new File(env.configFile(), SecurityPlugin.NAME); + return shieldDirectory.toPath().resolve(DEFAULT_FILE); } return Paths.get(location); } - public static IpFilterRule[] parseFile(Path path) { + public static IpFilterRule[] parseFile(Path path, ESLogger logger) { if (!Files.exists(path)) { + logger.info("No IP filtering rules loaded, as file {} does not exist. Rejecting all incoming connections!", path); return NO_RULES; } @@ -109,8 +112,11 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 } if (rules.size() == 0) { + logger.info("No IP filtering rules loaded. Rejecting all incoming connections!"); return NO_RULES; } + + logger.debug("Loaded {} ip filtering rules", rules.size()); return rules.toArray(new IpFilterRule[rules.size()]); } @@ -130,9 +136,13 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 public boolean authenticate(@Nullable Principal peerPrincipal, InetAddress peerAddress, int peerPort) { for (int i = 0; i < rules.length; i++) { if (rules[i].contains(peerAddress)) { - return rules[i].isAllowRule(); + boolean isAllowed = rules[i].isAllowRule(); + logger.trace("Authentication rule matched for host [{}]: {}", peerAddress, isAllowed); + return isAllowed; } } + + logger.trace("Rejecting host {}", peerAddress); return false; } @@ -140,7 +150,7 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 @Override public void onFileCreated(File file) { if (file.equals(IPFilteringN2NAuthenticator.this.file.toFile())) { - rules = parseFile(file.toPath()); + rules = parseFile(file.toPath(), logger); } } @@ -154,9 +164,7 @@ public class IPFilteringN2NAuthenticator extends AbstractComponent implements N2 @Override public void onFileChanged(File file) { if (file.equals(IPFilteringN2NAuthenticator.this.file.toFile())) { - if (file.equals(IPFilteringN2NAuthenticator.this.file.toFile())) { - rules = parseFile(file.toPath()); - } + rules = parseFile(file.toPath(), logger); } } } diff --git a/src/test/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticatorTests.java b/src/test/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticatorTests.java index 528ef0a7602..25c692ae9b4 100644 --- a/src/test/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticatorTests.java +++ b/src/test/java/org/elasticsearch/shield/n2n/IPFilteringN2NAuthenticatorTests.java @@ -44,6 +44,8 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private final Settings resourceWatcherServiceSettings = settingsBuilder().put("watcher.interval.medium", TimeValue.timeValueMillis(200)).build(); + private ResourceWatcherService resourceWatcherService; private File configFile; private Settings settings; @@ -137,12 +139,11 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase { @Test(expected = ElasticsearchParseException.class) public void testThatInvalidFileThrowsCorrectException() throws Exception { writeConfigFile("deny: all allow: all \n\n"); - IPFilteringN2NAuthenticator.parseFile(configFile.toPath()); + IPFilteringN2NAuthenticator.parseFile(configFile.toPath(), logger); } private void writeConfigFile(String data) throws IOException { Files.write(data.getBytes(Charsets.UTF_8), configFile); - Settings resourceWatcherServiceSettings = settingsBuilder().put("watcher.interval.medium", TimeValue.timeValueMillis(200)).build(); resourceWatcherService = new ResourceWatcherService(resourceWatcherServiceSettings, new ThreadPool("resourceWatcher")).start(); settings = settingsBuilder().put("shield.n2n.file", configFile.getPath()).build(); ipFilteringN2NAuthenticator = new IPFilteringN2NAuthenticator(settings, new Environment(), resourceWatcherService); diff --git a/src/test/java/org/elasticsearch/shield/n2n/IpFilteringIntegrationTests.java b/src/test/java/org/elasticsearch/shield/n2n/IpFilteringIntegrationTests.java index 791af06a0b9..d97e4d764a4 100644 --- a/src/test/java/org/elasticsearch/shield/n2n/IpFilteringIntegrationTests.java +++ b/src/test/java/org/elasticsearch/shield/n2n/IpFilteringIntegrationTests.java @@ -6,7 +6,7 @@ package org.elasticsearch.shield.n2n; import com.google.common.base.Charsets; -import com.google.common.net.InetAddresses; +import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.TransportAddress; @@ -18,11 +18,9 @@ import org.junit.Test; import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.net.HttpURLConnection; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; -import java.net.URL; -import java.util.Locale; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; @@ -38,12 +36,16 @@ public class IpFilteringIntegrationTests extends ShieldIntegrationTest { @Override protected Settings nodeSettings(int nodeOrdinal) { - File folder = newFolder(); + ImmutableSettings.Builder builder = settingsBuilder().put(super.nodeSettings(nodeOrdinal)); + // either deny all or do not have a configuration file, as this denies by default + if (getRandom().nextBoolean()) { + File folder = newFolder(); + builder.put("shield.n2n.file", writeFile(folder, "ip_filter.yml", CONFIG_IPFILTER_DENY_ALL)); + } else { + builder.remove("shield.n2n.file"); + } - return settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) - .put("shield.n2n.file", writeFile(folder, "ip_filter.yml", CONFIG_IPFILTER_DENY_ALL)) - .build(); + return builder.build(); } @Test(expected = SocketException.class) @@ -51,21 +53,22 @@ public class IpFilteringIntegrationTests extends ShieldIntegrationTest { TransportAddress transportAddress = internalCluster().getDataNodeInstance(HttpServerTransport.class).boundAddress().boundAddress(); assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class))); InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress; - String url = String.format(Locale.ROOT, "http://%s:%s/", InetAddresses.toUriString(inetSocketTransportAddress.address().getAddress()), inetSocketTransportAddress.address().getPort()); - logger.info("Opening connection to {}", url); - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); - connection.connect(); - logger.info("HTTP connection response code [{}]", connection.getResponseCode()); + trySocketConnection(inetSocketTransportAddress.address()); } @Test(expected = SocketException.class) public void testThatIpFilteringIsIntegratedIntoNettyPipelineViaTransportClient() throws Exception { - InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) internalCluster().getDataNodeInstance(Transport.class).boundAddress().boundAddress(); + TransportAddress transportAddress = (InetSocketTransportAddress) internalCluster().getDataNodeInstance(Transport.class).boundAddress().boundAddress(); + assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class))); + InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress; + trySocketConnection(inetSocketTransportAddress.address()); + } + private void trySocketConnection(InetSocketAddress address) throws Exception { try (Socket socket = new Socket()) { - logger.info("Connecting to {}", transportAddress.address()); - socket.connect(transportAddress.address(), 500); + logger.info("Connecting to {}", address); + socket.connect(address, 500); assertThat(socket.isConnected(), is(true)); try (OutputStream os = socket.getOutputStream()) {