Testing: Create ShieldIntegrationTest that other test inherit from
This integration test contains all of the configuration needed to run with shield and will be the base for further improvements. Closes elastic/elasticsearch#36 Relates elastic/elasticsearch#31 Original commit: elastic/x-pack-elasticsearch@fe77f4d32b
This commit is contained in:
parent
fcd3a89a3d
commit
d0e377ff76
|
@ -26,29 +26,35 @@ import org.elasticsearch.shield.transport.netty.NettySecuredTransportModule;
|
|||
public class SecurityModule extends AbstractModule implements SpawnModules, PreProcessModule {
|
||||
|
||||
private final Settings settings;
|
||||
private final boolean isClient;
|
||||
private final boolean isShieldEnabled;
|
||||
|
||||
public SecurityModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
this.isClient = settings.getAsBoolean("node.client", false);
|
||||
this.isShieldEnabled = settings.getComponentSettings(SecurityModule.class).getAsBoolean("enabled", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processModule(Module module) {
|
||||
if (module instanceof ActionModule) {
|
||||
if (module instanceof ActionModule && isShieldEnabled && !isClient) {
|
||||
((ActionModule) module).registerFilter(SecurityFilter.Action.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Module> spawnModules() {
|
||||
|
||||
// don't spawn module in client mode
|
||||
if (settings.getAsBoolean("node.client", false)) {
|
||||
// don't spawn modules if shield is explicitly disabled
|
||||
if (!isShieldEnabled) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
// don't spawn modules if shield is explicitly disabled
|
||||
if (!settings.getComponentSettings(SecurityModule.class).getAsBoolean("enabled", true)) {
|
||||
return ImmutableList.of();
|
||||
// spawn needed parts in client mode
|
||||
if (isClient) {
|
||||
return ImmutableList.of(
|
||||
new N2NModule(),
|
||||
new SecuredTransportModule()
|
||||
);
|
||||
}
|
||||
|
||||
return ImmutableList.of(
|
||||
|
@ -58,7 +64,7 @@ public class SecurityModule extends AbstractModule implements SpawnModules, PreP
|
|||
new N2NModule(),
|
||||
new NettySecuredHttpServerTransportModule(),
|
||||
new NettySecuredTransportModule(),
|
||||
new SecuredTransportModule(settings));
|
||||
new SecuredTransportModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.shield.transport;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.SecurityFilter;
|
||||
|
||||
/**
|
||||
|
@ -14,16 +13,8 @@ import org.elasticsearch.shield.SecurityFilter;
|
|||
*/
|
||||
public class SecuredTransportModule extends AbstractModule {
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
public SecuredTransportModule(Settings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
if (!settings.getAsBoolean("node.client", false)) {
|
||||
bind(TransportFilter.class).to(SecurityFilter.Transport.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,10 @@ public class SecuredMessageChannelHandler extends MessageChannelHandler {
|
|||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
if (future.isSuccess()) {
|
||||
logger.debug("SSL / TLS handshake completed for the channel.");
|
||||
logger.debug("SSL / TLS handshake completed for channel", ctx.getName());
|
||||
ctx.sendUpstream(e);
|
||||
} else {
|
||||
logger.error("SSL / TLS handshake failed, closing the channel");
|
||||
logger.error("SSL / TLS handshake failed, closing channel", ctx.getName());
|
||||
future.getChannel().close();
|
||||
throw new ElasticsearchSSLException("SSL / TLS handshake failed, closing the channel", future.getCause());
|
||||
}
|
||||
|
|
|
@ -52,9 +52,6 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase {
|
|||
@Before
|
||||
public void init() throws Exception {
|
||||
configFile = temporaryFolder.newFile();
|
||||
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();
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -66,75 +63,75 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase {
|
|||
public void testThatIpV4AddressesCanBeProcessed() throws Exception {
|
||||
writeConfigFile("allow: 127.0.0.1\ndeny: 10.0.0.0/8");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "10.2.3.4");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
assertAddressIsDenied("10.2.3.4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatIpV6AddressesCanBeProcessed() throws Exception {
|
||||
writeConfigFile("allow: 2001:0db8:1234::/48\ndeny: 1234:0db8:85a3:0000:0000:8a2e:0370:7334");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "2001:0db8:1234:0000:0000:8a2e:0370:7334");
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "1234:0db8:85a3:0000:0000:8a2e:0370:7334");
|
||||
assertAddressIsAllowed("2001:0db8:1234:0000:0000:8a2e:0370:7334");
|
||||
assertAddressIsDenied("1234:0db8:85a3:0000:0000:8a2e:0370:7334");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatHostnamesCanBeProcessed() throws Exception {
|
||||
writeConfigFile("allow: localhost\ndeny: '*.google.com'");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "173.194.70.100");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
assertAddressIsDenied("173.194.70.100");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatFileDeletionResultsInAllowingAll() throws Exception {
|
||||
writeConfigFile("allow: 127.0.0.1");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
|
||||
configFile.delete();
|
||||
assertThat(configFile.exists(), is(false));
|
||||
|
||||
sleep(250);
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied("127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatAnAllowAllAuthenticatorWorks() throws Exception {
|
||||
writeConfigFile("allow: all");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "173.194.70.100");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
assertAddressIsAllowed("173.194.70.100");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCommaSeparatedValuesWork() throws Exception {
|
||||
writeConfigFile("allow: 192.168.23.0/24, localhost\ndeny: all");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "192.168.23.1");
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "10.1.2.3");
|
||||
assertAddressIsAllowed("192.168.23.1");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
assertAddressIsDenied("10.1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatOrderIsImportant() throws Exception {
|
||||
writeConfigFile("deny: localhost\nallow: localhost");
|
||||
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied("127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatOrderIsImportantViceVersa() throws Exception {
|
||||
writeConfigFile("allow: localhost\ndeny: localhost");
|
||||
|
||||
assertAddressIsAllowed(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsAllowed("127.0.0.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatEmptyFileDoesNotLeadIntoLoop() throws Exception {
|
||||
writeConfigFile("# \n\n");
|
||||
|
||||
assertAddressIsDenied(ipFilteringN2NAuthenticator, "127.0.0.1");
|
||||
assertAddressIsDenied("127.0.0.1");
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchParseException.class)
|
||||
|
@ -145,17 +142,20 @@ public class IPFilteringN2NAuthenticatorTests extends ElasticsearchTestCase {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
private void assertAddressIsAllowed(IPFilteringN2NAuthenticator ipFilteringN2NAuthenticator, String ... inetAddresses) {
|
||||
private void assertAddressIsAllowed(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));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAddressIsDenied(IPFilteringN2NAuthenticator ipFilteringN2NAuthenticator, String ... inetAddresses) {
|
||||
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));
|
||||
|
|
|
@ -7,56 +7,48 @@ package org.elasticsearch.shield.n2n;
|
|||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import org.elasticsearch.common.os.OsUtils;
|
||||
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.http.HttpServerTransport;
|
||||
import org.elasticsearch.shield.plugin.SecurityPlugin;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.apache.lucene.util.LuceneTestCase.AwaitsFix;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ElasticsearchIntegrationTest.ClusterScope(scope = ElasticsearchIntegrationTest.Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
||||
@AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch-shield/issues/36")
|
||||
public class IpFilteringIntegrationTests extends ElasticsearchIntegrationTest {
|
||||
// no client nodes, no transport nodes, as they all get rejected on network connections
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0)
|
||||
public class IpFilteringIntegrationTests extends ShieldIntegrationTest {
|
||||
|
||||
private static final String CONFIG_IPFILTER_DENY_ALL = "deny: all\n";
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
ImmutableSettings.Builder builder = settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
.put("node.mode", "network")
|
||||
// todo http tests fail without an explicit IP (needs investigation)
|
||||
.put("network.host", randomBoolean() ? "127.0.0.1" : "::1")
|
||||
.put("plugin.types", SecurityPlugin.class.getName());
|
||||
//.put("shield.n2n.file", configFile.getPath())
|
||||
File folder = newFolder();
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
return builder.build();
|
||||
return settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("shield.n2n.file", writeFile(folder, "ip_filter.yml", CONFIG_IPFILTER_DENY_ALL))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test(expected = SocketException.class)
|
||||
public void testThatIpFilteringIsIntegratedIntoNettyPipelineViaHttp() throws Exception {
|
||||
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
|
||||
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());
|
||||
|
@ -67,17 +59,22 @@ public class IpFilteringIntegrationTests extends ElasticsearchIntegrationTest {
|
|||
logger.info("HTTP connection response code [{}]", connection.getResponseCode());
|
||||
}
|
||||
|
||||
@Ignore("Need to investigate further, why this does not fail")
|
||||
@Test(expected = SocketException.class)
|
||||
public void testThatIpFilteringIsIntegratedIntoNettyPipelineViaTransportClient() throws Exception {
|
||||
InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) internalCluster().getDataNodeInstance(Transport.class).boundAddress().boundAddress();
|
||||
|
||||
// TODO: This works and I do not understand why, telnet breaks...
|
||||
Socket socket = new Socket(transportAddress.address().getAddress(), transportAddress.address().getPort());
|
||||
socket.getOutputStream().write("foo".getBytes(Charsets.UTF_8));
|
||||
socket.getOutputStream().flush();
|
||||
socket.getInputStream().close();
|
||||
try (Socket socket = new Socket()) {
|
||||
logger.info("Connecting to {}", transportAddress.address());
|
||||
socket.connect(transportAddress.address(), 500);
|
||||
|
||||
assertThat(socket.isConnected(), is(true));
|
||||
socket.close();
|
||||
try (OutputStream os = socket.getOutputStream()) {
|
||||
os.write("foo".getBytes(Charsets.UTF_8));
|
||||
os.flush();
|
||||
}
|
||||
try (InputStream is = socket.getInputStream()) {
|
||||
is.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,101 +7,23 @@ package org.elasticsearch.shield.plugin;
|
|||
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
|
||||
import org.elasticsearch.common.os.OsUtils;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.transport.SecuredTransportService;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.transport.TransportModule;
|
||||
import org.junit.Rule;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.apache.lucene.util.LuceneTestCase.AwaitsFix;
|
||||
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.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 2, randomDynamicTemplates = false)
|
||||
@AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch-shield/issues/36")
|
||||
public class ShieldPluginTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpFolder = new TemporaryFolder();
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
File folder = newFolder();
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put("plugin.types", SecurityPlugin.class.getName())
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("shield.audit.enabled", true)
|
||||
.put("shield.authc.esusers.files.users", copyFile(folder, "users"))
|
||||
.put("shield.authc.esusers.files.users_roles", copyFile(folder, "users_roles"))
|
||||
.put("shield.authz.store.files.roles", copyFile(folder, "roles.yml"))
|
||||
.put("shield.n2n.file", copyFile(folder, "ip_filter.yml"))
|
||||
.put(TransportModule.TRANSPORT_SERVICE_TYPE_KEY, SecuredTransportService.class.getName())
|
||||
// for the test internal node clients
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue("test_user", "changeme".toCharArray()));
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue("test_user", "changeme".toCharArray()))
|
||||
.build();
|
||||
}
|
||||
public class ShieldPluginTests extends ShieldIntegrationTest {
|
||||
|
||||
@Test
|
||||
@TestLogging("_root:INFO,plugins.PluginsService:TRACE")
|
||||
public void testThatPluginIsLoaded() {
|
||||
logger.info("--> Getting nodes info");
|
||||
NodesInfoResponse nodeInfos = internalCluster().transportClient().admin().cluster().prepareNodesInfo().get();
|
||||
logger.info("--> Checking nodes info");
|
||||
logger.info("--> Checking nodes info that shield plugin is loaded");
|
||||
for (NodeInfo nodeInfo : nodeInfos.getNodes()) {
|
||||
assertThat(nodeInfo.getPlugins().getInfos(), hasSize(1));
|
||||
assertThat(nodeInfo.getPlugins().getInfos().get(0).getName(), is(SecurityPlugin.NAME));
|
||||
}
|
||||
}
|
||||
|
||||
private File newFolder() {
|
||||
try {
|
||||
return tmpFolder.newFolder();
|
||||
} catch (IOException ioe) {
|
||||
logger.error("could not create temporary folder", ioe);
|
||||
fail("could not create temporary folder");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String copyFile(File folder, String name) {
|
||||
Path file = folder.toPath().resolve(name);
|
||||
try {
|
||||
Files.copy(getClass().getResourceAsStream(name), file);
|
||||
} catch (IOException ioe) {
|
||||
logger.error("could not copy temporary configuration file [" + name + "]", ioe);
|
||||
fail("could not copy temporary configuration file [" + name + "]");
|
||||
}
|
||||
return file.toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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.test;
|
||||
|
||||
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.common.os.OsUtils;
|
||||
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.plugin.SecurityPlugin;
|
||||
import org.elasticsearch.shield.transport.netty.NettySecuredTransport;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.transport.TransportModule;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
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.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
|
||||
@Ignore
|
||||
@AbstractRandomizedTest.Integration
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0)
|
||||
public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest {
|
||||
|
||||
private static final String DEFAULT_USER_NAME = "test_user";
|
||||
private static final String DEFAULT_PASSWORD = "changeme";
|
||||
private static final String DEFAULT_ROLE = "user";
|
||||
|
||||
public static final String CONFIG_IPFILTER_ALLOW_ALL = "allow: all\n";
|
||||
public static final String CONFIG_STANDARD_USER = DEFAULT_USER_NAME + ":{plain}" + DEFAULT_PASSWORD + "\n";
|
||||
public static final String CONFIG_STANDARD_USER_ROLES = DEFAULT_USER_NAME + ":" + DEFAULT_ROLE + "\n";
|
||||
public static final String CONFIG_ROLE_ALLOW_ALL = "user:\n" +
|
||||
" cluster: ALL\n" +
|
||||
" indices:\n" +
|
||||
" '.*': ALL\n";
|
||||
|
||||
@ClassRule
|
||||
public static TemporaryFolder tmpFolder = new TemporaryFolder();
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
File folder = newFolder();
|
||||
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.builder()
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword().toCharArray()))
|
||||
.put("discovery.zen.ping.multicast.enabled", false)
|
||||
.put("discovery.type", "zen")
|
||||
.put("node.mode", "network")
|
||||
.put("plugin.types", SecurityPlugin.class.getName())
|
||||
.put("shield.authc.esusers.files.users", writeFile(folder, "users", CONFIG_STANDARD_USER))
|
||||
.put("shield.authc.esusers.files.users_roles", writeFile(folder, "users_roles", CONFIG_STANDARD_USER_ROLES))
|
||||
.put("shield.authz.store.files.roles", writeFile(folder, "roles.yml", CONFIG_ROLE_ALLOW_ALL))
|
||||
.put("shield.n2n.file", writeFile(folder, "ip_filter.yml", CONFIG_IPFILTER_ALLOW_ALL))
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode"))
|
||||
.put("shield.audit.enabled", true);
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword().toCharArray()))
|
||||
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName())
|
||||
.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false)
|
||||
.put("node.mode", "network")
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
.putArray("discovery.zen.ping.unicast.hosts", getUnicastHostAddress())
|
||||
.put(getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks", "testclient"))
|
||||
.build();
|
||||
}
|
||||
|
||||
protected String writeFile(File folder, String name, String content) {
|
||||
Path file = folder.toPath().resolve(name);
|
||||
try {
|
||||
com.google.common.io.Files.write(content.getBytes(Charsets.UTF_8), file.toFile());
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("Error writing file in test", e);
|
||||
}
|
||||
return file.toFile().getAbsolutePath();
|
||||
}
|
||||
|
||||
protected String getUnicastHostAddress() {
|
||||
TransportAddress transportAddress = internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress();
|
||||
assertThat(transportAddress, instanceOf(InetSocketTransportAddress.class));
|
||||
InetSocketTransportAddress address = (InetSocketTransportAddress) transportAddress;
|
||||
return InetAddresses.toAddrString(address.address().getAddress()) + ":" + address.address().getPort();
|
||||
}
|
||||
|
||||
protected String getClientUsername() {
|
||||
return DEFAULT_USER_NAME;
|
||||
};
|
||||
|
||||
protected String getClientPassword() {
|
||||
return DEFAULT_PASSWORD;
|
||||
}
|
||||
|
||||
protected Settings getSSLSettingsForStore(String resourcePathToStore, String password) {
|
||||
File store;
|
||||
try {
|
||||
store = new File(getClass().getResource(resourcePathToStore).toURI());
|
||||
assertThat(store.exists(), is(true));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ImmutableSettings.Builder builder = settingsBuilder()
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.transport.ssl.keystore", store.getPath())
|
||||
.put("shield.transport.ssl.keystore_password", password)
|
||||
.put("shield.transport.ssl.truststore", store.getPath())
|
||||
.put("shield.transport.ssl.truststore_password", password)
|
||||
.put("shield.http.ssl", true)
|
||||
.put("shield.http.ssl.require.client.auth", false)
|
||||
.put("shield.http.ssl.keystore", store.getPath())
|
||||
.put("shield.http.ssl.keystore_password", password)
|
||||
.put("shield.http.ssl.truststore", store.getPath())
|
||||
.put("shield.http.ssl.truststore_password", password);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected File newFolder() {
|
||||
try {
|
||||
return tmpFolder.newFolder();
|
||||
} catch (IOException ioe) {
|
||||
logger.error("could not create temporary folder", ioe);
|
||||
fail("could not create temporary folder");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String copyFile(File folder, String name) {
|
||||
Path file = folder.toPath().resolve(name);
|
||||
try {
|
||||
Files.copy(getClass().getResourceAsStream(name), file);
|
||||
} catch (IOException ioe) {
|
||||
logger.error("could not copy temporary configuration file [" + name + "]", ioe);
|
||||
fail("could not copy temporary configuration file [" + name + "]");
|
||||
}
|
||||
return file.toAbsolutePath().toString();
|
||||
}
|
||||
}
|
|
@ -5,117 +5,76 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.transport.ssl;
|
||||
|
||||
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.transport.NoNodeAvailableException;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.os.OsUtils;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.net.InetAddresses;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.http.HttpServerTransport;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.NodeBuilder;
|
||||
import org.elasticsearch.shield.plugin.SecurityPlugin;
|
||||
import org.elasticsearch.plugins.PluginsService;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.elasticsearch.shield.transport.netty.NettySecuredTransport;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.transport.Transport;
|
||||
import org.elasticsearch.transport.TransportModule;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.apache.lucene.util.LuceneTestCase.AwaitsFix;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
||||
@AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch-shield/issues/36")
|
||||
public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
@ClassRule
|
||||
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private static File ipFilterFile;
|
||||
|
||||
@BeforeClass
|
||||
public static void writeAllowAllIpFilterFile() throws Exception {
|
||||
ipFilterFile = temporaryFolder.newFile();
|
||||
Files.write("allow: all\n".getBytes(com.google.common.base.Charsets.UTF_8), ipFilterFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
File testnodeStore;
|
||||
try {
|
||||
testnodeStore = new File(getClass().getResource("certs/simple/testnode.jks").toURI());
|
||||
assertThat(testnodeStore.exists(), is(true));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
//
|
||||
.put("shield.authz.file.roles", "not/existing")
|
||||
// needed to ensure that netty transport is started
|
||||
.put("node.mode", "network")
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.transport.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.transport.ssl.keystore_password", "testnode")
|
||||
.put("shield.transport.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.transport.ssl.truststore_password", "testnode")
|
||||
.put("shield.http.ssl", true)
|
||||
.put("shield.http.ssl.require.client.auth", false)
|
||||
.put("shield.http.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.http.ssl.keystore_password", "testnode")
|
||||
.put("shield.http.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.http.ssl.truststore_password", "testnode")
|
||||
// SSL SETUP
|
||||
.put("plugin.types", SecurityPlugin.class.getName())
|
||||
.put("shield.n2n.file", ipFilterFile.getPath());
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
public class SslIntegrationTests extends ShieldIntegrationTest {
|
||||
|
||||
@Test
|
||||
@TestLogging("_root:INFO,org.elasticsearch.test:TRACE, org.elasticsearch.client.transport:DEBUG,org.elasticsearch.shield:TRACE")
|
||||
public void testThatTransportClientCanConnectToNodeViaSsl() throws Exception {
|
||||
TransportClient transportClient = new TransportClient(getSettings("transport_client").build(), false);
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
transportClient.addTransportAddress(transportAddress);
|
||||
|
||||
public void testThatInternallyCreatedTransportClientCanConnect() throws Exception {
|
||||
Client transportClient = internalCluster().transportClient();
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchSSLException.class)
|
||||
@TestLogging("_root:INFO,org.elasticsearch.client.transport:DEBUG")
|
||||
public void testThatUnconfiguredCipchersAreRejected() {
|
||||
// some randomly taken ciphers from SSLContext.getDefault().getSocketFactory().getSupportedCipherSuites()
|
||||
// could be really randomized
|
||||
Settings customSettings = getSettings("transport_client").put("shield.transport.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}).build();
|
||||
@Test
|
||||
public void testThatProgrammaticallyCreatedTransportClientCanConnect() throws Exception {
|
||||
Settings settings = settingsBuilder()
|
||||
.put(transportClientSettings())
|
||||
.put("name", "programmatic_transport_client_")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
|
||||
TransportClient transportClient = new TransportClient(customSettings);
|
||||
try (TransportClient transportClient = new TransportClient(settings, false)) {
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
transportClient.addTransportAddress(transportAddress);
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
|
||||
try (TransportClient transportClient = new TransportClient(settings, true)) {
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
transportClient.addTransportAddress(transportAddress);
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
}
|
||||
|
||||
// no SSL exception as this is the exception is returned when connecting
|
||||
@Test(expected = NoNodeAvailableException.class)
|
||||
public void testThatUnconfiguredCipchersAreRejected() {
|
||||
TransportClient transportClient = new TransportClient(settingsBuilder()
|
||||
.put(transportClientSettings())
|
||||
.put("name", "programmatic_transport_client")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.putArray("shield.transport.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"})
|
||||
.build());
|
||||
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
transportClient.addTransportAddress(transportAddress);
|
||||
|
@ -124,9 +83,19 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@TestLogging("_root:DEBUG")
|
||||
public void testConnectNodeWorks() throws Exception {
|
||||
try (Node node = NodeBuilder.nodeBuilder().settings(getSettings("ssl_node")).node().start()) {
|
||||
Settings settings = settingsBuilder()
|
||||
.put("name", "programmatic_node")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword().toCharArray()))
|
||||
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName())
|
||||
.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false)
|
||||
|
||||
.put(getSSLSettingsForStore("certs/simple/testclient.jks", "testclient"))
|
||||
.build();
|
||||
|
||||
try (Node node = NodeBuilder.nodeBuilder().settings(settings).node()) {
|
||||
try (Client client = node.client()) {
|
||||
assertGreenClusterState(client);
|
||||
}
|
||||
|
@ -135,34 +104,30 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
|||
|
||||
@Test
|
||||
public void testConnectNodeClientWorks() throws Exception {
|
||||
// no multicast, good old discovery
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
|
||||
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
|
||||
Settings.Builder settingsBuilder = getSettings("node_client")
|
||||
.put("node.client", true)
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
.put("discovery.zen.ping.unicast.hosts", inetSocketTransportAddress.address().getHostString() + ":" + inetSocketTransportAddress.address().getPort());
|
||||
Settings settings = settingsBuilder()
|
||||
.put("name", "programmatic_node_client")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.put("node.mode", "network")
|
||||
|
||||
try (Node node = NodeBuilder.nodeBuilder().settings(settingsBuilder).node().start()) {
|
||||
.put("discovery.zen.ping.multicast.enabled", false)
|
||||
.put("discovery.type", "zen")
|
||||
.putArray("discovery.zen.ping.unicast.hosts", getUnicastHostAddress())
|
||||
|
||||
.put("request.headers.Authorization", basicAuthHeaderValue(getClientUsername(), getClientPassword().toCharArray()))
|
||||
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName())
|
||||
.put("plugins." + PluginsService.LOAD_PLUGIN_FROM_CLASSPATH, false)
|
||||
.put("shield.n2n.file", writeFile(newFolder(), "ip_filter.yml", ShieldIntegrationTest.CONFIG_IPFILTER_ALLOW_ALL))
|
||||
|
||||
.put(getSSLSettingsForStore("certs/simple/testclient.jks", "testclient"))
|
||||
.build();
|
||||
|
||||
try (Node node = NodeBuilder.nodeBuilder().settings(settings).client(true).node()) {
|
||||
try (Client client = node.client()) {
|
||||
assertGreenClusterState(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchSSLException.class)
|
||||
public void testConnectNodeFailsWithWrongCipher() throws Exception {
|
||||
Settings customSettings = getSettings("ssl_node").put("shield.transport.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}).build();
|
||||
NodeBuilder.nodeBuilder().settings(customSettings).node().start();
|
||||
}
|
||||
|
||||
@Test(expected = ElasticsearchSSLException.class)
|
||||
public void testConnectNodeClientFailsWithWrongCipher() throws Exception {
|
||||
Settings customSettings = getSettings("ssl_node").put("node.client", true).put("shield.transport.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"}).build();
|
||||
NodeBuilder.nodeBuilder().settings(customSettings).node().start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatConnectionToHTTPWorks() throws Exception {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
|
@ -206,36 +171,9 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
|||
assertThat(data, containsString("You Know, for Search"));
|
||||
}
|
||||
|
||||
private ImmutableSettings.Builder getSettings(String name) {
|
||||
File testClientKeyStore;
|
||||
File testClientTrustStore;
|
||||
try {
|
||||
testClientKeyStore = new File(getClass().getResource("certs/simple/testclient.jks").toURI());
|
||||
testClientTrustStore = new File(getClass().getResource("certs/simple/testclient.jks").toURI());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertThat(testClientKeyStore.exists(), is(true));
|
||||
assertThat(testClientTrustStore.exists(), is(true));
|
||||
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
.put("node.name", name)
|
||||
.put("plugins.load_classpath_plugins", false)
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.transport.ssl.keystore", testClientKeyStore.getPath())
|
||||
.put("shield.transport.ssl.keystore_password", "testclient")
|
||||
.put("shield.transport.ssl.truststore", testClientTrustStore .getPath())
|
||||
.put("shield.transport.ssl.truststore_password", "testclient")
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySecuredTransport.class.getName())
|
||||
.put("shield.n2n.file", ipFilterFile.getPath())
|
||||
.put("cluster.name", internalCluster().getClusterName());
|
||||
}
|
||||
|
||||
private void assertGreenClusterState(Client client) {
|
||||
ClusterHealthResponse clusterHealthResponse = client.admin().cluster().prepareHealth().get();
|
||||
assertNoTimeout(clusterHealthResponse);
|
||||
assertThat(clusterHealthResponse.getStatus(), is(ClusterHealthStatus.GREEN));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,22 +6,15 @@
|
|||
package org.elasticsearch.shield.transport.ssl;
|
||||
|
||||
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.net.InetAddresses;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.os.OsUtils;
|
||||
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.http.HttpServerTransport;
|
||||
import org.elasticsearch.shield.plugin.SecurityPlugin;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
|
@ -33,15 +26,16 @@ import java.security.KeyStore;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.apache.lucene.util.LuceneTestCase.AwaitsFix;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ElasticsearchIntegrationTest.ClusterScope(scope = ElasticsearchIntegrationTest.Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
||||
@AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch-shield/issues/36")
|
||||
public class SslRequireAuthTests extends ElasticsearchIntegrationTest {
|
||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0)
|
||||
public class SslRequireAuthTests extends ShieldIntegrationTest {
|
||||
|
||||
public static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() {
|
||||
@Override
|
||||
|
@ -50,54 +44,22 @@ public class SslRequireAuthTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
};
|
||||
|
||||
@ClassRule
|
||||
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private static File ipFilterFile;
|
||||
|
||||
@BeforeClass
|
||||
public static void writeAllowAllIpFilterFile() throws Exception {
|
||||
ipFilterFile = temporaryFolder.newFile();
|
||||
Files.write("allow: all\n".getBytes(com.google.common.base.Charsets.UTF_8), ipFilterFile);
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(getSSLSettingsForStore("certs/simple/testnode.jks", "testnode"))
|
||||
.put("shield.transport.ssl.require.client.auth", true)
|
||||
.put("shield.http.ssl.require.client.auth", true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
File testnodeStore;
|
||||
try {
|
||||
testnodeStore = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI());
|
||||
assertThat(testnodeStore.exists(), is(true));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ImmutableSettings.Builder builder = ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||
// prevents exception until parsing has been fixed in PR
|
||||
.put("shield.authz.file.roles", "not/existing")
|
||||
// needed to ensure that netty transport is started
|
||||
.put("node.mode", "network")
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.transport.ssl.require.client.auth", true)
|
||||
.put("shield.transport.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.transport.ssl.keystore_password", "testnode")
|
||||
.put("shield.transport.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.transport.ssl.truststore_password", "testnode")
|
||||
.put("shield.http.ssl", true)
|
||||
.put("shield.http.ssl.require.client.auth", true)
|
||||
.put("shield.http.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.http.ssl.keystore_password", "testnode")
|
||||
.put("shield.http.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.http.ssl.truststore_password", "testnode")
|
||||
.put("plugin.types", SecurityPlugin.class.getName())
|
||||
.put("shield.n2n.file", ipFilterFile.getPath());
|
||||
|
||||
if (OsUtils.MAC) {
|
||||
builder.put("network.host", randomBoolean() ? "127.0.0.1" : "::1");
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
protected Settings transportClientSettings() {
|
||||
return ImmutableSettings.builder()
|
||||
.put(super.transportClientSettings())
|
||||
.put(getSSLSettingsForStore("certs/simple/testclient.jks", "testclient"))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,7 +93,6 @@ public class SslRequireAuthTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@TestLogging("_root:DEBUG")
|
||||
public void testThatConnectionToHTTPWorks() throws Exception {
|
||||
File store = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI());
|
||||
|
||||
|
|
Loading…
Reference in New Issue