LICESE_EXPIRATION_ACTION_MATCHER = Privilege.HEALTH_AND_STATS.predicate();
private final AuthenticationService authcService;
private final AuthorizationService authzService;
@@ -57,14 +56,14 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte
this.signatureService = signatureService;
this.auditTrail = auditTrail;
this.actionMapper = actionMapper;
- licenseEventsNotifier.register(new LicensesClientService.Listener() {
+ licenseEventsNotifier.register(new LicenseEventsNotifier.Listener() {
@Override
- public void onEnabled() {
+ public void enabled() {
licenseEnabled = true;
}
@Override
- public void onDisabled() {
+ public void disabled() {
licenseEnabled = false;
}
});
@@ -77,8 +76,10 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte
A functional requirement - when the license of shield is disabled (invalid/expires), shield will continue
to operate normally, except all read operations will be blocked.
*/
- if (!licenseEnabled && READ_ACTION_MATCHER.apply(action)) {
- logger.error("blocking read operation [{}] due to disabled license", action);
+ if (!licenseEnabled && LICESE_EXPIRATION_ACTION_MATCHER.apply(action)) {
+ logger.error("blocking [{}] operation due to expired license. Cluster health, cluster stats and indices stats \n" +
+ "operations are blocked on shield license expiration. All data operations (read and write) continue to work. \n" +
+ "If you have a new license, please update it. Otherwise, please reach out to your support contact.", action);
throw new LicenseExpiredException(LicenseService.FEATURE_NAME);
}
diff --git a/src/main/java/org/elasticsearch/shield/authz/Privilege.java b/src/main/java/org/elasticsearch/shield/authz/Privilege.java
index 5fac995903b..e221ff6573b 100644
--- a/src/main/java/org/elasticsearch/shield/authz/Privilege.java
+++ b/src/main/java/org/elasticsearch/shield/authz/Privilege.java
@@ -40,6 +40,7 @@ public abstract class Privilege> {
static final String SUB_ACTION_SUFFIX_PATTERN = "*";
public static final System SYSTEM = new System();
+ public static final General HEALTH_AND_STATS = new General("health_and_stats", "cluster:monitor/health*", "cluster:monitor/stats*", "indices:monitor/stats*");
protected final Name name;
@@ -106,6 +107,34 @@ public abstract class Privilege
> {
}
}
+ public static class General extends AutomatonPrivilege {
+
+ private static final General NONE = new General(Name.NONE, Automata.makeEmpty());
+
+ public General(String name, String... patterns) {
+ super(name, patterns);
+ }
+
+ public General(Name name, String... patterns) {
+ super(name, patterns);
+ }
+
+ public General(Name name, Automaton automaton) {
+ super(name, automaton);
+ }
+
+ @Override
+ protected General create(Name name, Automaton automaton) {
+ return new General(name, automaton);
+ }
+
+ @Override
+ protected General none() {
+ return NONE;
+ }
+ }
+
+
public static class Index extends AutomatonPrivilege {
public static final Index NONE = new Index(Name.NONE, Automata.makeEmpty());
diff --git a/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java b/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java
index bbcc18d55a1..5de13445386 100644
--- a/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java
+++ b/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java
@@ -5,8 +5,6 @@
*/
package org.elasticsearch.shield.license;
-import org.elasticsearch.license.plugin.core.LicensesClientService;
-
import java.util.HashSet;
import java.util.Set;
@@ -22,22 +20,28 @@ import java.util.Set;
*/
public class LicenseEventsNotifier {
- private final Set listeners = new HashSet<>();
+ private final Set listeners = new HashSet<>();
- public void register(LicensesClientService.Listener listener) {
+ public void register(Listener listener) {
listeners.add(listener);
}
protected void notifyEnabled() {
- for (LicensesClientService.Listener listener : listeners) {
- listener.onEnabled();
+ for (Listener listener : listeners) {
+ listener.enabled();
}
}
protected void notifyDisabled() {
- for (LicensesClientService.Listener listener : listeners) {
- listener.onDisabled();
+ for (Listener listener : listeners) {
+ listener.disabled();
}
}
+ public static interface Listener {
+
+ void enabled();
+
+ void disabled();
+ }
}
diff --git a/src/main/java/org/elasticsearch/shield/license/LicenseService.java b/src/main/java/org/elasticsearch/shield/license/LicenseService.java
index d1b28bc59a4..c63999aefe9 100644
--- a/src/main/java/org/elasticsearch/shield/license/LicenseService.java
+++ b/src/main/java/org/elasticsearch/shield/license/LicenseService.java
@@ -6,14 +6,21 @@
package org.elasticsearch.shield.license;
import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.joda.FormatDateTimeFormatter;
+import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.core.LicensesClientService;
import org.elasticsearch.license.plugin.core.LicensesService;
import org.elasticsearch.shield.ShieldPlugin;
+import java.util.Collection;
+import java.util.Locale;
+
/**
*
*/
@@ -24,8 +31,11 @@ public class LicenseService extends AbstractLifecycleComponent {
private static final LicensesService.TrialLicenseOptions TRIAL_LICENSE_OPTIONS =
new LicensesService.TrialLicenseOptions(TimeValue.timeValueHours(30 * 24), 1000);
+ private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT);
+
private final LicensesClientService licensesClientService;
private final LicenseEventsNotifier notifier;
+ private final Collection expirationLoggers;
private boolean enabled = false;
@@ -34,6 +44,41 @@ public class LicenseService extends AbstractLifecycleComponent {
super(settings);
this.licensesClientService = licensesClientService;
this.notifier = notifier;
+ this.expirationLoggers = ImmutableList.of(
+ new LicensesService.ExpirationCallback.Pre(days(7), days(30), days(1)) {
+ @Override
+ public void on(License license, LicensesService.ExpirationStatus status) {
+ logger.error("\n" +
+ "#\n" +
+ "# Shield license will expire on [{}]. Cluster health, cluster stats and indices stats operations are\n" +
+ "# blocked on Shield license expiration. All data operations (read and write) continue to work. If you\n" +
+ "# have a new license, please update it. Otherwise, please reach out to your support contact.\n" +
+ "#", DATE_FORMATTER.printer().print(license.expiryDate()));
+ }
+ },
+ new LicensesService.ExpirationCallback.Pre(days(0), days(7), minutes(10)) {
+ @Override
+ public void on(License license, LicensesService.ExpirationStatus status) {
+ logger.error("\n" +
+ "#\n" +
+ "# Shield license will expire on [{}]. Cluster health, cluster stats and indices stats operations are\n" +
+ "# blocked on Shield license expiration. All data operations (read and write) continue to work. If you\n" +
+ "# have a new license, please update it. Otherwise, please reach out to your support contact.\n" +
+ "#", DATE_FORMATTER.printer().print(license.expiryDate()));
+ }
+ },
+ new LicensesService.ExpirationCallback.Post(days(0), null, minutes(10)) {
+ @Override
+ public void on(License license, LicensesService.ExpirationStatus status) {
+ logger.error("\n" +
+ "#\n" +
+ "# SHIELD LICENSE EXPIRED ON [{}]! CLUSTER HEALTH, CLUSTER STATS AND INDICES STATS OPERATIONS ARE\n" +
+ "# NOW BLOCKED. ALL DATA OPERATIONS (READ AND WRITE) CONTINUE TO WORK. IF YOU HAVE A NEW LICENSE, PLEASE\n" +
+ "# UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" +
+ "#", DATE_FORMATTER.printer().print(license.expiryDate()));
+ }
+ }
+ );
}
public synchronized boolean enabled() {
@@ -43,10 +88,10 @@ public class LicenseService extends AbstractLifecycleComponent {
@Override
protected void doStart() throws ElasticsearchException {
if (settings.getGroups("tribe", true).isEmpty()) {
- licensesClientService.register(FEATURE_NAME, TRIAL_LICENSE_OPTIONS, new InternalListener());
+ licensesClientService.register(FEATURE_NAME, TRIAL_LICENSE_OPTIONS, expirationLoggers, new InternalListener());
} else {
//TODO currently we disable licensing on tribe node. remove this once es core supports merging cluster
- new InternalListener().onEnabled();
+ new InternalListener().onEnabled(null);
}
}
@@ -58,22 +103,33 @@ public class LicenseService extends AbstractLifecycleComponent {
protected void doClose() throws ElasticsearchException {
}
+ static TimeValue days(int days) {
+ return TimeValue.timeValueHours(days * 24);
+ }
+
+ static TimeValue minutes(int minutes) {
+ return TimeValue.timeValueMinutes(minutes);
+ }
+
class InternalListener implements LicensesClientService.Listener {
@Override
- public void onEnabled() {
+ public void onEnabled(License license) {
synchronized (LicenseService.this) {
+ logger.info("enabling license for [{}]", FEATURE_NAME);
enabled = true;
notifier.notifyEnabled();
}
}
@Override
- public void onDisabled() {
+ public void onDisabled(License license) {
synchronized (LicenseService.this) {
+ logger.info("DISABLING LICENSE FOR [{}]", FEATURE_NAME);
enabled = false;
notifier.notifyDisabled();
}
}
}
+
}
diff --git a/src/test/java/org/elasticsearch/integration/LicensingTests.java b/src/test/java/org/elasticsearch/integration/LicensingTests.java
index 22ef9f8af89..59dc97b6ea8 100644
--- a/src/test/java/org/elasticsearch/integration/LicensingTests.java
+++ b/src/test/java/org/elasticsearch/integration/LicensingTests.java
@@ -5,9 +5,11 @@
*/
package org.elasticsearch.integration;
-import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsIndices;
+import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.index.IndexResponse;
-import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.common.component.AbstractComponent;
@@ -15,6 +17,7 @@ import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.core.LicenseExpiredException;
import org.elasticsearch.license.plugin.core.LicensesClientService;
import org.elasticsearch.license.plugin.core.LicensesService;
@@ -31,12 +34,9 @@ import java.util.Collection;
import java.util.List;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
-import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.SUITE;
-import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
/**
*
@@ -44,6 +44,19 @@ import static org.hamcrest.Matchers.is;
@ClusterScope(scope = SUITE)
public class LicensingTests extends ShieldIntegrationTest {
+ static final License DUMMY_LICENSE = License.builder()
+ .feature(LicenseService.FEATURE_NAME)
+ .expiryDate(System.currentTimeMillis())
+ .issueDate(System.currentTimeMillis())
+ .issuedTo("LicensingTests")
+ .issuer("test")
+ .maxNodes(Integer.MAX_VALUE)
+ .signature("_signature")
+ .type("test_license_for_shield")
+ .subscriptionType("all_is_good")
+ .uid(String.valueOf(CHILD_JVM_ID) + System.identityHashCode(LicensingTests.class))
+ .build();
+
public static final String ROLES =
ShieldSettingsSource.DEFAULT_ROLE + ":\n" +
" cluster: all\n" +
@@ -116,17 +129,26 @@ public class LicensingTests extends ShieldIntegrationTest {
Client client = internalCluster().transportClient();
disableLicensing();
+
try {
- client.prepareSearch().setQuery(matchAllQuery()).get();
- fail("expected an license expired exception when running a search with disabled license");
+ client.admin().indices().prepareStats().get();
+ fail("expected an license expired exception when executing an index stats action");
} catch (LicenseExpiredException lee) {
// expected
assertThat(lee.feature(), equalTo(LicenseService.FEATURE_NAME));
}
try {
- client.prepareGet("test1", "type", indexResponse.getId()).get();
- fail("expected an license expired exception when running a get with disabled license");
+ client.admin().cluster().prepareClusterStats().get();
+ fail("expected an license expired exception when executing cluster stats action");
+ } catch (LicenseExpiredException lee) {
+ // expected
+ assertThat(lee.feature(), equalTo(LicenseService.FEATURE_NAME));
+ }
+
+ try {
+ client.admin().cluster().prepareHealth().get();
+ fail("expected an license expired exception when executing cluster health action");
} catch (LicenseExpiredException lee) {
// expected
assertThat(lee.feature(), equalTo(LicenseService.FEATURE_NAME));
@@ -134,27 +156,17 @@ public class LicensingTests extends ShieldIntegrationTest {
enableLicensing();
- SearchResponse searchResponse = client.prepareSearch().setQuery(matchAllQuery()).get();
- assertNoFailures(searchResponse);
- assertHitCount(searchResponse, 2);
+ IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats().get();
+ assertNoFailures(indicesStatsResponse);
- GetResponse getResponse = client.prepareGet("test1", "type", indexResponse.getId()).get();
- assertThat(getResponse.getId(), equalTo(indexResponse.getId()));
+ ClusterStatsResponse clusterStatsNodeResponse = client.admin().cluster().prepareClusterStats().get();
+ assertThat(clusterStatsNodeResponse, notNullValue());
+ ClusterStatsIndices indices = clusterStatsNodeResponse.getIndicesStats();
+ assertThat(indices, notNullValue());
+ assertThat(indices.getIndexCount(), is(2));
- enableLicensing();
- indexResponse = index("test", "type", jsonBuilder()
- .startObject()
- .field("name", "value2")
- .endObject());
- assertThat(indexResponse.isCreated(), is(true));
-
- disableLicensing();
-
- indexResponse = index("test", "type", jsonBuilder()
- .startObject()
- .field("name", "value3")
- .endObject());
- assertThat(indexResponse.isCreated(), is(true));
+ ClusterHealthResponse clusterIndexHealth = client.admin().cluster().prepareHealth().get();
+ assertThat(clusterIndexHealth, notNullValue());
}
public static void disableLicensing() {
@@ -208,20 +220,20 @@ public class LicensingTests extends ShieldIntegrationTest {
}
@Override
- public void register(String feature, LicensesService.TrialLicenseOptions trialLicenseOptions, Listener listener) {
+ public void register(String s, LicensesService.TrialLicenseOptions trialLicenseOptions, Collection collection, Listener listener) {
listeners.add(listener);
enable();
}
void enable() {
for (Listener listener : listeners) {
- listener.onEnabled();
+ listener.onEnabled(DUMMY_LICENSE);
}
}
void disable() {
for (Listener listener : listeners) {
- listener.onDisabled();
+ listener.onDisabled(DUMMY_LICENSE);
}
}
}
diff --git a/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java b/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java
index beafbd9e761..0593231f41c 100644
--- a/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java
+++ b/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java
@@ -26,6 +26,7 @@ import org.elasticsearch.test.rest.json.JsonPath;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportService;
import org.hamcrest.Matcher;
+import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -49,6 +50,15 @@ public class ShieldPluginEnabledDisabledTests extends ShieldIntegrationTest {
enabled = randomBoolean();
}
+ @After
+ public void cleanup() throws Exception {
+ // now that on a disabled license we block cluster health/stats and indices stats, we need
+ // to make sure that after the tests (which disable the license for testing purposes) we
+ // reenabled the license, so the internal cluster will be cleaned appropriately.
+ logger.info("cleanup: enabling licensing...");
+ LicensingTests.enableLicensing();
+ }
+
@Override
protected Settings nodeSettings(int nodeOrdinal) {
logger.info("******* shield is " + (enabled ? "enabled" : "disabled"));
diff --git a/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java b/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java
index 3c2e40d2137..337325b3b4a 100644
--- a/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java
+++ b/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java
@@ -10,15 +10,14 @@ import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.support.ActionFilterChain;
import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.license.plugin.core.LicensesClientService;
import org.elasticsearch.shield.User;
import org.elasticsearch.shield.audit.AuditTrail;
import org.elasticsearch.shield.authc.AuthenticationService;
import org.elasticsearch.shield.authz.AuthorizationException;
import org.elasticsearch.shield.authz.AuthorizationService;
import org.elasticsearch.shield.license.LicenseEventsNotifier;
-import org.elasticsearch.shield.signature.SignatureService;
import org.elasticsearch.shield.signature.SignatureException;
+import org.elasticsearch.shield.signature.SignatureService;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -110,8 +109,8 @@ public class ShieldActionFilterTests extends ElasticsearchTestCase {
private class MockLicenseEventsNotifier extends LicenseEventsNotifier {
@Override
- public void register(LicensesClientService.Listener listener) {
- listener.onEnabled();
+ public void register(MockLicenseEventsNotifier.Listener listener) {
+ listener.enabled();
}
}
}
diff --git a/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java b/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java
index 623c3b25e8f..97f58b2dfb2 100644
--- a/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java
+++ b/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java
@@ -7,6 +7,7 @@ package org.elasticsearch.shield.test;
import com.google.common.base.Charsets;
import org.elasticsearch.ElasticsearchException;
+import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.io.Streams;
import java.io.File;
@@ -15,6 +16,20 @@ import java.nio.file.Path;
public class ShieldTestUtils {
+ public static File createFolder(File parent, String name) {
+ File createdFolder = new File(parent, name);
+ //the directory might exist e.g. if the global cluster gets restarted, then we recreate the directory as well
+ if (createdFolder.exists()) {
+ if (!FileSystemUtils.deleteRecursively(createdFolder)) {
+ throw new RuntimeException("could not delete existing temporary folder: " + createdFolder.getAbsolutePath());
+ }
+ }
+ if (!createdFolder.mkdir()) {
+ throw new RuntimeException("could not create temporary folder: " + createdFolder.getAbsolutePath());
+ }
+ return createdFolder;
+ }
+
public static String writeFile(File folder, String name, byte[] content) {
Path file = folder.toPath().resolve(name);
try {
diff --git a/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTest.java b/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTest.java
index 59dab148868..4248e5daa55 100644
--- a/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTest.java
+++ b/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTest.java
@@ -5,13 +5,16 @@
*/
package org.elasticsearch.shield.transport;
-import org.elasticsearch.ElasticsearchTimeoutException;
+import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.collect.ImmutableMap;
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.common.unit.TimeValue;
+import org.elasticsearch.discovery.MasterNotDiscoveredException;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.internal.InternalNode;
+import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
import org.elasticsearch.shield.signature.InternalSignatureService;
import org.elasticsearch.test.ShieldIntegrationTest;
import org.elasticsearch.test.ShieldSettingsSource;
@@ -24,6 +27,8 @@ import java.net.InetSocketAddress;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.elasticsearch.node.NodeBuilder.nodeBuilder;
+import static org.elasticsearch.shield.test.ShieldTestUtils.createFolder;
+import static org.elasticsearch.shield.test.ShieldTestUtils.writeFile;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import static org.hamcrest.CoreMatchers.instanceOf;
@@ -108,11 +113,19 @@ public class ServerTransportFilterIntegrationTest extends ShieldIntegrationTest
Settings dataNodeSettings = internalCluster().getDataNodeInstance(Settings.class);
String systemKeyFile = dataNodeSettings.get(InternalSignatureService.FILE_SETTING);
+ File folder = createFolder(globalTempDir(), getClass().getSimpleName() + "-" + randomAsciiOfLength(10));
+
// test that starting up a node works
Settings nodeSettings = settingsBuilder()
+ .put("shield.authc.realms.esusers.type", ESUsersRealm.TYPE)
+ .put("shield.authc.realms.esusers.order", 0)
+ .put("shield.authc.realms.esusers.files.users", writeFile(folder, "users", configUsers()))
+ .put("shield.authc.realms.esusers.files.users_roles", writeFile(folder, "users_roles", configUsersRoles()))
+ .put("shield.authz.store.files.roles", writeFile(folder, "roles.yml", configRoles()))
.put(ShieldSettingsSource.getSSLSettingsForStore("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks", "testnode"))
.put("node.mode", "network")
.put("node.name", "my-test-node")
+ .put("shield.user", "test_user:changeme")
.put("cluster.name", internalCluster().getClusterName())
.put("discovery.zen.ping.multicast.enabled", false)
.put("discovery.zen.ping.unicast.hosts", "localhost:" + randomClientPort)
@@ -127,9 +140,21 @@ public class ServerTransportFilterIntegrationTest extends ShieldIntegrationTest
// assert that node is not connected by waiting for the timeout
try {
- node.client().admin().cluster().prepareHealth().get("1s");
- fail("Expected timeout exception due to node unable to connect");
- } catch (ElasticsearchTimeoutException e) {}
+ // updating cluster settings requires a master. since the node should not be able to
+ // connect to the cluster, there should be no master, and therefore this
+ // operation should fail. we can't use cluster health/stats here to and
+ // wait for a timeout, because as long as the node is not connected to the cluster
+ // the license is disabled and therefore blocking health & stats calls.
+ node.client().admin().cluster().prepareUpdateSettings()
+ .setTransientSettings(ImmutableMap.of("key", "value"))
+ .setMasterNodeTimeout(TimeValue.timeValueSeconds(2))
+ .get();
+ fail("Expected to fail update settings as the node should not be able to connect to the cluster, and therefore there should be no master");
+ } catch (MasterNotDiscoveredException e) {
+ // expected
+ logger.error("expected: " + e);
+ }
}
}
+
}
diff --git a/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java b/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java
index a17fccd9ea9..e93a3283536 100644
--- a/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java
+++ b/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java
@@ -29,7 +29,7 @@ import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
// no client nodes, no transport clients, as they all get rejected on network connections
-@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0, transportClientRatio = 0.0)
+@ClusterScope(scope = Scope.SUITE, numDataNodes = 0, numClientNodes = 0, transportClientRatio = 0.0)
public class IpFilteringIntegrationTests extends ShieldIntegrationTest {
private static int randomClientPort;
diff --git a/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java b/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java
index cbc0dc89883..ea76b716154 100644
--- a/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java
+++ b/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java
@@ -18,6 +18,7 @@ import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.shield.signature.InternalSignatureService;
+import org.elasticsearch.shield.test.ShieldTestUtils;
import org.elasticsearch.shield.transport.netty.NettySecuredTransport;
import org.elasticsearch.test.discovery.ClusterDiscoveryConfiguration;
@@ -107,7 +108,7 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
@Override
public Settings node(int nodeOrdinal) {
- File folder = createFolder(parentFolder, subfolderPrefix + "-" + nodeOrdinal);
+ File folder = ShieldTestUtils.createFolder(parentFolder, subfolderPrefix + "-" + nodeOrdinal);
ImmutableSettings.Builder builder = ImmutableSettings.builder().put(super.node(nodeOrdinal))
.put("plugin.types", ShieldPlugin.class.getName() + "," + licensePluginClass().getName())
.put("shield.audit.enabled", randomBoolean())
@@ -184,20 +185,6 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
}
}
- private static File createFolder(File parent, String name) {
- File createdFolder = new File(parent, name);
- //the directory might exist e.g. if the global cluster gets restarted, then we recreate the directory as well
- if (createdFolder.exists()) {
- if (!FileSystemUtils.deleteRecursively(createdFolder)) {
- throw new RuntimeException("could not delete existing temporary folder: " + createdFolder.getAbsolutePath());
- }
- }
- if (!createdFolder.mkdir()) {
- throw new RuntimeException("could not create temporary folder: " + createdFolder.getAbsolutePath());
- }
- return createdFolder;
- }
-
private static byte[] generateKey() {
try {
return InternalSignatureService.generateKey();