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@51f16d75ba
This commit is contained in:
parent
c17c140cd2
commit
25d2480e78
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
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()) {
|
||||
|
|
Loading…
Reference in New Issue