Merge pull request elastic/elasticsearch#2908 from rjernst/deguice2

Internal: Collapse Licensee per feature into single XPackLicenseState

Original commit: elastic/x-pack-elasticsearch@c4dec85d63
This commit is contained in:
Ryan Ernst 2016-07-25 17:54:13 -07:00 committed by GitHub
commit c44b668605
98 changed files with 1374 additions and 3241 deletions

View File

@ -46,9 +46,6 @@ public class Graph extends Plugin implements ActionPlugin {
public Collection<Module> createGuiceModules() {
return Collections.singletonList(b -> {
XPackPlugin.bindFeatureSet(b, GraphFeatureSet.class);
if (transportClientMode) {
b.bind(GraphLicensee.class).toProvider(Providers.of(null));
}
});
}

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.XPackFeatureSet;
import java.io.IOException;
@ -20,12 +21,12 @@ import java.io.IOException;
public class GraphFeatureSet implements XPackFeatureSet {
private final boolean enabled;
private final GraphLicensee licensee;
private final XPackLicenseState licenseState;
@Inject
public GraphFeatureSet(Settings settings, @Nullable GraphLicensee licensee, NamedWriteableRegistry namedWriteableRegistry) {
public GraphFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, NamedWriteableRegistry namedWriteableRegistry) {
this.enabled = Graph.enabled(settings);
this.licensee = licensee;
this.licenseState = licenseState;
namedWriteableRegistry.register(Usage.class, Usage.writeableName(Graph.NAME), Usage::new);
}
@ -41,7 +42,7 @@ public class GraphFeatureSet implements XPackFeatureSet {
@Override
public boolean available() {
return licensee != null && licensee.isAvailable();
return licenseState != null && licenseState.isGraphAllowed();
}
@Override

View File

@ -1,64 +0,0 @@
/*
* 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.xpack.graph;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
public class GraphLicensee extends AbstractLicenseeComponent {
public static final String ID = Graph.NAME;
public GraphLicensee(Settings settings) {
super(settings, ID);
}
@Override
public String[] expirationMessages() {
return new String[] {
"Graph explore APIs are disabled"
};
}
@Override
public String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
case STANDARD:
case GOLD:
switch (currentMode) {
case TRIAL:
case PLATINUM:
return new String[] { "Graph will be disabled" };
}
break;
}
return Strings.EMPTY_ARRAY;
}
/**
* Determine if Graph Exploration should be enabled.
* <p>
* Exploration is only disabled when the license has expired or if the mode is not:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean isAvailable() {
// status is volatile
Status localStatus = status;
OperationMode operationMode = localStatus.getMode();
boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
return licensed && localStatus.isActive();
}
}

View File

@ -24,6 +24,7 @@ import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.sampler.DiversifiedAggregationBuilder;
@ -37,7 +38,7 @@ import org.elasticsearch.search.aggregations.bucket.terms.support.IncludeExclude
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.elasticsearch.xpack.graph.Graph;
import org.elasticsearch.xpack.graph.action.Connection.ConnectionId;
import org.elasticsearch.xpack.graph.action.GraphExploreRequest.TermBoost;
import org.elasticsearch.xpack.graph.action.Vertex.VertexId;
@ -58,7 +59,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class TransportGraphExploreAction extends HandledTransportAction<GraphExploreRequest, GraphExploreResponse> {
private final TransportSearchAction searchAction;
protected final GraphLicensee licensee;
protected final XPackLicenseState licenseState;
static class VertexPriorityQueue extends PriorityQueue<Vertex> {
@ -76,19 +77,19 @@ public class TransportGraphExploreAction extends HandledTransportAction<GraphExp
@Inject
public TransportGraphExploreAction(Settings settings, ThreadPool threadPool, TransportSearchAction transportSearchAction,
TransportService transportService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver,
GraphLicensee licensee) {
XPackLicenseState licenseState) {
super(settings, GraphExploreAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver,
GraphExploreRequest::new);
this.searchAction = transportSearchAction;
this.licensee = licensee;
this.licenseState = licenseState;
}
@Override
protected void doExecute(GraphExploreRequest request, ActionListener<GraphExploreResponse> listener) {
if (licensee.isAvailable()) {
if (licenseState.isGraphAllowed()) {
new AsyncGraphAction(request, listener).start();
} else {
listener.onFailure(LicenseUtils.newComplianceException(GraphLicensee.ID));
listener.onFailure(LicenseUtils.newComplianceException(Graph.NAME));
}
}

View File

@ -7,9 +7,8 @@ package org.elasticsearch.xpack.graph;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.graph.GraphFeatureSet;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.junit.Before;
import static org.hamcrest.core.Is.is;
@ -24,24 +23,24 @@ import static org.mockito.Mockito.when;
*/
public class GraphFeatureSetTests extends ESTestCase {
private GraphLicensee licensee;
private XPackLicenseState licenseState;
private NamedWriteableRegistry namedWriteableRegistry;
@Before
public void init() throws Exception {
licensee = mock(GraphLicensee.class);
licenseState = mock(XPackLicenseState.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
}
public void testWritableRegistration() throws Exception {
new GraphFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry);
new GraphFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry);
verify(namedWriteableRegistry).register(eq(GraphFeatureSet.Usage.class), eq("xpack.usage.graph"), anyObject());
}
public void testAvailable() throws Exception {
GraphFeatureSet featureSet = new GraphFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry);
GraphFeatureSet featureSet = new GraphFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry);
boolean available = randomBoolean();
when(licensee.isAvailable()).thenReturn(available);
when(licenseState.isGraphAllowed()).thenReturn(available);
assertThat(featureSet.available(), is(available));
}
@ -55,7 +54,7 @@ public class GraphFeatureSetTests extends ESTestCase {
} else {
settings.put("xpack.graph.enabled", enabled);
}
GraphFeatureSet featureSet = new GraphFeatureSet(settings.build(), licensee, namedWriteableRegistry);
GraphFeatureSet featureSet = new GraphFeatureSet(settings.build(), licenseState, namedWriteableRegistry);
assertThat(featureSet.enabled(), is(enabled));
}

View File

@ -1,102 +0,0 @@
/*
* 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.xpack.graph.license;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
import org.elasticsearch.xpack.graph.GraphLicensee;
import static org.hamcrest.Matchers.is;
public class LicenseTests extends AbstractLicenseeTestCase {
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY);
public void testPlatinumTrialLicenseCanDoEverything() throws Exception {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
}
public void testBasicLicenseIsDisabled() throws Exception {
setOperationMode(graphLicensee, OperationMode.BASIC);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testStandardLicenseIsDisabled() throws Exception {
setOperationMode(graphLicensee, OperationMode.STANDARD);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testNoLicenseDoesNotWork() {
setOperationMode(graphLicensee, OperationMode.BASIC);
disable(graphLicensee);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testExpiredPlatinumTrialLicenseIsRestricted() throws Exception {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
disable(graphLicensee);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testUpgradingFromBasicLicenseWorks() {
setOperationMode(graphLicensee, OperationMode.BASIC);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
}
public void testDowngradingToBasicLicenseWorks() {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
setOperationMode(graphLicensee, OperationMode.BASIC);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testUpgradingFromStandardLicenseWorks() {
setOperationMode(graphLicensee, OperationMode.STANDARD);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
}
public void testDowngradingToStandardLicenseWorks() {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
setOperationMode(graphLicensee, OperationMode.STANDARD);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testDowngradingToGoldLicenseWorks() {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
setOperationMode(graphLicensee, OperationMode.GOLD);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
}
public void testUpgradingExpiredLicenseWorks() {
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
disable(graphLicensee);
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
setOperationMode(graphLicensee, randomTrialOrPlatinumMode());
assertLicensePlatinumTrialBehaviour(graphLicensee);
}
private void assertLicensePlatinumTrialBehaviour(GraphLicensee graphLicensee) {
assertThat("Expected graph exploration to be allowed", graphLicensee.isAvailable(), is(true));
}
private void assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(GraphLicensee graphLicensee) {
assertThat("Expected graph exploration not to be allowed", graphLicensee.isAvailable(), is(false));
}
}

View File

@ -5,6 +5,11 @@
*/
package org.elasticsearch.license.plugin;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.cluster.metadata.MetaData;
@ -21,23 +26,14 @@ import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
import org.elasticsearch.license.plugin.action.put.TransportPutLicenseAction;
import org.elasticsearch.license.plugin.core.LicensesMetaData;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.license.plugin.rest.RestDeleteLicenseAction;
import org.elasticsearch.license.plugin.rest.RestGetLicenseAction;
import org.elasticsearch.license.plugin.rest.RestPutLicenseAction;
import org.elasticsearch.plugins.ActionPlugin;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.SecurityLicensee;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.elasticsearch.xpack.XPackPlugin.isTribeNode;
@ -87,16 +83,10 @@ public class Licensing implements ActionPlugin {
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
ResourceWatcherService resourceWatcherService,
SecurityLicenseState securityLicenseState) {
SecurityLicensee securityLicensee = new SecurityLicensee(settings, securityLicenseState);
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
GraphLicensee graphLicensee = new GraphLicensee(settings);
XPackLicenseState licenseState) {
LicenseService licenseService = new LicenseService(settings, clusterService, clock,
environment, resourceWatcherService,
Arrays.asList(securityLicensee, watcherLicensee, monitoringLicensee, graphLicensee));
return Arrays.asList(licenseService, securityLicenseState, securityLicensee, watcherLicensee, monitoringLicensee, graphLicensee);
environment, resourceWatcherService, licenseState);
return Arrays.asList(licenseService, licenseState);
}
public List<Setting<?>> getSettings() {

View File

@ -1,60 +0,0 @@
/*
* 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.license.plugin.core;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.settings.Settings;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* A supporting base class for injectable Licensee components.
*/
public abstract class AbstractLicenseeComponent extends AbstractComponent implements Licensee {
private final String id;
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
// we initialize the licensee state to enabled with trial operation mode
protected volatile Status status = Status.ENABLED;
protected AbstractLicenseeComponent(Settings settings, String id) {
super(settings);
this.id = id;
}
@Override
public final String id() {
return id;
}
/**
* @return the current status of this licensee (can never be null)
*/
public Status getStatus() {
return status;
}
public void add(Listener listener) {
listeners.add(listener);
}
@Override
public void onChange(Status status) {
this.status = status;
logger.trace("[{}] is running in [{}] mode", id(), status);
for (Listener listener : listeners) {
listener.onChange(status);
}
}
public interface Listener {
void onChange(Status status);
}
}

View File

@ -44,18 +44,13 @@ import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* Service responsible for managing {@link LicensesMetaData}
* Interfaces through which this is exposed are:
* - LicensesClientService - responsible for listener registration of consumer plugin(s)
* Service responsible for managing {@link LicensesMetaData}.
* <p>
* Notification Scheme:
* <p>
* All registered listeners are notified of the current license upon registration or when a new license is installed in the cluster state.
* When a new license is notified as enabled to the registered listener, a notification is scheduled at the time of license expiry.
* Registered listeners are notified using {@link #onUpdate(LicensesMetaData)}
* On the master node, the service handles updating the cluster state when a new license is registered.
* It also listens on all nodes for cluster state updates, and updates {@link XPackLicenseState} when
* the license changes are detected in the cluster state.
*/
public class LicenseService extends AbstractLifecycleComponent implements ClusterStateListener, SchedulerEngine.Listener {
@ -65,14 +60,12 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
/**
* Duration of grace period after a license has expired
*/
public static final TimeValue GRACE_PERIOD_DURATION = days(7);
static final TimeValue GRACE_PERIOD_DURATION = days(7);
private final ClusterService clusterService;
/**
* Currently active consumers to notify to
*/
private final List<InternalLicensee> registeredLicensees;
/** The xpack feature state to update when license changes are made. */
private final XPackLicenseState licenseState;
/**
* Currently active license
@ -104,115 +97,70 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
"please read the following messages and update the license again, this time with the \"acknowledge=true\" parameter:";
public LicenseService(Settings settings, ClusterService clusterService, Clock clock, Environment env,
ResourceWatcherService resourceWatcherService, List<Licensee> registeredLicensees) {
ResourceWatcherService resourceWatcherService, XPackLicenseState licenseState) {
super(settings);
this.clusterService = clusterService;
this.clock = clock;
this.scheduler = new SchedulerEngine(clock);
this.registeredLicensees = registeredLicensees.stream().map(InternalLicensee::new).collect(Collectors.toList());
this.licenseState = licenseState;
this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService,
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> notifyLicensees(getLicense()));
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> updateLicenseState(getLicense()));
this.scheduler.register(this);
populateExpirationCallbacks();
}
private void logExpirationWarning(long expirationMillis, boolean expired) {
String expiredMsg = expired ? "will expire" : "expired";
String general = LoggerMessageFormat.format(null, "\n" +
"#\n" +
"# License [{}] on [{}]. If you have a new license, please update it.\n" +
"# Otherwise, please reach out to your support contact.\n" +
"# ", expiredMsg, DATE_FORMATTER.printer().print(expirationMillis));
if (expired) {
general = general.toUpperCase(Locale.ROOT);
}
StringBuilder builder = new StringBuilder(general);
builder.append(System.lineSeparator());
if (expired) {
builder.append("# COMMERCIAL PLUGINS OPERATING WITH REDUCED FUNCTIONALITY");
} else {
builder.append("# Commercial plugins operate with reduced functionality on license expiration:");
}
XPackLicenseState.EXPIRATION_MESSAGES.forEach((feature, messages) -> {
if (messages.length > 0) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(feature);
for (String message : messages) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(message);
}
}
});
logger.warn("{}", builder);
}
private void populateExpirationCallbacks() {
expirationCallbacks.add(new ExpirationCallback.Pre(days(7), days(25), days(1)) {
@Override
public void on(License license) {
String general = LoggerMessageFormat.format(null, "\n" +
"#\n" +
"# License will expire on [{}]. If you have a new license, please update it.\n" +
"# Otherwise, please reach out to your support contact.\n" +
"# ", DATE_FORMATTER.printer().print(license.expiryDate()));
if (!registeredLicensees.isEmpty()) {
StringBuilder builder = new StringBuilder(general);
builder.append(System.lineSeparator());
builder.append("# Commercial plugins operate with reduced functionality on license " +
"expiration:");
for (InternalLicensee licensee : registeredLicensees) {
if (licensee.expirationMessages().length > 0) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(licensee.id());
for (String message : licensee.expirationMessages()) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(message);
}
}
}
logger.warn("{}", builder);
} else {
logger.warn("{}", general);
}
}
}
);
@Override
public void on(License license) {
logExpirationWarning(license.expiryDate(), false);
}
});
expirationCallbacks.add(new ExpirationCallback.Pre(days(0), days(7), TimeValue.timeValueMinutes(10)) {
@Override
public void on(License license) {
String general = LoggerMessageFormat.format(null, "\n" +
"#\n" +
"# License will expire on [{}]. If you have a new license, please update it.\n" +
"# Otherwise, please reach out to your support contact.\n" +
"# ", DATE_FORMATTER.printer().print(license.expiryDate()));
if (!registeredLicensees.isEmpty()) {
StringBuilder builder = new StringBuilder(general);
builder.append(System.lineSeparator());
builder.append("# Commercial plugins operate with reduced functionality on license " +
"expiration:");
for (InternalLicensee licensee : registeredLicensees) {
if (licensee.expirationMessages().length > 0) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(licensee.id());
for (String message : licensee.expirationMessages()) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(message);
}
}
}
logger.warn("{}", builder.toString());
} else {
logger.warn("{}", general);
}
}
}
);
@Override
public void on(License license) {
logExpirationWarning(license.expiryDate(), false);
}
});
expirationCallbacks.add(new ExpirationCallback.Post(days(0), null, TimeValue.timeValueMinutes(10)) {
@Override
public void on(License license) {
// logged when grace period begins
String general = LoggerMessageFormat.format(null, "\n" +
"#\n" +
"# LICENSE EXPIRED ON [{}]. 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()));
if (!registeredLicensees.isEmpty()) {
StringBuilder builder = new StringBuilder(general);
builder.append(System.lineSeparator());
builder.append("# COMMERCIAL PLUGINS OPERATING WITH REDUCED FUNCTIONALITY");
for (InternalLicensee licensee : registeredLicensees) {
if (licensee.expirationMessages().length > 0) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(licensee.id());
for (String message : licensee.expirationMessages()) {
builder.append(System.lineSeparator());
builder.append("# - ");
builder.append(message);
}
}
}
logger.warn("{}", builder.toString());
} else {
logger.warn("{}", general);
}
}
}
);
@Override
public void on(License license) {
// logged when grace period begins
logExpirationWarning(license.expiryDate(), true);
}
});
}
/**
@ -228,23 +176,23 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
listener.onResponse(new PutLicenseResponse(true, LicensesStatus.EXPIRED));
} else {
if (!request.acknowledged()) {
// TODO: ack messages should be generated on the master, since another node's cluster state may be behind...
final License currentLicense = getLicense();
if (currentLicense != null) {
Map<String, String[]> acknowledgeMessages = new HashMap<>(registeredLicensees.size() + 1);
Map<String, String[]> acknowledgeMessages = new HashMap<>();
if (!License.isAutoGeneratedLicense(currentLicense.signature()) // current license is not auto-generated
&& currentLicense.issueDate() > newLicense.issueDate()) { // and has a later issue date
acknowledgeMessages.put("license",
new String[]{"The new license is older than the currently installed license. Are you sure you want to " +
"override the current license?"});
acknowledgeMessages.put("license", new String[]{
"The new license is older than the currently installed license. " +
"Are you sure you want to override the current license?"});
}
for (InternalLicensee licensee : registeredLicensees) {
String[] listenerAcknowledgeMessages = licensee.acknowledgmentMessages(
currentLicense.operationMode(), newLicense.operationMode());
if (listenerAcknowledgeMessages.length > 0) {
acknowledgeMessages.put(licensee.id(), listenerAcknowledgeMessages);
XPackLicenseState.ACKNOWLEDGMENT_MESSAGES.forEach((feature, ackMessages) -> {
String[] messages = ackMessages.apply(currentLicense.operationMode(), newLicense.operationMode());
if (messages.length > 0) {
acknowledgeMessages.put(feature, messages);
}
}
if (!acknowledgeMessages.isEmpty()) {
});
if (acknowledgeMessages.isEmpty() == false) {
// needs acknowledgement
listener.onResponse(new PutLicenseResponse(false, LicensesStatus.VALID, ACKNOWLEDGEMENT_HEADER,
acknowledgeMessages));
@ -280,7 +228,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
if (licensesMetaData != null) {
final License license = licensesMetaData.getLicense();
if (event.getJobName().equals(LICENSE_JOB)) {
notifyLicensees(license);
updateLicenseState(license);
} else if (event.getJobName().startsWith(ExpirationCallback.EXPIRATION_JOB_PREFIX)) {
expirationCallbacks.stream()
.filter(expirationCallback -> expirationCallback.getId().equals(event.getJobName()))
@ -315,17 +263,6 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
});
}
public Licensee.Status licenseeStatus(License license) {
if (license == null) {
return new Licensee.Status(License.OperationMode.MISSING, false);
}
long time = clock.millis();
boolean active = time >= license.issueDate() &&
time < license.expiryDate() + GRACE_PERIOD_DURATION.getMillis();
return new Licensee.Status(license.operationMode(), active);
}
public License getLicense() {
final License license = getLicense(clusterService.state().metaData().custom(LicensesMetaData.TYPE));
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
@ -379,15 +316,25 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
protected void doStart() throws ElasticsearchException {
clusterService.add(this);
scheduler.start(Collections.emptyList());
registeredLicensees.forEach(x -> initLicensee(x.licensee));
logger.debug("initializing license state");
final ClusterState clusterState = clusterService.state();
if (clusterService.lifecycleState() == Lifecycle.State.STARTED
&& clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
&& clusterState.nodes().getMasterNode() != null) {
final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE);
if (clusterState.getNodes().isLocalNodeElectedMaster() &&
(currentMetaData == null || currentMetaData.getLicense() == null)) {
// triggers a cluster changed event
// eventually notifying the current licensee
registerTrialLicense();
}
}
}
@Override
protected void doStop() throws ElasticsearchException {
clusterService.remove(this);
scheduler.stop();
// clear all handlers
registeredLicensees.clear();
// clear current license
currentLicense.set(null);
}
@ -432,23 +379,18 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
}
}
private void notifyLicensees(final License license) {
protected void updateLicenseState(final License license) {
if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
// implies license has been explicitly deleted
// update licensee states
registeredLicensees.forEach(InternalLicensee::onRemove);
licenseState.update(License.OperationMode.MISSING, false);
return;
}
if (license != null) {
logger.debug("notifying [{}] listeners", registeredLicensees.size());
long time = clock.millis();
boolean active = time >= license.issueDate() &&
time < license.expiryDate() + GRACE_PERIOD_DURATION.getMillis();
licenseState.update(license.operationMode(), active);
Licensee.Status status = new Licensee.Status(license.operationMode(), active);
for (InternalLicensee licensee : registeredLicensees) {
licensee.onChange(status);
}
if (active) {
if (time < license.expiryDate()) {
logger.debug("license [{}] - valid", license.uid());
@ -487,7 +429,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
previousLicense.removeOperationModeFileWatcher();
}
}
notifyLicensees(license);
updateLicenseState(license);
}
}
@ -510,24 +452,6 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
};
}
private void initLicensee(Licensee licensee) {
logger.debug("initializing licensee [{}]", licensee.id());
final ClusterState clusterState = clusterService.state();
if (clusterService.lifecycleState() == Lifecycle.State.STARTED
&& clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
&& clusterState.nodes().getMasterNode() != null) {
final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE);
if (clusterState.getNodes().isLocalNodeElectedMaster() &&
(currentMetaData == null || currentMetaData.getLicense() == null)) {
// triggers a cluster changed event
// eventually notifying the current licensee
registerTrialLicense();
} else {
notifyLicensees(currentMetaData.getLicense());
}
}
}
License getLicense(final LicensesMetaData metaData) {
if (metaData != null) {
License license = metaData.getLicense();
@ -543,48 +467,4 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
}
return null;
}
/**
* Stores acknowledgement, expiration and license notification callbacks
* for a registered listener
*/
private final class InternalLicensee {
volatile Licensee.Status currentStatus = Licensee.Status.MISSING;
private final Licensee licensee;
private InternalLicensee(Licensee licensee) {
this.licensee = licensee;
}
@Override
public String toString() {
return "(listener: " + licensee.id() + ", state: " + currentStatus + ")";
}
public String id() {
return licensee.id();
}
public String[] expirationMessages() {
return licensee.expirationMessages();
}
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
return licensee.acknowledgmentMessages(currentMode, newMode);
}
public synchronized void onChange(final Licensee.Status status) {
if (currentStatus == null // not yet initialized
|| !currentStatus.equals(status)) { // current license has changed
logger.debug("licensee [{}] notified", licensee.id());
licensee.onChange(status);
currentStatus = status;
}
}
public void onRemove() {
onChange(Licensee.Status.MISSING);
}
}
}

View File

@ -1,104 +0,0 @@
/*
* 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.license.plugin.core;
import org.elasticsearch.license.core.License.OperationMode;
import java.util.Locale;
import java.util.Objects;
public interface Licensee {
/**
* Unique id used to log expiry and
* acknowledgment messages
*/
String id();
/**
* Messages to be printed when
* logging license expiry warnings
*/
String[] expirationMessages();
/**
* Messages to be returned when
* changing from current operation mode
* to new operation mode
*/
String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode);
/**
* Notifies when a new license is activated
* or when a license state change has occurred
*/
void onChange(Status status);
/**
* {@code Status} represents both the type and state of a license.
* <p>
* Most places in the code are expected to use {@code volatile} {@code Status} fields. It's important to follow use a local reference
* whenever checking different parts of the {@code Status}:
* <pre>
* Status status = this.status;
* return status.isActive() &amp;&amp;
* (status.getMode() == OperationMode.TRIAL || status.getMode == OperationMode.PLATINUM);
* </pre>
* Otherwise the license has the potential to change in-between both checks.
*/
class Status {
public static Status ENABLED = new Status(OperationMode.TRIAL, true);
public static Status MISSING = new Status(OperationMode.MISSING, false);
private final OperationMode mode;
private final boolean active;
public Status(OperationMode mode, boolean active) {
this.mode = mode;
this.active = active;
}
/**
* Returns the operation mode of the license
* responsible for the current <code>licenseState</code>
* <p>
* Note: Knowing the mode does not indicate whether the license is active. If that matters (e.g.,
* disabling services when a license becomes disabled), then check {@link #isActive()}.
*/
public OperationMode getMode() {
return mode;
}
/** Returns true if the license is within the issue date and grace period, or false otherwise */
public boolean isActive() {
return active;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Status status = (Status) o;
return active == status.active &&
mode == status.mode;
}
@Override
public int hashCode() {
return Objects.hash(mode, active);
}
@Override
public String toString() {
if (active) {
return mode.name().toLowerCase(Locale.ROOT);
} else {
return "disabled " + mode.name().toLowerCase(Locale.ROOT);
}
}
}
}

View File

@ -15,7 +15,7 @@ import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.xpack.TribeTransportTestCase;
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateSignedLicense;
public class LicenseTribeTests extends TribeTransportTestCase {

View File

@ -19,6 +19,7 @@ import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
import org.elasticsearch.license.plugin.core.LicensesStatus;
import org.elasticsearch.license.plugin.core.TestUtils;
import org.elasticsearch.xpack.monitoring.Monitoring;
import org.elasticsearch.node.Node;
import org.elasticsearch.plugins.Plugin;
@ -30,9 +31,8 @@ import org.elasticsearch.xpack.watcher.Watcher;
import java.util.Collection;
import java.util.Collections;
import static org.elasticsearch.license.plugin.TestUtils.dateMath;
import static org.elasticsearch.license.plugin.TestUtils.generateExpiredLicense;
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateExpiredLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateSignedLicense;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;

View File

@ -5,8 +5,6 @@
*/
package org.elasticsearch.license.plugin.core;
import java.util.Arrays;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
@ -51,11 +49,11 @@ public abstract class AbstractLicenseServiceTestCase extends ESTestCase {
environment = mock(Environment.class);
}
protected void setInitialState(License license, Licensee... licensees) {
protected void setInitialState(License license, XPackLicenseState licenseState) {
Path tempDir = createTempDir();
when(environment.configFile()).thenReturn(tempDir);
licenseService = new LicenseService(Settings.EMPTY, clusterService, clock, environment,
resourceWatcherService, Arrays.asList(licensees));
resourceWatcherService, licenseState);
ClusterState state = mock(ClusterState.class);
final ClusterBlocks noBlock = ClusterBlocks.builder().build();
when(state.blocks()).thenReturn(noBlock);

View File

@ -1,163 +0,0 @@
/*
* 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.license.plugin.core;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.test.ESTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Provides helper methods for {@link Licensee} implementations.
* <p>
* Note: This requires that this class be on the classpath for those implementations.
*/
public abstract class AbstractLicenseeTestCase extends ESTestCase {
/**
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
* <p>
* This will randomly {@code null}-out the {@code fromMode} license.
*
* @param fromMode Original / current license
* @param toMode New license
* @param licensee The licensee to test
*/
public static void assertEmptyAck(OperationMode fromMode, OperationMode toMode, Licensee licensee) {
// test it
String[] messages = licensee.acknowledgmentMessages(fromMode, toMode);
assertThat(fromToMessage(fromMode, toMode), messages.length, equalTo(0));
}
/**
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
* <p>
* This will randomly {@code null}-out the {@code fromMode} license.
*
* @param fromMode Original / current license
* @param toMode New license
* @param licenseeSupplier Supplies the licensee to test
*/
public static void assertEmptyAck(OperationMode fromMode, OperationMode toMode, Supplier<Licensee> licenseeSupplier) {
assertEmptyAck(fromMode, toMode, licenseeSupplier.get());
}
/**
* Get the ack when changing {@code fromMode} to {@code toMode}.
* <p>
* This just serves to remove a lot of duplicated code.
*
* @param fromMode Original / current license
* @param toMode New license
* @param licensee The licensee to test
*/
public static String[] ackLicenseChange(OperationMode fromMode, OperationMode toMode, Licensee licensee) {
return licensee.acknowledgmentMessages(fromMode, toMode);
}
/**
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
* <p>
* This just serves to remove a lot of duplicated code.
*
* @param fromMode Original / current license
* @param toMode New license
* @param licenseeSupplier Supplies the licensee to test
*/
public static String[] ackLicenseChange(OperationMode fromMode, OperationMode toMode, Supplier<Licensee> licenseeSupplier) {
return ackLicenseChange(fromMode, toMode, licenseeSupplier.get());
}
/**
* Randomly get {@link OperationMode#TRIAL} or {@link OperationMode#PLATINUM}.
*
* @return Never {@code null}.
*/
public static OperationMode randomTrialOrPlatinumMode() {
return randomFrom(OperationMode.TRIAL, OperationMode.PLATINUM);
}
/**
* Randomly get {@link OperationMode#TRIAL}, {@link OperationMode#STANDARD}, {@link OperationMode#GOLD}, or
* {@link OperationMode#PLATINUM}.
*
* @return Never {@code null}.
*/
public static OperationMode randomTrialStandardGoldOrPlatinumMode() {
return randomFrom(OperationMode.TRIAL, OperationMode.STANDARD, OperationMode.GOLD, OperationMode.PLATINUM);
}
/**
* Randomly get any {@link OperationMode}.
*
* @return Never {@code null}.
*/
public static OperationMode randomMode() {
return randomFrom(OperationMode.values());
}
/**
* Get any {@link #randomMode() mode}, except the selected {@code mode}.
*
* @param mode The mode to exclude.
* @return Never {@code null}.
*/
public static OperationMode randomModeExcept(OperationMode mode) {
return randomValueOtherThan(mode, AbstractLicenseeTestCase::randomMode);
}
/**
* Get a random value from the {@code values} that passes {@code filter}.
*
* @param values The values to filter and randomly select from
* @param filter The filter to apply
* @return Never {@code null}.
* @throws IllegalArgumentException if nothing matches the {@code filter}
* @see #randomFrom(Object[])
*/
public static <T> T randomFrom(T[] values, Predicate<T> filter) {
return randomFrom(Arrays.stream(values).filter(filter).collect(Collectors.toList()));
}
/**
* Get a message to show with assertions for license transition.
*
* @param fromMode Coming "from" mode
* @param toMode Going "to" mode
* @return Never {@code null}.
*/
public static String fromToMessage(OperationMode fromMode, OperationMode toMode) {
return String.format(Locale.ROOT, "From [%s] to [%s]", fromMode, toMode);
}
private OperationMode operationMode;
public void setOperationMode(Licensee licensee, OperationMode operationMode) {
this.operationMode = operationMode;
enable(licensee);
}
public void disable(Licensee licensee) {
licensee.onChange(new Licensee.Status(operationMode, false));
}
public void enable(Licensee licensee) {
licensee.onChange(new Licensee.Status(operationMode, true));
}
}

View File

@ -16,7 +16,6 @@ import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.common.transport.LocalTransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
@ -31,12 +30,12 @@ import static org.mockito.Mockito.when;
public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
private TestUtils.AssertingLicensee licensee;
private TestUtils.AssertingLicenseState licenseState;
@Before
public void setup() {
licensee = new TestUtils.AssertingLicensee("LicenseClusterChangeTests", logger);
setInitialState(null, licensee);
licenseState = new TestUtils.AssertingLicenseState();
setInitialState(null, licenseState);
licenseService.start();
}
@ -52,8 +51,8 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
MetaData metaData = MetaData.builder().putCustom(LicensesMetaData.TYPE, new LicensesMetaData(license)).build();
ClusterState newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
assertThat(licensee.statuses.size(), equalTo(1));
assertTrue(licensee.statuses.get(0).isActive());
assertThat(licenseState.activeUpdates.size(), equalTo(1));
assertTrue(licenseState.activeUpdates.get(0));
}
public void testNoNotificationOnExistingLicense() throws Exception {
@ -62,7 +61,7 @@ public class LicenseClusterChangeTests extends AbstractLicenseServiceTestCase {
ClusterState newState = ClusterState.builder(new ClusterName("a")).metaData(metaData).build();
ClusterState oldState = ClusterState.builder(newState).build();
licenseService.clusterChanged(new ClusterChangedEvent("simulated", newState, oldState));
assertThat(licensee.statuses.size(), equalTo(0));
assertThat(licenseState.activeUpdates.size(), equalTo(0));
}
public void testTrialLicenseGeneration() throws Exception {

View File

@ -9,7 +9,6 @@ import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.ClusterStateUpdateTask;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.plugin.TestUtils;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@ -21,9 +20,8 @@ import static org.mockito.Mockito.when;
public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
public void testTrialLicenseRequestOnEmptyLicenseState() throws Exception {
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(
"testTrialLicenseRequestOnEmptyLicenseState", logger);
setInitialState(null, licensee);
XPackLicenseState licenseState = new XPackLicenseState();
setInitialState(null, licenseState);
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(true);
licenseService.start();
@ -36,13 +34,4 @@ public class LicenseRegistrationTests extends AbstractLicenseServiceTestCase {
assertNotNull(licenseMetaData.getLicense());
assertEquals(clock.millis() + LicenseService.TRIAL_LICENSE_DURATION.millis(), licenseMetaData.getLicense().expiryDate());
}
public void testNotificationOnRegistration() throws Exception {
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(
"testNotificationOnRegistration", logger);
setInitialState(TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)), licensee);
licenseService.start();
assertThat(licensee.statuses.size(), equalTo(1));
assertTrue(licensee.statuses.get(0).isActive());
}
}

View File

@ -7,7 +7,6 @@ package org.elasticsearch.license.plugin.core;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.TestUtils;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.scheduler.SchedulerEngine;
import org.junit.Before;

View File

@ -3,14 +3,15 @@
* 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.license.plugin;
package org.elasticsearch.license.plugin.core;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.AbstractLicensesIntegrationTestCase;
import org.elasticsearch.license.plugin.LicensingClient;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.xpack.MockNetty3Plugin;
@ -22,13 +23,13 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateSignedLicense;
import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0)
public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTestCase {
public class LicenseServiceClusterTests extends AbstractLicensesIntegrationTestCase {
@Override
protected Settings transportClientSettings() {
@ -123,40 +124,40 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
wipeAllLicenses();
internalCluster().startNode();
ensureGreen();
assertLicenseState(true);
assertLicenseActive(true);
logger.info("--> restart node");
internalCluster().fullRestart();
ensureYellow();
logger.info("--> await node for enabled");
assertLicenseState(true);
assertLicenseActive(true);
}
public void testClusterRestartWhileGrace() throws Exception {
wipeAllLicenses();
internalCluster().startNode();
assertLicenseState(true);
assertLicenseActive(true);
putLicense(TestUtils.generateSignedLicense(TimeValue.timeValueMillis(0)));
ensureGreen();
assertLicenseState(true);
assertLicenseActive(true);
logger.info("--> restart node");
internalCluster().fullRestart();
ensureYellow();
logger.info("--> await node for grace_period");
assertLicenseState(true);
assertLicenseActive(true);
}
public void testClusterRestartWhileExpired() throws Exception {
wipeAllLicenses();
internalCluster().startNode();
ensureGreen();
assertLicenseState(true);
assertLicenseActive(true);
putLicense(TestUtils.generateExpiredLicense(System.currentTimeMillis() - LicenseService.GRACE_PERIOD_DURATION.getMillis()));
assertLicenseState(false);
assertLicenseActive(false);
logger.info("--> restart node");
internalCluster().fullRestart();
ensureYellow();
logger.info("--> await node for disabled");
assertLicenseState(false);
assertLicenseActive(false);
}
public void testClusterNotRecovered() throws Exception {
@ -164,13 +165,13 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
internalCluster().startNode(nodeSettingsBuilder(0).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true));
logger.info("--> start second master out of two [recovered state]");
internalCluster().startNode(nodeSettingsBuilder(1).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true));
assertLicenseState(true);
assertLicenseActive(true);
}
private void assertLicenseState(boolean active) throws InterruptedException {
private void assertLicenseActive(boolean active) throws InterruptedException {
boolean success = awaitBusy(() -> {
for (LicenseService service : internalCluster().getDataNodeInstances(LicenseService.class)) {
if (service.licenseeStatus(service.getLicense()).isActive() == active) {
for (XPackLicenseState licenseState : internalCluster().getDataNodeInstances(XPackLicenseState.class)) {
if (licenseState.isActive() == active) {
return true;
}
}
@ -181,8 +182,8 @@ public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTest
private void assertOperationMode(License.OperationMode operationMode) throws InterruptedException {
boolean success = awaitBusy(() -> {
for (LicenseService service : internalCluster().getDataNodeInstances(LicenseService.class)) {
if (service.licenseeStatus(service.getLicense()).getMode() == operationMode) {
for (XPackLicenseState licenseState : internalCluster().getDataNodeInstances(XPackLicenseState.class)) {
if (licenseState.getOperationMode() == operationMode) {
return true;
}
}

View File

@ -5,19 +5,14 @@
*/
package org.elasticsearch.license.plugin.core;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.ClusterStateUpdateTask;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.TestUtils;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateSignedLicense;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.mockito.Matchers.any;
@ -28,93 +23,40 @@ public class LicensesAcknowledgementTests extends AbstractLicenseServiceTestCase
public void testAcknowledgment() throws Exception {
String id = "testAcknowledgment";
String[] acknowledgeMessages = new String[] {"message"};
TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(id, logger);
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licensee);
licenseService.start();
licensee.setAcknowledgementMessages(acknowledgeMessages);
// try installing a signed license
License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10));
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
// ensure acknowledgement message was part of the response
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID,
Collections.singletonMap(id, acknowledgeMessages)));
assertThat(licensee.acknowledgementRequested.size(), equalTo(1));
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
assertThat(licenseService.getLicense(), not(signedLicense));
// try installing a signed license with acknowledgement
putLicenseRequest = new PutLicenseRequest().license(signedLicense).acknowledge(true);
// ensure license was installed and no acknowledgment message was returned
licensee.setAcknowledgementMessages(new String[0]);
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID,
Collections.<String, String[]>emptyMap()));
verify(clusterService, times(1)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
assertThat(licensee.acknowledgementRequested.size(), equalTo(1));
assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
}
public void testAcknowledgementMultipleLicensee() throws Exception {
String id1 = "testAcknowledgementMultipleLicensee_1";
String[] acknowledgeMessages1 = new String[] {"testAcknowledgementMultipleLicensee_1"};
String id2 = "testAcknowledgementMultipleLicensee_2";
String[] acknowledgeMessages2 = new String[] {"testAcknowledgementMultipleLicensee_2"};
TestUtils.AssertingLicensee licensee1 = new TestUtils.AssertingLicensee(id1, logger);
licensee1.setAcknowledgementMessages(acknowledgeMessages1);
TestUtils.AssertingLicensee licensee2 = new TestUtils.AssertingLicensee(id2, logger);
licensee2.setAcknowledgementMessages(acknowledgeMessages2);
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licensee1, licensee2);
XPackLicenseState licenseState = new XPackLicenseState();
setInitialState(TestUtils.generateSignedLicense("trial", TimeValue.timeValueHours(2)), licenseState);
licenseService.start();
// try installing a signed license
License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10));
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense);
// ensure acknowledgement message was part of the response
final HashMap<String, String[]> expectedMessages = new HashMap<>();
expectedMessages.put(id1, acknowledgeMessages1);
expectedMessages.put(id2, acknowledgeMessages2);
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID,
expectedMessages));
verify(clusterService, times(0)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
assertThat(licensee2.acknowledgementRequested.size(), equalTo(1));
assertThat(licensee2.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
assertThat(licensee1.acknowledgementRequested.size(), equalTo(1));
assertThat(licensee1.acknowledgementRequested.get(0).v2(), equalTo(signedLicense.operationMode()));
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, true));
assertThat(licenseService.getLicense(), not(signedLicense));
// try installing a signed license with acknowledgement
putLicenseRequest = new PutLicenseRequest().license(signedLicense).acknowledge(true);
// ensure license was installed and no acknowledgment message was returned
licensee1.setAcknowledgementMessages(new String[0]);
licensee2.setAcknowledgementMessages(new String[0]);
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID,
Collections.<String, String[]>emptyMap()));
verify(clusterService, times(1)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
licenseService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID, false));
verify(clusterService, times(2)).submitStateUpdateTask(any(String.class), any(ClusterStateUpdateTask.class));
}
private static class AssertingLicensesUpdateResponse implements ActionListener<PutLicenseResponse> {
private final boolean expectedAcknowledgement;
private final LicensesStatus expectedStatus;
private final Map<String, String[]> expectedAckMessages;
private final boolean expectAckMessages;
public AssertingLicensesUpdateResponse(boolean expectedAcknowledgement, LicensesStatus expectedStatus,
Map<String, String[]> expectedAckMessages) {
boolean expectAckMessages) {
this.expectedAcknowledgement = expectedAcknowledgement;
this.expectedStatus = expectedStatus;
this.expectedAckMessages = expectedAckMessages;
this.expectAckMessages = expectAckMessages;
}
@Override
public void onResponse(PutLicenseResponse licensesUpdateResponse) {
assertThat(licensesUpdateResponse.isAcknowledged(), equalTo(expectedAcknowledgement));
assertThat(licensesUpdateResponse.status(), equalTo(expectedStatus));
assertThat(licensesUpdateResponse.acknowledgeMessages().size(), equalTo(expectedAckMessages.size()));
for (Map.Entry<String, String[]> expectedEntry : expectedAckMessages.entrySet()) {
Map<String, String[]> actual = licensesUpdateResponse.acknowledgeMessages();
assertThat(actual.containsKey(expectedEntry.getKey()), equalTo(true));
String[] actualMessages = actual.get(expectedEntry.getKey());
assertThat(actualMessages, equalTo(expectedEntry.getValue()));
}
assertEquals(licensesUpdateResponse.acknowledgeMessages().isEmpty(), expectAckMessages == false);
}
@Override

View File

@ -16,7 +16,6 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.TestUtils;
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase;
@ -26,7 +25,7 @@ import org.elasticsearch.xpack.monitoring.Monitoring;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.watcher.Watcher;
import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense;
import static org.elasticsearch.license.plugin.core.TestUtils.generateSignedLicense;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;

View File

@ -22,7 +22,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.Licensing;
import org.elasticsearch.license.plugin.TestUtils;
import org.elasticsearch.test.ESTestCase;
import java.util.Base64;

View File

@ -1,91 +0,0 @@
/*
* 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.license.plugin.core;
import java.util.List;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.TestUtils;
import org.elasticsearch.license.plugin.TestUtils.AssertingLicensee;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import static org.hamcrest.Matchers.equalTo;
public class LicensesNotificationTests extends AbstractLicenseServiceTestCase {
public void testLicenseNotification() throws Exception {
final License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(48));
int nLicensee = randomIntBetween(1, 3);
AssertingLicensee[] assertingLicensees = new AssertingLicensee[nLicensee];
for (int i = 0; i < assertingLicensees.length; i++) {
assertingLicensees[i] = new AssertingLicensee("testLicenseNotification" + i, logger);
}
setInitialState(license, assertingLicensees);
licenseService.start();
for (int i = 0; i < assertingLicensees.length; i++) {
assertLicenseStates(assertingLicensees[i], true);
}
clock.fastForward(TimeValue.timeValueMillis(license.expiryDate() - clock.millis()));
final LicensesMetaData licensesMetaData = new LicensesMetaData(license);
licenseService.onUpdate(licensesMetaData);
for (AssertingLicensee assertingLicensee : assertingLicensees) {
assertLicenseStates(assertingLicensee, true);
}
clock.fastForward(TimeValue.timeValueMillis((license.expiryDate() +
LicenseService.GRACE_PERIOD_DURATION.getMillis()) - clock.millis()));
licenseService.onUpdate(licensesMetaData);
for (AssertingLicensee assertingLicensee : assertingLicensees) {
assertLicenseStates(assertingLicensee, true, false);
}
clock.setTime(new DateTime(DateTimeZone.UTC));
final License newLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2));
clock.fastForward(TimeValue.timeValueHours(1));
LicensesMetaData licensesMetaData1 = new LicensesMetaData(newLicense);
licenseService.onUpdate(licensesMetaData1);
for (AssertingLicensee assertingLicensee : assertingLicensees) {
assertLicenseStates(assertingLicensee, true, false, true);
}
}
private void assertLicenseStates(AssertingLicensee licensee, boolean... states) {
StringBuilder msg = new StringBuilder();
msg.append("Actual: ");
msg.append(dumpLicensingStates(licensee.statuses));
msg.append(" Expected: ");
msg.append(dumpLicensingStates(states));
assertThat(msg.toString(), licensee.statuses.size(), equalTo(states.length));
for (int i = 0; i < states.length; i++) {
assertThat(msg.toString(), licensee.statuses.get(i).isActive(), equalTo(states[i]));
}
}
private String dumpLicensingStates(List<Licensee.Status> statuses) {
return dumpLicensingStates(statuses.toArray(new Licensee.Status[statuses.size()]));
}
private String dumpLicensingStates(Licensee.Status... statuses) {
boolean[] states = new boolean[statuses.length];
for (int i = 0; i < statuses.length; i++) {
states[i] = statuses[i].isActive();
}
return dumpLicensingStates(states);
}
private String dumpLicensingStates(boolean... states) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < states.length; i++) {
sb.append(states[i]);
if (i != states.length - 1) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}

View File

@ -3,7 +3,7 @@
* 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.license.plugin;
package org.elasticsearch.license.plugin.core;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.collect.Tuple;
@ -21,12 +21,10 @@ import org.elasticsearch.license.core.License;
import org.elasticsearch.license.licensor.LicenseSigner;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.Licensee;
import org.elasticsearch.license.plugin.core.LicensesStatus;
import org.junit.Assert;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
@ -171,44 +169,14 @@ public class TestUtils {
assertThat(status.get(), equalTo(expectedStatus));
}
public static class AssertingLicensee implements Licensee {
public final ESLogger logger;
public final String id;
public final List<Licensee.Status> statuses = new CopyOnWriteArrayList<>();
public final AtomicInteger expirationMessagesCalled = new AtomicInteger(0);
public final List<Tuple<License.OperationMode, License.OperationMode>> acknowledgementRequested = new CopyOnWriteArrayList<>();
private String[] acknowledgmentMessages = new String[0];
public AssertingLicensee(String id, ESLogger logger) {
this.logger = logger;
this.id = id;
}
public void setAcknowledgementMessages(String[] acknowledgementMessages) {
this.acknowledgmentMessages = acknowledgementMessages;
}
@Override
public String id() {
return id;
}
public static class AssertingLicenseState extends XPackLicenseState {
public final List<License.OperationMode> modeUpdates = new ArrayList<>();
public final List<Boolean> activeUpdates = new ArrayList<>();
@Override
public String[] expirationMessages() {
expirationMessagesCalled.incrementAndGet();
return new String[0];
}
@Override
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
acknowledgementRequested.add(new Tuple<>(currentMode, newMode));
return acknowledgmentMessages;
}
@Override
public void onChange(Status status) {
assertNotNull(status);
statuses.add(status);
void update(License.OperationMode mode, boolean active) {
modeUpdates.add(mode);
activeUpdates.add(active);
}
}
}

View File

@ -12,6 +12,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.XPackFeatureSet;
import org.elasticsearch.xpack.monitoring.agent.exporter.Exporter;
import org.elasticsearch.xpack.monitoring.agent.exporter.Exporters;
@ -26,14 +27,14 @@ import java.util.Map;
public class MonitoringFeatureSet implements XPackFeatureSet {
private final boolean enabled;
private final MonitoringLicensee licensee;
private final XPackLicenseState licenseState;
private final Exporters exporters;
@Inject
public MonitoringFeatureSet(Settings settings, @Nullable MonitoringLicensee licensee, @Nullable Exporters exporters,
public MonitoringFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, @Nullable Exporters exporters,
NamedWriteableRegistry namedWriteableRegistry) {
this.enabled = MonitoringSettings.ENABLED.get(settings);
this.licensee = licensee;
this.licenseState = licenseState;
this.exporters = exporters;
namedWriteableRegistry.register(Usage.class, Usage.writeableName(Monitoring.NAME), Usage::new);
}
@ -50,7 +51,7 @@ public class MonitoringFeatureSet implements XPackFeatureSet {
@Override
public boolean available() {
return licensee != null && licensee.isAvailable();
return licenseState != null && licenseState.isMonitoringAllowed();
}
@Override

View File

@ -1,116 +0,0 @@
/*
* 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.xpack.monitoring;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
/**
* {@code MonitoringLicensee} determines whether certain features of Monitoring are enabled or disabled.
* <p>
* Once the license expires, the agent will stop:
* <ul>
* <li>Collecting and publishing new metrics.</li>
* <li>Cleaning up (deleting) older indices.</li>
* </ul>
*/
public class MonitoringLicensee extends AbstractLicenseeComponent {
public MonitoringLicensee(Settings settings) {
super(settings, Monitoring.NAME);
}
/**
* {@inheritDoc}
*
* @see #collectionEnabled()
* @see #cleaningEnabled()
*/
@Override
public String[] expirationMessages() {
return new String[] {
"The agent will stop collecting cluster and indices metrics",
"The agent will stop automatically cleaning indices older than [xpack.monitoring.history.duration]",
};
}
@Override
public String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] {
LoggerMessageFormat.format(
"Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
"running multiple clusters, users won't be able to access the clusters with\n" +
"[{}] licenses from within a single X-Pack Kibana instance. You will have to deploy a\n" +
"separate and dedicated X-pack Kibana instance for each [{}] cluster you wish to monitor.",
newMode, newMode, newMode),
LoggerMessageFormat.format(
"Automatic index cleanup is locked to {} days for clusters with [{}] license.",
MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newMode)
};
}
break;
}
return Strings.EMPTY_ARRAY;
}
/**
* Monitoring is always available as long as there is a valid license
*
* @return true
*/
public boolean isAvailable() {
return status.isActive();
}
/**
* Determine if the index cleaning service is enabled.
* <p>
* Collection is only disabled <em>automatically</em> when the license expires. All modes are valid for collection.
* <p>
* Collection <em>can</em> be disabled explicitly by the user, although that's generally a temporary solution to unrelated issues
* (e.g., initial setup when the monitoring cluster doesn't actually exist).
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean collectionEnabled() {
return status.isActive();
}
/**
* Determine if the index cleaning service is enabled.
* <p>
* Index cleaning is only disabled when the license expires. All modes are valid for cleaning.
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean cleaningEnabled() {
return status.isActive();
}
/**
* Determine if the current license allows the retention of indices to be modified.
* <p>
* Only users with a non-{@link OperationMode#BASIC} license can update the retention period.
* <p>
* Note: This does not consider the <em>state</em> of the license so that any change is remembered for when they fix their license.
*
* @return {@code true} if the user is allowed to modify the retention. Otherwise {@code false}.
*/
public boolean allowUpdateRetention() {
final OperationMode mode = status.getMode();
return mode != OperationMode.BASIC && mode != OperationMode.MISSING;
}
}

View File

@ -29,8 +29,6 @@ public class MonitoringModule extends AbstractModule {
bind(MonitoringSettings.class).asEagerSingleton();
bind(AgentService.class).asEagerSingleton();
bind(CleanerService.class).asEagerSingleton();
} else if (transportClientMode) {
bind(MonitoringLicensee.class).toProvider(Providers.of(null));
}
}
}

View File

@ -12,8 +12,8 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -25,16 +25,16 @@ public abstract class AbstractCollector extends AbstractLifecycleComponent imple
protected final ClusterService clusterService;
protected final MonitoringSettings monitoringSettings;
protected final MonitoringLicensee licensee;
protected final XPackLicenseState licenseState;
@Inject
public AbstractCollector(Settings settings, String name, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee) {
MonitoringSettings monitoringSettings, XPackLicenseState licenseState) {
super(settings);
this.name = name;
this.clusterService = clusterService;
this.monitoringSettings = monitoringSettings;
this.licensee = licensee;
this.licenseState = licenseState;
}
@Override
@ -61,7 +61,7 @@ public abstract class AbstractCollector extends AbstractLifecycleComponent imple
* Indicates if the current collector is allowed to collect data
*/
protected boolean shouldCollect() {
if (!licensee.collectionEnabled()) {
if (licenseState.isMonitoringAllowed() == false) {
logger.trace("collector [{}] can not collect data due to invalid license", name());
return false;
}

View File

@ -13,7 +13,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -38,8 +38,8 @@ public class ClusterStateCollector extends AbstractCollector {
@Inject
public ClusterStateCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
MonitoringSettings monitoringSettings, XPackLicenseState licenseState, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
}

View File

@ -13,9 +13,9 @@ import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -45,9 +45,9 @@ public class ClusterStatsCollector extends AbstractCollector {
@Inject
public ClusterStatsCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client,
MonitoringSettings monitoringSettings, XPackLicenseState licenseState, InternalClient client,
LicenseService licenseService) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
this.licenseService = licenseService;
}

View File

@ -13,7 +13,7 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -40,8 +40,8 @@ public class IndexRecoveryCollector extends AbstractCollector {
@Inject
public IndexRecoveryCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
MonitoringSettings monitoringSettings, XPackLicenseState licenseState, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
}

View File

@ -15,7 +15,7 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -42,8 +42,8 @@ public class IndexStatsCollector extends AbstractCollector {
@Inject
public IndexStatsCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
MonitoringSettings monitoringSettings, XPackLicenseState licenseState, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
}

View File

@ -13,7 +13,7 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -37,8 +37,8 @@ public class IndicesStatsCollector extends AbstractCollector {
@Inject
public IndicesStatsCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
MonitoringSettings monitoringSettings, XPackLicenseState licenseState, InternalClient client) {
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
}

View File

@ -17,7 +17,7 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -43,9 +43,9 @@ public class NodeStatsCollector extends AbstractCollector {
@Inject
public NodeStatsCollector(Settings settings, ClusterService clusterService, MonitoringSettings monitoringSettings,
MonitoringLicensee licensee, InternalClient client,
XPackLicenseState licenseState, InternalClient client,
NodeEnvironment nodeEnvironment, DiskThresholdDecider diskThresholdDecider) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
super(settings, NAME, clusterService, monitoringSettings, licenseState);
this.client = client;
this.nodeEnvironment = nodeEnvironment;
this.diskThresholdDecider = diskThresholdDecider;

View File

@ -13,7 +13,7 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -36,8 +36,8 @@ public class ShardsCollector extends AbstractCollector {
@Inject
public ShardsCollector(Settings settings, ClusterService clusterService,
MonitoringSettings monitoringSettings, MonitoringLicensee licensee) {
super(settings, NAME, clusterService, monitoringSettings, licensee);
MonitoringSettings monitoringSettings, XPackLicenseState licenseState) {
super(settings, NAME, clusterService, monitoringSettings, licenseState);
}
@Override

View File

@ -13,8 +13,8 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.AbstractLifecycleRunnable;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.joda.time.DateTime;
import org.joda.time.chrono.ISOChronology;
@ -28,7 +28,7 @@ import java.util.concurrent.ScheduledFuture;
*/
public class CleanerService extends AbstractLifecycleComponent {
private final MonitoringLicensee licensee;
private final XPackLicenseState licenseState;
private final ThreadPool threadPool;
private final ExecutionScheduler executionScheduler;
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
@ -36,10 +36,10 @@ public class CleanerService extends AbstractLifecycleComponent {
private volatile TimeValue globalRetention;
CleanerService(Settings settings, ClusterSettings clusterSettings, MonitoringLicensee licensee, ThreadPool threadPool,
CleanerService(Settings settings, ClusterSettings clusterSettings, XPackLicenseState licenseState, ThreadPool threadPool,
ExecutionScheduler executionScheduler) {
super(settings);
this.licensee = licensee;
this.licenseState = licenseState;
this.threadPool = threadPool;
this.executionScheduler = executionScheduler;
this.globalRetention = MonitoringSettings.HISTORY_DURATION.get(settings);
@ -50,8 +50,8 @@ public class CleanerService extends AbstractLifecycleComponent {
}
@Inject
public CleanerService(Settings settings, ClusterSettings clusterSettings, ThreadPool threadPool, MonitoringLicensee licensee) {
this(settings, clusterSettings, licensee,threadPool, new DefaultExecutionScheduler());
public CleanerService(Settings settings, ClusterSettings clusterSettings, ThreadPool threadPool, XPackLicenseState licenseState) {
this(settings, clusterSettings, licenseState, threadPool, new DefaultExecutionScheduler());
}
@Override
@ -85,11 +85,11 @@ public class CleanerService extends AbstractLifecycleComponent {
* This will ignore the global retention if the license does not allow retention updates.
*
* @return Never {@code null}
* @see MonitoringLicensee#allowUpdateRetention()
* @see XPackLicenseState#isUpdateRetentionAllowed()
*/
public TimeValue getRetention() {
// we only care about their value if they are allowed to set it
if (licensee.allowUpdateRetention() && globalRetention != null) {
if (licenseState.isUpdateRetentionAllowed() && globalRetention != null) {
return globalRetention;
}
else {
@ -107,7 +107,7 @@ public class CleanerService extends AbstractLifecycleComponent {
*/
public void setGlobalRetention(TimeValue globalRetention) {
// notify the user that their setting will be ignored until they get the right license
if (licensee.allowUpdateRetention() == false) {
if (licenseState.isUpdateRetentionAllowed() == false) {
logger.warn("[{}] setting will be ignored until an appropriate license is applied",
MonitoringSettings.HISTORY_DURATION.getKey());
}
@ -165,7 +165,7 @@ public class CleanerService extends AbstractLifecycleComponent {
@Override
protected void doRunInLifecycle() throws Exception {
if (licensee.cleaningEnabled() == false) {
if (licenseState.isMonitoringAllowed() == false) {
logger.debug("cleaning service is disabled due to invalid license");
return;
}

View File

@ -7,6 +7,7 @@ package org.elasticsearch.xpack.monitoring;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.XPackFeatureSet;
import org.elasticsearch.xpack.monitoring.agent.exporter.Exporter;
@ -33,26 +34,26 @@ import static org.mockito.Mockito.when;
*/
public class MonitoringFeatureSetTests extends ESTestCase {
private MonitoringLicensee licensee;
private XPackLicenseState licenseState;
private NamedWriteableRegistry namedWriteableRegistry;
private Exporters exporters;
@Before
public void init() throws Exception {
licensee = mock(MonitoringLicensee.class);
licenseState = mock(XPackLicenseState.class);
exporters = mock(Exporters.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
}
public void testWritableRegistration() throws Exception {
new MonitoringFeatureSet(Settings.EMPTY, licensee, exporters, namedWriteableRegistry);
new MonitoringFeatureSet(Settings.EMPTY, licenseState, exporters, namedWriteableRegistry);
verify(namedWriteableRegistry).register(eq(MonitoringFeatureSet.Usage.class), eq("xpack.usage.monitoring"), anyObject());
}
public void testAvailable() throws Exception {
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licensee, exporters, namedWriteableRegistry);
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licenseState, exporters, namedWriteableRegistry);
boolean available = randomBoolean();
when(licensee.isAvailable()).thenReturn(available);
when(licenseState.isMonitoringAllowed()).thenReturn(available);
assertThat(featureSet.available(), is(available));
}
@ -60,12 +61,12 @@ public class MonitoringFeatureSetTests extends ESTestCase {
boolean enabled = randomBoolean();
Settings.Builder settings = Settings.builder();
settings.put("xpack.monitoring.enabled", enabled);
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(settings.build(), licensee, exporters, namedWriteableRegistry);
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(settings.build(), licenseState, exporters, namedWriteableRegistry);
assertThat(featureSet.enabled(), is(enabled));
}
public void testEnabledDefault() throws Exception {
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licensee, exporters, namedWriteableRegistry);
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licenseState, exporters, namedWriteableRegistry);
assertThat(featureSet.enabled(), is(true));
}
@ -102,7 +103,7 @@ public class MonitoringFeatureSetTests extends ESTestCase {
}
when(exporters.iterator()).thenReturn(exporterList.iterator());
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licensee, exporters, namedWriteableRegistry);
MonitoringFeatureSet featureSet = new MonitoringFeatureSet(Settings.EMPTY, licenseState, exporters, namedWriteableRegistry);
XPackFeatureSet.Usage usage = featureSet.usage();
assertThat(usage.name(), is(featureSet.name()));
assertThat(usage.enabled(), is(featureSet.enabled()));

View File

@ -5,55 +5,20 @@
*/
package org.elasticsearch.xpack.monitoring.agent.collector;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.carrotsearch.randomizedtesting.RandomizedTest;
import com.carrotsearch.randomizedtesting.SysGlobals;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.cluster.block.ClusterBlocks;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.Licensing;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.Licensee;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
import org.elasticsearch.xpack.security.InternalClient;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.junit.Before;
import static java.util.Collections.emptyList;
import static org.elasticsearch.common.unit.TimeValue.timeValueMinutes;
@ClusterScope(scope = ESIntegTestCase.Scope.SUITE, randomDynamicTemplates = false, transportClientRatio = 0.0)
public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(InternalXPackPlugin.class);
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
@ -62,11 +27,6 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
.build();
}
@Before
public void ensureLicenseIsEnabled() {
enableLicense();
}
public InternalClient securedClient() {
return internalCluster().getInstance(InternalClient.class);
}
@ -82,83 +42,6 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
assertNotNull(results);
}
protected void assertCannotCollect(AbstractCollector collector) {
assertNotNull(collector);
assertFalse("collector [" + collector.name() + "] should not be able to collect data", collector.shouldCollect());
Collection results = collector.collect();
assertTrue(results == null || results.isEmpty());
}
private static License createTestingLicense(long issueDate, long expiryDate) {
return License.builder()
.expiryDate(expiryDate)
.issueDate(issueDate)
.issuedTo("AbstractCollectorTestCase")
.issuer("test")
.maxNodes(Integer.MAX_VALUE)
.signature("_signature")
.type("trial")
.uid(String.valueOf(RandomizedTest.systemPropertyAsInt(SysGlobals.CHILDVM_SYSPROP_JVM_ID, 0)) +
System.identityHashCode(AbstractCollectorTestCase.class))
.build();
}
protected static void enableLicense() {
long issueDate = System.currentTimeMillis();
long expiryDate = issueDate + randomDaysInMillis();
final License license = createTestingLicense(issueDate, expiryDate);
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.onChange(license.operationMode(), true);
}
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.update(license);
}
}
protected static void beginGracefulPeriod() {
long expiryDate = System.currentTimeMillis() + timeValueMinutes(10).millis();
long issueDate = expiryDate - randomDaysInMillis();
final License license = createTestingLicense(issueDate, expiryDate);
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.onChange(license.operationMode(), true);
}
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.update(license);
}
}
protected static void endGracefulPeriod() {
long expiryDate = System.currentTimeMillis() - MonitoringSettings.MAX_LICENSE_GRACE_PERIOD.millis() - timeValueMinutes(10).millis();
long issueDate = expiryDate - randomDaysInMillis();
final License license = createTestingLicense(issueDate, expiryDate);
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.onChange(license.operationMode(), false);
}
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.update(license);
}
}
protected static void disableLicense() {
long expiryDate = System.currentTimeMillis() - MonitoringSettings.MAX_LICENSE_GRACE_PERIOD.millis() - randomDaysInMillis();
long issueDate = expiryDate - randomDaysInMillis();
final License license = createTestingLicense(issueDate, expiryDate);
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.onChange(license.operationMode(), false);
}
for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) {
service.update(license);
}
}
private static long randomDaysInMillis() {
return TimeValue.timeValueHours(randomIntBetween(1, 30) * 24).millis();
}
public void waitForNoBlocksOnNodes() throws Exception {
assertBusy(new Runnable() {
@Override
@ -182,85 +65,4 @@ public abstract class AbstractCollectorTestCase extends MonitoringIntegTestCase
assertTrue(clusterBlocks.indices().values().isEmpty());
}, 30L, TimeUnit.SECONDS);
}
public static class InternalLicensing extends Licensing {
public InternalLicensing() {
super(Settings.EMPTY);
}
@Override
public Collection<Module> nodeModules() {
return Collections.singletonList(b -> b.bind(LicenseService.class).to(LicenseServiceForCollectors.class));
}
@Override
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
ResourceWatcherService resourceWatcherService,
SecurityLicenseState securityLicenseState) {
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
GraphLicensee graphLicensee = new GraphLicensee(settings);
LicenseService licenseService = new LicenseServiceForCollectors(settings, environment,
resourceWatcherService, Arrays.asList(watcherLicensee, monitoringLicensee, graphLicensee));
return Arrays.asList(licenseService, watcherLicensee, monitoringLicensee, graphLicensee);
}
@Override
public List<ActionHandler<? extends ActionRequest<?>, ? extends ActionResponse>> getActions() {
return emptyList();
}
@Override
public List<Class<? extends RestHandler>> getRestHandlers() {
return emptyList();
}
}
public static class InternalXPackPlugin extends XPackPlugin {
public InternalXPackPlugin(Settings settings) throws IOException {
super(settings);
licensing = new InternalLicensing();
}
}
public static class LicenseServiceForCollectors extends LicenseService {
private final List<Licensee> licensees;
private volatile License license;
@Inject
public LicenseServiceForCollectors(Settings settings, Environment env,
ResourceWatcherService resourceWatcherService, List<Licensee> licensees) {
super(settings, null, null, env, resourceWatcherService, licensees);
this.licensees = licensees;
}
public void onChange(License.OperationMode operationMode, boolean active) {
for (Licensee licensee : licensees) {
licensee.onChange(new Licensee.Status(operationMode, active));
}
}
@Override
public Licensee.Status licenseeStatus(License license) {
return null;
}
@Override
public License getLicense() {
return license;
}
public synchronized void update(License license) {
this.license = license;
}
@Override
protected void doStart() {}
@Override
protected void doStop() {}
}
}

View File

@ -10,8 +10,8 @@ import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -106,44 +106,6 @@ public class ClusterStateCollectorTests extends AbstractCollectorTestCase {
}
}
public void testClusterStateCollectorWithLicensing() {
try {
String[] nodes = internalCluster().getNodeNames();
for (String node : nodes) {
logger.debug("--> creating a new instance of the collector");
ClusterStateCollector collector = newClusterStateCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private ClusterStateCollector newClusterStateCollector() {
// This collector runs on master node only
return newClusterStateCollector(internalCluster().getMasterName());
@ -154,7 +116,7 @@ public class ClusterStateCollectorTests extends AbstractCollectorTestCase {
return new ClusterStateCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
securedClient(nodeId));
}

View File

@ -12,8 +12,8 @@ import org.elasticsearch.Version;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollector;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
@ -75,52 +75,6 @@ public class ClusterStatsCollectorTests extends AbstractCollectorTestCase {
equalTo(internalCluster().getNodeNames().length));
}
public void testClusterStatsCollectorWithLicensing() {
try {
String[] nodes = internalCluster().getNodeNames();
for (String node : nodes) {
logger.debug("--> creating a new instance of the collector");
ClusterStatsCollector collector = newClusterStatsCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector, ClusterInfoMonitoringDoc.class, ClusterStatsMonitoringDoc.class);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector, ClusterInfoMonitoringDoc.class, ClusterStatsMonitoringDoc.class);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector can still collect data (if node is master)");
endGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector, ClusterInfoMonitoringDoc.class);
} else {
assertCannotCollect(collector);
}
logger.debug("--> disabling license and checks that the collector can still collect data (if node is master)");
disableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector, ClusterInfoMonitoringDoc.class);
} else {
assertCannotCollect(collector);
}
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private ClusterStatsCollector newClusterStatsCollector() {
// This collector runs on master node only
return newClusterStatsCollector(internalCluster().getMasterName());
@ -131,7 +85,7 @@ public class ClusterStatsCollectorTests extends AbstractCollectorTestCase {
return new ClusterStatsCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
securedClient(nodeId),
internalCluster().getInstance(LicenseService.class, nodeId));
}

View File

@ -13,10 +13,10 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.indices.recovery.RecoveryState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -130,46 +130,6 @@ public class IndexRecoveryCollectorTests extends AbstractCollectorTestCase {
}
}
public void testIndexRecoveryCollectorWithLicensing() throws Exception {
List<String> nodesIds = internalCluster().startNodesAsync(randomIntBetween(2, 5)).get();
waitForNoBlocksOnNodes();
try {
for (String node : nodesIds) {
logger.debug("--> creating a new instance of the collector");
IndexRecoveryCollector collector = newIndexRecoveryCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
public void testEmptyCluster() throws Exception {
final String node = internalCluster().startNode(Settings.builder().put(MonitoringSettings.INDICES.getKey(),
Strings.EMPTY_ARRAY));
@ -211,7 +171,7 @@ public class IndexRecoveryCollectorTests extends AbstractCollectorTestCase {
return new IndexRecoveryCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
securedClient(nodeId));
}
}

View File

@ -11,9 +11,9 @@ import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -181,55 +181,6 @@ public class IndexStatsCollectorTests extends AbstractCollectorTestCase {
}
}
public void testIndexStatsCollectorWithLicensing() throws Exception {
List<String> nodesIds = internalCluster().startNodesAsync(randomIntBetween(2, 5)).get();
waitForNoBlocksOnNodes();
try {
final int nbDocs = randomIntBetween(1, 20);
for (int i = 0; i < nbDocs; i++) {
client().prepareIndex("test", "test").setSource("num", i).get();
}
securedFlush();
securedRefresh();
securedEnsureGreen("test");
for (String node : nodesIds) {
logger.debug("--> creating a new instance of the collector");
IndexStatsCollector collector = newIndexStatsCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private IndexStatsCollector newIndexStatsCollector() {
// This collector runs on master node only
return newIndexStatsCollector(internalCluster().getMasterName());
@ -240,7 +191,7 @@ public class IndexStatsCollectorTests extends AbstractCollectorTestCase {
return new IndexStatsCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
securedClient(nodeId));
}
}

View File

@ -13,9 +13,9 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -155,55 +155,6 @@ public class IndicesStatsCollectorTests extends AbstractCollectorTestCase {
assertThat(indicesStats.getIndices().keySet(), hasSize(nbIndices));
}
public void testIndicesStatsCollectorWithLicensing() throws Exception {
List<String> nodesIds = internalCluster().startNodesAsync(randomIntBetween(2, 5)).get();
waitForNoBlocksOnNodes();
try {
final int nbDocs = randomIntBetween(1, 20);
for (int i = 0; i < nbDocs; i++) {
client().prepareIndex("test", "test").setSource("num", i).get();
}
securedFlush();
securedRefresh();
securedEnsureGreen("test");
for (String node : nodesIds) {
logger.debug("--> creating a new instance of the collector");
IndicesStatsCollector collector = newIndicesStatsCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private IndicesStatsCollector newIndicesStatsCollector() {
// This collector runs on master node only
return newIndicesStatsCollector(internalCluster().getMasterName());
@ -216,7 +167,7 @@ public class IndicesStatsCollectorTests extends AbstractCollectorTestCase {
return new IndicesStatsCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
securedClient(nodeId));
}
}

View File

@ -11,9 +11,9 @@ import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -63,41 +63,11 @@ public class NodeStatsCollectorTests extends AbstractCollectorTestCase {
}
}
public void testNodeStatsCollectorWithLicensing() {
try {
String[] nodes = internalCluster().getNodeNames();
for (String node : nodes) {
logger.debug("--> creating a new instance of the collector");
NodeStatsCollector collector = newNodeStatsCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data");
enableLicense();
assertCanCollect(collector);
logger.debug("--> starting graceful period and checks that the collector can still collect data");
beginGracefulPeriod();
assertCanCollect(collector);
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private NodeStatsCollector newNodeStatsCollector(final String nodeId) {
return new NodeStatsCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId),
internalCluster().getInstance(XPackLicenseState.class, nodeId),
internalCluster().getInstance(InternalClient.class, nodeId),
internalCluster().getInstance(NodeEnvironment.class, nodeId),
internalCluster().getInstance(DiskThresholdDecider.class, nodeId));

View File

@ -10,8 +10,8 @@ import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.MonitoredSystem;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.agent.collector.AbstractCollectorTestCase;
import org.elasticsearch.xpack.monitoring.agent.exporter.MonitoringDoc;
@ -160,44 +160,6 @@ public class ShardsCollectorTests extends AbstractCollectorTestCase {
}
}
public void testShardsCollectorWithLicensing() {
try {
String[] nodes = internalCluster().getNodeNames();
for (String node : nodes) {
logger.debug("--> creating a new instance of the collector");
ShardsCollector collector = newShardsCollector(node);
assertNotNull(collector);
logger.debug("--> enabling license and checks that the collector can collect data if node is master");
enableLicense();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> starting graceful period and checks that the collector can still collect data if node is master");
beginGracefulPeriod();
if (node.equals(internalCluster().getMasterName())) {
assertCanCollect(collector);
} else {
assertCannotCollect(collector);
}
logger.debug("--> ending graceful period and checks that the collector cannot collect data");
endGracefulPeriod();
assertCannotCollect(collector);
logger.debug("--> disabling license and checks that the collector cannot collect data");
disableLicense();
assertCannotCollect(collector);
}
} finally {
// Ensure license is enabled before finishing the test
enableLicense();
}
}
private ShardsCollector newShardsCollector() {
// This collector runs on master node only
return newShardsCollector(internalCluster().getMasterName());
@ -208,6 +170,6 @@ public class ShardsCollectorTests extends AbstractCollectorTestCase {
return new ShardsCollector(internalCluster().getInstance(Settings.class, nodeId),
internalCluster().getInstance(ClusterService.class, nodeId),
internalCluster().getInstance(MonitoringSettings.class, nodeId),
internalCluster().getInstance(MonitoringLicensee.class, nodeId));
internalCluster().getInstance(XPackLicenseState.class, nodeId));
}
}

View File

@ -8,10 +8,10 @@ package org.elasticsearch.xpack.monitoring.cleaner;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
@ -34,7 +34,7 @@ public class CleanerServiceTests extends ESTestCase {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private final MonitoringLicensee licensee = mock(MonitoringLicensee.class);
private final XPackLicenseState licenseState = mock(XPackLicenseState.class);
private ClusterSettings clusterSettings;
private ThreadPool threadPool;
@ -56,39 +56,39 @@ public class CleanerServiceTests extends ESTestCase {
TimeValue expected = TimeValue.timeValueHours(1);
Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), expected.getStringRep()).build();
new CleanerService(settings, clusterSettings, threadPool, licensee);
new CleanerService(settings, clusterSettings, threadPool, licenseState);
}
public void testGetRetentionWithSettingWithUpdatesAllowed() {
TimeValue expected = TimeValue.timeValueHours(25);
Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), expected.getStringRep()).build();
when(licensee.allowUpdateRetention()).thenReturn(true);
when(licenseState.isUpdateRetentionAllowed()).thenReturn(true);
assertEquals(expected, new CleanerService(settings, clusterSettings, threadPool, licensee).getRetention());
assertEquals(expected, new CleanerService(settings, clusterSettings, threadPool, licenseState).getRetention());
verify(licensee).allowUpdateRetention();
verify(licenseState).isUpdateRetentionAllowed();
}
public void testGetRetentionDefaultValueWithNoSettings() {
when(licensee.allowUpdateRetention()).thenReturn(true);
when(licenseState.isUpdateRetentionAllowed()).thenReturn(true);
assertEquals(MonitoringSettings.HISTORY_DURATION.get(Settings.EMPTY),
new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licensee).getRetention());
new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licenseState).getRetention());
verify(licensee).allowUpdateRetention();
verify(licenseState).isUpdateRetentionAllowed();
}
public void testGetRetentionDefaultValueWithSettingsButUpdatesNotAllowed() {
TimeValue notExpected = TimeValue.timeValueHours(25);
Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), notExpected.getStringRep()).build();
when(licensee.allowUpdateRetention()).thenReturn(false);
when(licenseState.isUpdateRetentionAllowed()).thenReturn(false);
assertEquals(MonitoringSettings.HISTORY_DURATION.get(Settings.EMPTY),
new CleanerService(settings, clusterSettings, threadPool, licensee).getRetention());
new CleanerService(settings, clusterSettings, threadPool, licenseState).getRetention());
verify(licensee).allowUpdateRetention();
verify(licenseState).isUpdateRetentionAllowed();
}
public void testSetGlobalRetention() {
@ -96,15 +96,15 @@ public class CleanerServiceTests extends ESTestCase {
// only thing calling this method and it will use the settings object to validate the time value
TimeValue expected = TimeValue.timeValueHours(2);
when(licensee.allowUpdateRetention()).thenReturn(true);
when(licenseState.isUpdateRetentionAllowed()).thenReturn(true);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licensee);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licenseState);
service.setGlobalRetention(expected);
assertEquals(expected, service.getRetention());
verify(licensee, times(2)).allowUpdateRetention(); // once by set, once by get
verify(licenseState, times(2)).isUpdateRetentionAllowed(); // once by set, once by get
}
public void testSetGlobalRetentionAppliesEvenIfLicenseDisallows() {
@ -113,9 +113,9 @@ public class CleanerServiceTests extends ESTestCase {
TimeValue expected = TimeValue.timeValueHours(2);
// required to be true on the second call for it to see it take effect
when(licensee.allowUpdateRetention()).thenReturn(false).thenReturn(true);
when(licenseState.isUpdateRetentionAllowed()).thenReturn(false).thenReturn(true);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licensee);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licenseState);
// uses allow=false
service.setGlobalRetention(expected);
@ -123,7 +123,7 @@ public class CleanerServiceTests extends ESTestCase {
// uses allow=true
assertEquals(expected, service.getRetention());
verify(licensee, times(2)).allowUpdateRetention();
verify(licenseState, times(2)).isUpdateRetentionAllowed();
}
public void testNextExecutionDelay() {
@ -151,9 +151,9 @@ public class CleanerServiceTests extends ESTestCase {
CountDownLatch latch = new CountDownLatch(nbExecutions);
logger.debug("--> creates a cleaner service that cleans every second");
MonitoringLicensee licensee = mock(MonitoringLicensee.class);
when(licensee.cleaningEnabled()).thenReturn(true);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, licensee, threadPool,
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isMonitoringAllowed()).thenReturn(true);
CleanerService service = new CleanerService(Settings.EMPTY, clusterSettings, licenseState, threadPool,
new TestExecutionScheduler(1_000));
logger.debug("--> registers cleaning listener");

View File

@ -1,168 +0,0 @@
/*
* 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.xpack.monitoring.license;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.Licensing;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.Licensee;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@ClusterScope(scope = SUITE, transportClientRatio = 0, numClientNodes = 0)
public class LicenseIntegrationTests extends MonitoringIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(InternalXPackPlugin.class);
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.build();
}
public void testEnableDisableLicense() {
assertTrue(getLicensee().getStatus().isActive());
assertThat(getLicensee().collectionEnabled(), is(true));
disableLicensing();
assertThat(getLicensee().getStatus().isActive(), equalTo(false));
assertThat(getLicensee().collectionEnabled(), is(false));
enableLicensing();
assertTrue(getLicensee().getStatus().isActive());
assertThat(getLicensee().collectionEnabled(), is(true));
}
private MonitoringLicensee getLicensee() {
MonitoringLicensee licensee = internalCluster().getInstance(MonitoringLicensee.class);
assertNotNull(licensee);
return licensee;
}
public static void disableLicensing() {
for (MockLicenseService service : internalCluster().getInstances(MockLicenseService.class)) {
service.disable();
}
}
public static void enableLicensing() {
for (MockLicenseService service : internalCluster().getInstances(MockLicenseService.class)) {
service.enable();
}
}
public static class MockLicensing extends Licensing {
public MockLicensing() {
super(Settings.EMPTY);
}
@Override
public Collection<Module> nodeModules() {
return Collections.singletonList(b -> b.bind(LicenseService.class).to(MockLicenseService.class));
}
@Override
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
ResourceWatcherService resourceWatcherService,
SecurityLicenseState securityLicenseState) {
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
GraphLicensee graphLicensee = new GraphLicensee(settings);
LicenseService licenseService = new MockLicenseService(settings, environment, resourceWatcherService,
Arrays.asList(watcherLicensee, monitoringLicensee, graphLicensee));
return Arrays.asList(licenseService, watcherLicensee, monitoringLicensee, graphLicensee);
}
@Override
public List<ActionHandler<? extends ActionRequest<?>, ? extends ActionResponse>> getActions() {
return emptyList();
}
@Override
public List<Class<? extends RestHandler>> getRestHandlers() {
return emptyList();
}
}
public static class MockLicenseService extends LicenseService {
private final List<Licensee> licensees;
@Inject
public MockLicenseService(Settings settings, Environment environment,
ResourceWatcherService resourceWatcherService, List<Licensee> licensees) {
super(settings, null, null, environment, resourceWatcherService, licensees);
this.licensees = licensees;
enable();
}
public void enable() {
for (Licensee licensee : licensees) {
licensee.onChange(new Licensee.Status(License.OperationMode.BASIC, true));
}
}
public void disable() {
for (Licensee licensee : licensees) {
licensee.onChange(new Licensee.Status(License.OperationMode.BASIC, false));
}
}
@Override
public Licensee.Status licenseeStatus(License license) {
return null;
}
@Override
public License getLicense() {
return null;
}
@Override
protected void doStart() {}
@Override
protected void doStop() {}
}
public static class InternalXPackPlugin extends XPackPlugin {
public InternalXPackPlugin(Settings settings) throws IOException {
super(settings);
licensing = new MockLicensing();
}
}
}

View File

@ -1,111 +0,0 @@
/*
* 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.xpack.monitoring.license;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
import org.elasticsearch.license.plugin.core.Licensee.Status;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import java.util.function.Predicate;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Tests {@link MonitoringLicensee}.
* <p>
* If you change the behavior of these tests, then it means that licensing changes for Monitoring!
*/
public class MonitoringLicenseeTests extends AbstractLicenseeTestCase {
private final MonitoringLicensee licensee = new MonitoringLicensee(Settings.EMPTY);
public void testAcknowledgementMessagesToAnyFromFreeIsNoOp() {
assertEmptyAck(OperationMode.BASIC, randomMode(), licensee);
}
public void testAcknowledgementMessagesToTrialGoldOrPlatinumFromAnyIsNoOp() {
assertEmptyAck(randomMode(), randomTrialStandardGoldOrPlatinumMode(), licensee);
}
public void testAcknowledgementMessagesToBasicFromNotBasicNotesLimits() {
OperationMode from = randomFrom(OperationMode.STANDARD, OperationMode.GOLD, OperationMode.PLATINUM, OperationMode.TRIAL);
OperationMode to = OperationMode.BASIC;
String[] messages = ackLicenseChange(from, to, licensee);
// leaving messages up to inspection
assertThat(fromToMessage(from, to), messages.length, equalTo(2));
}
public void testCollectionEnabledIsTrueForActiveState() {
assertEnabled(true, MonitoringLicensee::collectionEnabled, true);
}
public void testCollectionEnabledIsFalseForInactiveState() {
assertEnabled(false, MonitoringLicensee::collectionEnabled, false);
}
public void testCleaningEnabledIsTrueForActiveState() {
assertEnabled(true, MonitoringLicensee::cleaningEnabled, true);
}
public void testCleaningEnabledIsFalseForInactiveState() {
assertEnabled(false, MonitoringLicensee::cleaningEnabled, false);
}
public void testAllowUpdateRetentionIsTrueForNotBasic() {
OperationMode mode = randomFrom(OperationMode.STANDARD, OperationMode.GOLD, OperationMode.PLATINUM, OperationMode.TRIAL);
assertEnabled(mode, MonitoringLicensee::allowUpdateRetention, true);
}
public void testAllowUpdateRetentionIsFalseForBasic() {
assertEnabled(OperationMode.BASIC, MonitoringLicensee::allowUpdateRetention, false);
}
public void testAllowUpdateRetentionIsFalseForMissing() {
assertEnabled(OperationMode.MISSING, MonitoringLicensee::allowUpdateRetention, false);
}
/**
* Assert that the {@link #licensee} is {@code predicate}d as {@code expected} when setting the {@code state}.
*
* @param active The state that should cause the {@code expected} {@code predicate}.
* @param predicate The method to invoke (expected to be an instance method).
* @param expected The expected outcome given the {@code state} and {@code predicate}.
*/
private void assertEnabled(boolean active, Predicate<MonitoringLicensee> predicate, boolean expected) {
Status status = mock(Status.class);
when(status.isActive()).thenReturn(active);
licensee.onChange(status);
assertThat(predicate.test(licensee), equalTo(expected));
verify(status).isActive();
}
/**
* Assert that the {@link #licensee} is {@code predicate}d as {@code expected} when setting the {@code mode}.
*
* @param mode The mode that should cause the {@code expected} {@code predicate}.
* @param predicate The method to invoke (expected to be an instance method).
* @param expected The expected outcome given the {@code mode} and {@code predicate}.
*/
private void assertEnabled(OperationMode mode, Predicate<MonitoringLicensee> predicate, boolean expected) {
Status status = mock(Status.class);
when(status.getMode()).thenReturn(mode);
licensee.onChange(status);
assertThat(predicate.test(licensee), equalTo(expected));
verify(status).getMode();
}
}

View File

@ -40,6 +40,7 @@ import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.plugins.ActionPlugin;
import org.elasticsearch.plugins.IngestPlugin;
import org.elasticsearch.rest.RestHandler;
@ -89,10 +90,10 @@ import org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import org.elasticsearch.xpack.security.authc.support.SecuredString;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor;
import org.elasticsearch.xpack.security.authz.accesscontrol.OptOutQueryCache;
import org.elasticsearch.xpack.security.authz.accesscontrol.SecurityIndexSearcherWrapper;
import org.elasticsearch.xpack.security.authz.accesscontrol.SetSecurityUserProcessor;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.authz.store.FileRolesStore;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
@ -149,10 +150,10 @@ public class Security implements ActionPlugin, IngestPlugin {
private final Environment env;
private final boolean enabled;
private final boolean transportClientMode;
private final SecurityLicenseState securityLicenseState;
private final XPackLicenseState licenseState;
private final CryptoService cryptoService;
public Security(Settings settings, Environment env) throws IOException {
public Security(Settings settings, Environment env, XPackLicenseState licenseState) throws IOException {
this.settings = settings;
this.env = env;
this.transportClientMode = XPackPlugin.transportClientMode(settings);
@ -163,17 +164,13 @@ public class Security implements ActionPlugin, IngestPlugin {
} else {
cryptoService = null;
}
securityLicenseState = new SecurityLicenseState();
this.licenseState = licenseState;
}
public CryptoService getCryptoService() {
return cryptoService;
}
public SecurityLicenseState getSecurityLicenseState() {
return securityLicenseState;
}
public boolean isEnabled() {
return enabled;
}
@ -203,7 +200,7 @@ public class Security implements ActionPlugin, IngestPlugin {
b.bind(Realms.class).toProvider(Providers.of(null)); // for SecurityFeatureSet
b.bind(CompositeRolesStore.class).toProvider(Providers.of(null)); // for SecurityFeatureSet
b.bind(AuditTrailService.class)
.toInstance(new AuditTrailService(settings, Collections.emptyList(), securityLicenseState));
.toInstance(new AuditTrailService(settings, Collections.emptyList(), licenseState));
});
modules.add(new SecurityTransportModule(settings));
return modules;
@ -259,7 +256,7 @@ public class Security implements ActionPlugin, IngestPlugin {
}
}
}
final Realms realms = new Realms(settings, env, realmFactories, securityLicenseState, reservedRealm);
final Realms realms = new Realms(settings, env, realmFactories, licenseState, reservedRealm);
components.add(nativeUsersStore);
components.add(realms);
@ -288,7 +285,7 @@ public class Security implements ActionPlugin, IngestPlugin {
}
}
final AuditTrailService auditTrailService =
new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), securityLicenseState);
new AuditTrailService(settings, auditTrails.stream().collect(Collectors.toList()), licenseState);
components.add(auditTrailService);
AuthenticationFailureHandler failureHandler = null;
@ -425,12 +422,13 @@ public class Security implements ActionPlugin, IngestPlugin {
return;
}
assert securityLicenseState != null;
assert licenseState != null;
if (flsDlsEnabled(settings)) {
module.setSearcherWrapper((indexService) -> new SecurityIndexSearcherWrapper(indexService.getIndexSettings(),
indexService.newQueryShardContext(), indexService.mapperService(),
indexService.cache().bitsetFilterCache(), indexService.getIndexServices().getThreadPool().getThreadContext(),
securityLicenseState, indexService.getIndexServices().getScriptService()));
module.setSearcherWrapper(indexService ->
new SecurityIndexSearcherWrapper(indexService.getIndexSettings(), indexService.newQueryShardContext(),
indexService.mapperService(), indexService.cache().bitsetFilterCache(),
indexService.getIndexServices().getThreadPool().getThreadContext(), licenseState,
indexService.getIndexServices().getScriptService()));
}
if (transportClientMode == false) {
/* We need to forcefully overwrite the query cache implementation to use security's opt out query cache implementation.

View File

@ -13,6 +13,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.Realms;
@ -40,7 +41,7 @@ public class SecurityFeatureSet implements XPackFeatureSet {
private final Settings settings;
private final boolean enabled;
private final SecurityLicenseState licenseState;
private final XPackLicenseState licenseState;
@Nullable
private final Realms realms;
@Nullable
@ -53,7 +54,7 @@ public class SecurityFeatureSet implements XPackFeatureSet {
private final CryptoService cryptoService;
@Inject
public SecurityFeatureSet(Settings settings, @Nullable SecurityLicenseState licenseState, @Nullable Realms realms,
public SecurityFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, @Nullable Realms realms,
NamedWriteableRegistry namedWriteableRegistry, @Nullable CompositeRolesStore rolesStore,
@Nullable IPFilter ipFilter, @Nullable AuditTrailService auditTrailService,
@Nullable CryptoService cryptoService) {
@ -80,7 +81,7 @@ public class SecurityFeatureSet implements XPackFeatureSet {
@Override
public boolean available() {
return licenseState != null && licenseState.authenticationAndAuthorizationEnabled();
return licenseState != null && licenseState.isAuthAllowed();
}
@Override

View File

@ -1,103 +0,0 @@
/*
* 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.xpack.security;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.Licensee.Status;
/**
* This class serves to decouple security code that needs to check the license state from the {@link SecurityLicensee} as the
* tight coupling causes issues with guice injection and circular dependencies
*/
public class SecurityLicenseState {
// we initialize the licensee status to enabled with trial operation mode to ensure no
// legitimate requests are blocked before initial license plugin notification
protected volatile Status status = Status.ENABLED;
/**
* @return true if authentication and authorization should be enabled. this does not indicate what realms are available
* @see SecurityLicenseState#enabledRealmType() for the enabled realms
*/
public boolean authenticationAndAuthorizationEnabled() {
OperationMode mode = status.getMode();
return mode == OperationMode.STANDARD || mode == OperationMode.GOLD || mode == OperationMode.PLATINUM
|| mode == OperationMode.TRIAL;
}
/**
* @return true if IP filtering should be enabled
*/
public boolean ipFilteringEnabled() {
OperationMode mode = status.getMode();
return mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL;
}
/**
* @return true if auditing should be enabled
*/
public boolean auditingEnabled() {
OperationMode mode = status.getMode();
return mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL;
}
/**
* Indicates whether the stats and health API calls should be allowed. If a license is expired and past the grace
* period then we deny these calls.
*
* @return true if the license allows for the stats and health APIs to be used.
*/
public boolean statsAndHealthEnabled() {
return status.isActive();
}
/**
* Determine if Document Level Security (DLS) and Field Level Security (FLS) should be enabled.
* <p>
* DLS and FLS are only disabled when the mode is not:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
* Note: This does not consider the <em>state</em> of the license so that Security does not suddenly leak information!
*
* @return {@code true} to enable DLS and FLS. Otherwise {@code false}.
*/
public boolean documentAndFieldLevelSecurityEnabled() {
Status status = this.status;
return status.getMode() == OperationMode.TRIAL || status.getMode() == OperationMode.PLATINUM;
}
/**
* @return the type of realms that are enabled based on the license {@link OperationMode}
*/
public EnabledRealmType enabledRealmType() {
OperationMode mode = status.getMode();
switch (mode) {
case PLATINUM:
case TRIAL:
return EnabledRealmType.ALL;
case GOLD:
return EnabledRealmType.DEFAULT;
case STANDARD:
return EnabledRealmType.NATIVE;
default:
return EnabledRealmType.NONE;
}
}
void updateStatus(Status status) {
this.status = status;
}
public enum EnabledRealmType {
NONE,
NATIVE,
DEFAULT,
ALL
}
}

View File

@ -1,86 +0,0 @@
/*
* 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.xpack.security;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
/**
*
*/
public class SecurityLicensee extends AbstractLicenseeComponent {
private final SecurityLicenseState securityLicenseState;
public SecurityLicensee(Settings settings, SecurityLicenseState securityLicenseState) {
super(settings, Security.NAME);
this.securityLicenseState = securityLicenseState;
}
@Override
public void onChange(Status status) {
super.onChange(status);
securityLicenseState.updateStatus(status);
}
@Override
public String[] expirationMessages() {
return new String[]{
"Cluster health, cluster stats and indices stats operations are blocked",
"All data operations (read and write) continue to work"
};
}
@Override
public String[] acknowledgmentMessages(License.OperationMode currentMode, License.OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] {
"The following X-Pack security functionality will be disabled: authentication, authorization, " +
"ip filtering, and auditing. Please restart your node after applying the license.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
break;
case GOLD:
switch (currentMode) {
case BASIC:
case STANDARD:
// ^^ though technically it was already disabled, it's not bad to remind them
case TRIAL:
case PLATINUM:
return new String[] {
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
break;
case STANDARD:
switch (currentMode) {
case BASIC:
// ^^ though technically it was already disabled, it's not bad to remind them
case GOLD:
case PLATINUM:
case TRIAL:
return new String[] {
"Authentication will be limited to the native realms.",
"IP filtering and auditing will be disabled.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
}
return Strings.EMPTY_ARRAY;
}
}

View File

@ -33,7 +33,7 @@ import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.authz.AuthorizationUtils;
import org.elasticsearch.xpack.security.authz.privilege.HealthAndStatsPrivilege;
import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
@ -55,13 +55,13 @@ public class SecurityActionFilter extends AbstractComponent implements ActionFil
private final AuditTrail auditTrail;
private final SecurityActionMapper actionMapper;
private final Set<RequestInterceptor> requestInterceptors;
private final SecurityLicenseState licenseState;
private final XPackLicenseState licenseState;
private final ThreadContext threadContext;
private final SecurityContext securityContext;
@Inject
public SecurityActionFilter(Settings settings, AuthenticationService authcService, AuthorizationService authzService,
CryptoService cryptoService, AuditTrailService auditTrail, SecurityLicenseState licenseState,
CryptoService cryptoService, AuditTrailService auditTrail, XPackLicenseState licenseState,
SecurityActionMapper actionMapper, Set<RequestInterceptor> requestInterceptors, ThreadPool threadPool,
SecurityContext securityContext) {
super(settings);
@ -83,7 +83,7 @@ public class SecurityActionFilter extends AbstractComponent implements ActionFil
A functional requirement - when the license of security is disabled (invalid/expires), security will continue
to operate normally, except all read operations will be blocked.
*/
if (!licenseState.statsAndHealthEnabled() && LICENSE_EXPIRATION_ACTION_MATCHER.test(action)) {
if (licenseState.isStatsAndHealthAllowed() == false && LICENSE_EXPIRATION_ACTION_MATCHER.test(action)) {
logger.error("blocking [{}] operation due to expired license. Cluster health, cluster stats and indices stats \n" +
"operations are blocked on 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);
@ -95,7 +95,7 @@ public class SecurityActionFilter extends AbstractComponent implements ActionFil
final ThreadContext.StoredContext original = threadContext.newStoredContext();
final boolean restoreOriginalContext = securityContext.getAuthentication() != null;
try {
if (licenseState.authenticationAndAuthorizationEnabled()) {
if (licenseState.isAuthAllowed()) {
if (AuthorizationUtils.shouldReplaceUserWithSystem(threadContext, action)) {
try (ThreadContext.StoredContext ctx = threadContext.stashContext()) {
applyInternal(task, action, request, new SigningListener(this, listener, original), chain);

View File

@ -10,15 +10,13 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
import org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule;
import org.elasticsearch.xpack.security.user.User;
@ -28,7 +26,7 @@ import org.elasticsearch.xpack.security.user.User;
*/
public class AuditTrailService extends AbstractComponent implements AuditTrail {
private final SecurityLicenseState securityLicenseState;
private final XPackLicenseState licenseState;
final List<AuditTrail> auditTrails;
@Override
@ -36,10 +34,10 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
return "service";
}
public AuditTrailService(Settings settings, List<AuditTrail> auditTrails, SecurityLicenseState licenseState) {
public AuditTrailService(Settings settings, List<AuditTrail> auditTrails, XPackLicenseState licenseState) {
super(settings);
this.auditTrails = Collections.unmodifiableList(auditTrails);
this.securityLicenseState = licenseState;
this.licenseState = licenseState;
}
/** Returns the audit trail implementations that this service delegates to. */
@ -49,7 +47,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void anonymousAccessDenied(String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.anonymousAccessDenied(action, message);
}
@ -58,7 +56,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void anonymousAccessDenied(RestRequest request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.anonymousAccessDenied(request);
}
@ -67,7 +65,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(RestRequest request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(request);
}
@ -76,7 +74,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(action, message);
}
@ -85,7 +83,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(AuthenticationToken token, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(token, action, message);
}
@ -94,7 +92,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(String realm, AuthenticationToken token, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(realm, token, action, message);
}
@ -103,7 +101,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(AuthenticationToken token, RestRequest request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(token, request);
}
@ -112,7 +110,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void authenticationFailed(String realm, AuthenticationToken token, RestRequest request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.authenticationFailed(realm, token, request);
}
@ -121,7 +119,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void accessGranted(User user, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.accessGranted(user, action, message);
}
@ -130,7 +128,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void accessDenied(User user, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.accessDenied(user, action, message);
}
@ -146,7 +144,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void tamperedRequest(String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.tamperedRequest(action, message);
}
@ -155,7 +153,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void tamperedRequest(User user, String action, TransportMessage request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.tamperedRequest(user, action, request);
}
@ -164,7 +162,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void connectionGranted(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.connectionGranted(inetAddress, profile, rule);
}
@ -173,7 +171,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void connectionDenied(InetAddress inetAddress, String profile, SecurityIpFilterRule rule) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.connectionDenied(inetAddress, profile, rule);
}
@ -182,7 +180,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void runAsGranted(User user, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.runAsGranted(user, action, message);
}
@ -191,7 +189,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void runAsDenied(User user, String action, TransportMessage message) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.runAsDenied(user, action, message);
}
@ -200,7 +198,7 @@ public class AuditTrailService extends AbstractComponent implements AuditTrail {
@Override
public void runAsDenied(User user, RestRequest request) {
if (securityLicenseState.auditingEnabled()) {
if (licenseState.isAuditingAllowed()) {
for (AuditTrail auditTrail : auditTrails) {
auditTrail.runAsDenied(user, request);
}

View File

@ -5,22 +5,6 @@
*/
package org.elasticsearch.xpack.security.authc;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType;
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
import org.elasticsearch.xpack.security.authc.file.FileRealm;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -30,6 +14,21 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState.AllowedRealmType;
import org.elasticsearch.xpack.security.authc.activedirectory.ActiveDirectoryRealm;
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authc.file.FileRealm;
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import static org.elasticsearch.xpack.security.Security.setting;
/**
@ -44,7 +43,7 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
private final Environment env;
private final Map<String, Realm.Factory> factories;
private final SecurityLicenseState securityLicenseState;
private final XPackLicenseState licenseState;
private final ReservedRealm reservedRealm;
protected List<Realm> realms = Collections.emptyList();
@ -53,12 +52,12 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
// a list of realms that are considered native, that is they only interact with x-pack and no 3rd party auth sources
protected List<Realm> nativeRealmsOnly = Collections.emptyList();
public Realms(Settings settings, Environment env, Map<String, Realm.Factory> factories, SecurityLicenseState securityLicenseState,
public Realms(Settings settings, Environment env, Map<String, Realm.Factory> factories, XPackLicenseState licenseState,
ReservedRealm reservedRealm) {
super(settings);
this.env = env;
this.factories = factories;
this.securityLicenseState = securityLicenseState;
this.licenseState = licenseState;
this.reservedRealm = reservedRealm;
}
@ -105,12 +104,12 @@ public class Realms extends AbstractLifecycleComponent implements Iterable<Realm
@Override
public Iterator<Realm> iterator() {
if (securityLicenseState.authenticationAndAuthorizationEnabled() == false) {
if (licenseState.isAuthAllowed() == false) {
return Collections.emptyIterator();
}
EnabledRealmType enabledRealmType = securityLicenseState.enabledRealmType();
switch (enabledRealmType) {
AllowedRealmType allowedRealmType = licenseState.allowedRealmType();
switch (allowedRealmType) {
case ALL:
return realms.iterator();
case DEFAULT:

View File

@ -45,6 +45,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.IndexSearcherWrapper;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.shard.ShardUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
@ -52,7 +53,6 @@ import org.elasticsearch.script.ScriptService;
import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.accesscontrol.DocumentSubsetReader.DocumentSubsetDirectoryReader;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.support.Exceptions;
import org.elasticsearch.xpack.security.user.User;
@ -85,14 +85,14 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper {
private final Set<String> allowedMetaFields;
private final QueryShardContext queryShardContext;
private final BitsetFilterCache bitsetFilterCache;
private final SecurityLicenseState securityLicenseState;
private final XPackLicenseState licenseState;
private final ThreadContext threadContext;
private final ESLogger logger;
private final ScriptService scriptService;
public SecurityIndexSearcherWrapper(IndexSettings indexSettings, QueryShardContext queryShardContext,
MapperService mapperService, BitsetFilterCache bitsetFilterCache,
ThreadContext threadContext, SecurityLicenseState securityLicenseState,
ThreadContext threadContext, XPackLicenseState licenseState,
ScriptService scriptService) {
this.scriptService = scriptService;
this.logger = Loggers.getLogger(getClass(), indexSettings.getSettings());
@ -100,7 +100,7 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper {
this.queryShardContext = queryShardContext;
this.bitsetFilterCache = bitsetFilterCache;
this.threadContext = threadContext;
this.securityLicenseState = securityLicenseState;
this.licenseState = licenseState;
Set<String> allowedMetaFields = new HashSet<>();
allowedMetaFields.addAll(Arrays.asList(MapperService.getAllMetaFields()));
@ -114,7 +114,7 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper {
@Override
protected DirectoryReader wrap(DirectoryReader reader) {
if (securityLicenseState.documentAndFieldLevelSecurityEnabled() == false) {
if (licenseState.isDocumentAndFieldLevelSecurityAllowed() == false) {
return reader;
}
@ -171,7 +171,7 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper {
@Override
protected IndexSearcher wrap(IndexSearcher searcher) throws EngineException {
if (securityLicenseState.documentAndFieldLevelSecurityEnabled() == false) {
if (licenseState.isDocumentAndFieldLevelSecurityAllowed() == false) {
return searcher;
}

View File

@ -19,7 +19,7 @@ import org.elasticsearch.rest.RestFilterChain;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3HttpServerTransport;
import org.elasticsearch.threadpool.ThreadPool;
import org.jboss.netty.handler.ssl.SslHandler;
@ -35,13 +35,13 @@ public class SecurityRestFilter extends RestFilter {
private final AuthenticationService service;
private final ESLogger logger;
private final SecurityLicenseState licenseState;
private final XPackLicenseState licenseState;
private final ThreadContext threadContext;
private final boolean extractClientCertificate;
@Inject
public SecurityRestFilter(AuthenticationService service, RestController controller, Settings settings,
ThreadPool threadPool, SecurityLicenseState licenseState) {
ThreadPool threadPool, XPackLicenseState licenseState) {
this.service = service;
this.licenseState = licenseState;
this.threadContext = threadPool.getThreadContext();
@ -59,7 +59,7 @@ public class SecurityRestFilter extends RestFilter {
@Override
public void process(RestRequest request, RestChannel channel, NodeClient client, RestFilterChain filterChain) throws Exception {
if (licenseState.authenticationAndAuthorizationEnabled()) {
if (licenseState.isAuthAllowed()) {
// CORS - allow for preflight unauthenticated OPTIONS request
if (request.method() != RestRequest.Method.OPTIONS) {
if (extractClientCertificate) {

View File

@ -14,7 +14,7 @@ import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.AuthorizationUtils;
import org.elasticsearch.xpack.security.authz.accesscontrol.RequestContext;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
@ -46,7 +46,7 @@ public class SecurityServerTransportService extends TransportService {
protected final AuthorizationService authzService;
protected final SecurityActionMapper actionMapper;
protected final ClientTransportFilter clientFilter;
protected final SecurityLicenseState licenseState;
protected final XPackLicenseState licenseState;
protected final Map<String, ServerTransportFilter> profileFilters;
@ -56,7 +56,7 @@ public class SecurityServerTransportService extends TransportService {
AuthorizationService authzService,
SecurityActionMapper actionMapper,
ClientTransportFilter clientTransportFilter,
SecurityLicenseState licenseState) {
XPackLicenseState licenseState) {
super(settings, transport, threadPool);
this.authcService = authcService;
this.authzService = authzService;
@ -155,11 +155,11 @@ public class SecurityServerTransportService extends TransportService {
protected final String action;
protected final TransportRequestHandler<T> handler;
private final Map<String, ServerTransportFilter> profileFilters;
private final SecurityLicenseState licenseState;
private final XPackLicenseState licenseState;
private final ThreadContext threadContext;
public ProfileSecuredRequestHandler(String action, TransportRequestHandler<T> handler,
Map<String, ServerTransportFilter> profileFilters, SecurityLicenseState licenseState,
Map<String, ServerTransportFilter> profileFilters, XPackLicenseState licenseState,
ThreadContext threadContext) {
this.action = action;
this.handler = handler;
@ -171,7 +171,7 @@ public class SecurityServerTransportService extends TransportService {
@Override
public void messageReceived(T request, TransportChannel channel, Task task) throws Exception {
try (ThreadContext.StoredContext ctx = threadContext.newStoredContext()) {
if (licenseState.authenticationAndAuthorizationEnabled()) {
if (licenseState.isAuthAllowed()) {
String profile = channel.getProfileName();
ServerTransportFilter filter = profileFilters.get(profile);

View File

@ -17,7 +17,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
@ -88,8 +88,8 @@ public class IPFilter {
}
};
private final AuditTrail auditTrail;
private final SecurityLicenseState licenseState;
private final AuditTrailService auditTrail;
private final XPackLicenseState licenseState;
private final boolean alwaysAllowBoundAddresses;
private final ESLogger logger;
@ -107,7 +107,7 @@ public class IPFilter {
@Inject
public IPFilter(final Settings settings, AuditTrailService auditTrail, ClusterSettings clusterSettings,
SecurityLicenseState licenseState) {
XPackLicenseState licenseState) {
this.logger = Loggers.getLogger(getClass(), settings);
this.auditTrail = auditTrail;
this.licenseState = licenseState;
@ -174,7 +174,7 @@ public class IPFilter {
}
public boolean accept(String profile, InetAddress peerAddress) {
if (licenseState.ipFilteringEnabled() == false) {
if (licenseState.isIpFilteringAllowed() == false) {
return true;
}

View File

@ -1,327 +0,0 @@
/*
* 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.integration;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
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.client.Client;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.Licensing;
import org.elasticsearch.license.plugin.core.LicenseService;
import org.elasticsearch.license.plugin.core.Licensee;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.MockNetty3Plugin;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.graph.GraphLicensee;
import org.elasticsearch.xpack.monitoring.MonitoringLicensee;
import org.elasticsearch.xpack.XPackTransportClient;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.SecurityLicensee;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.junit.After;
import static java.util.Collections.emptyList;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
/**
*
*/
public class LicensingTests extends SecurityIntegTestCase {
public static final String ROLES =
SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
" cluster: [ all ]\n" +
" indices:\n" +
" - names: '*'\n" +
" privileges: [manage]\n" +
" - names: '/.*/'\n" +
" privileges: [write]\n" +
" - names: 'test'\n" +
" privileges: [read]\n" +
" - names: 'test1'\n" +
" privileges: [read]\n" +
"\n" +
"role_a:\n" +
" indices:\n" +
" - names: 'a'\n" +
" privileges: [all]\n" +
"\n" +
"role_b:\n" +
" indices:\n" +
" - names: 'b'\n" +
" privileges: [all]\n";
public static final String USERS =
SecuritySettingsSource.CONFIG_STANDARD_USER +
"user_a:{plain}passwd\n" +
"user_b:{plain}passwd\n";
public static final String USERS_ROLES =
SecuritySettingsSource.CONFIG_STANDARD_USER_ROLES +
"role_a:user_a,user_b\n" +
"role_b:user_b\n";
@Override
protected String configRoles() {
return ROLES;
}
@Override
protected String configUsers() {
return USERS;
}
@Override
protected String configUsersRoles() {
return USERS_ROLES;
}
@Override
public Settings nodeSettings(int nodeOrdinal) {
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(MockNetty3Plugin.class); // for http
return plugins;
}
@Override
protected Class<? extends XPackPlugin> xpackPluginClass() {
return InternalXPackPlugin.class;
}
@After
public void resetLicensing() {
enableLicensing();
}
public void testEnableDisableBehaviour() throws Exception {
IndexResponse indexResponse = index("test", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
indexResponse = index("test1", "type", jsonBuilder()
.startObject()
.field("name", "value1")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
disableLicensing();
assertElasticsearchSecurityException(() -> client.admin().indices().prepareStats().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareClusterStats().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareHealth().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareNodesStats().get());
enableLicensing(randomFrom(OperationMode.values()));
IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats().get();
assertNoFailures(indicesStatsResponse);
ClusterStatsResponse clusterStatsNodeResponse = client.admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsNodeResponse, notNullValue());
ClusterStatsIndices indices = clusterStatsNodeResponse.getIndicesStats();
assertThat(indices, notNullValue());
assertThat(indices.getIndexCount(), greaterThanOrEqualTo(2));
ClusterHealthResponse clusterIndexHealth = client.admin().cluster().prepareHealth().get();
assertThat(clusterIndexHealth, notNullValue());
NodesStatsResponse nodeStats = client.admin().cluster().prepareNodesStats().get();
assertThat(nodeStats, notNullValue());
}
public void testRestAuthenticationByLicenseType() throws Exception {
Response response = getRestClient().performRequest("GET", "/");
// the default of the licensing tests is basic
assertThat(response.getStatusLine().getStatusCode(), is(200));
// generate a new license with a mode that enables auth
OperationMode mode = randomFrom(OperationMode.GOLD, OperationMode.TRIAL, OperationMode.PLATINUM, OperationMode.STANDARD);
enableLicensing(mode);
try {
getRestClient().performRequest("GET", "/");
fail("request should have failed");
} catch(ResponseException e) {
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401));
}
}
public void testTransportClientAuthenticationByLicenseType() throws Exception {
Settings.Builder builder = Settings.builder()
.put(internalCluster().transportClient().settings());
// remove user info
builder.remove(Security.USER_SETTING.getKey());
builder.remove(ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER);
// basic has no auth
try (TransportClient client = new XPackTransportClient(builder.build())) {
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
assertGreenClusterState(client);
}
// enable a license that enables security
OperationMode mode = randomFrom(OperationMode.GOLD, OperationMode.TRIAL, OperationMode.PLATINUM, OperationMode.STANDARD);
enableLicensing(mode);
try (TransportClient client = new XPackTransportClient(builder.build())) {
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
client.admin().cluster().prepareHealth().get();
fail("should not have been able to connect to a node!");
} catch (NoNodeAvailableException e) {
// expected
}
}
private static void assertElasticsearchSecurityException(ThrowingRunnable runnable) {
ElasticsearchSecurityException ee = expectThrows(ElasticsearchSecurityException.class, runnable);
assertThat(ee.getHeader("es.license.expired.feature"), hasItem(Security.NAME));
assertThat(ee.status(), is(RestStatus.FORBIDDEN));
}
public static void disableLicensing() {
disableLicensing(OperationMode.BASIC);
}
public static void disableLicensing(OperationMode operationMode) {
for (TestLicenseService service : internalCluster().getInstances(TestLicenseService.class)) {
service.disable(operationMode);
}
}
public static void enableLicensing() {
enableLicensing(OperationMode.BASIC);
}
public static void enableLicensing(OperationMode operationMode) {
for (TestLicenseService service : internalCluster().getInstances(TestLicenseService.class)) {
service.enable(operationMode);
}
}
public static class InternalLicensing extends Licensing {
@Override
public Collection<Module> nodeModules() {
return Collections.singletonList(b -> b.bind(LicenseService.class).to(TestLicenseService.class));
}
@Override
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
ResourceWatcherService resourceWatcherService,
SecurityLicenseState securityLicenseState) {
SecurityLicensee securityLicensee = new SecurityLicensee(settings, securityLicenseState);
WatcherLicensee watcherLicensee = new WatcherLicensee(settings);
MonitoringLicensee monitoringLicensee = new MonitoringLicensee(settings);
GraphLicensee graphLicensee = new GraphLicensee(settings);
TestLicenseService licensesService = new TestLicenseService(settings, environment, resourceWatcherService,
Arrays.asList(securityLicensee, watcherLicensee, monitoringLicensee, graphLicensee));
return Arrays.asList(securityLicensee, licensesService, watcherLicensee, monitoringLicensee,
graphLicensee, securityLicenseState);
}
public InternalLicensing() {
super(Settings.EMPTY);
}
@Override
public List<ActionHandler<? extends ActionRequest<?>, ? extends ActionResponse>> getActions() {
return emptyList();
}
@Override
public List<Class<? extends RestHandler>> getRestHandlers() {
return emptyList();
}
}
public static class InternalXPackPlugin extends XPackPlugin {
public InternalXPackPlugin(Settings settings) throws IOException {
super(settings);
licensing = new InternalLicensing();
}
}
public static class TestLicenseService extends LicenseService {
private final List<Licensee> licensees;
public TestLicenseService(Settings settings, Environment env, ResourceWatcherService resourceWatcherService,
List<Licensee> licensees) {
super(settings, null, null, env, resourceWatcherService, Collections.emptyList());
this.licensees = licensees;
enable(OperationMode.BASIC);
}
void enable(OperationMode operationMode) {
for (Licensee licensee : licensees) {
licensee.onChange(new Licensee.Status(operationMode, true));
}
}
void disable(OperationMode operationMode) {
for (Licensee licensee : licensees) {
licensee.onChange(new Licensee.Status(operationMode, false));
}
}
@Override
protected void doStart() {}
@Override
protected void doStop() {}
}
}

View File

@ -0,0 +1,222 @@
/*
* 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.license.plugin.core;
import java.util.ArrayList;
import java.util.Collection;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
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.client.Client;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.transport.NoNodeAvailableException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.license.core.License;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.xpack.MockNetty3Plugin;
import org.elasticsearch.xpack.XPackTransportClient;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
import org.junit.After;
import org.junit.Before;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
public class LicensingTests extends SecurityIntegTestCase {
public static final String ROLES =
SecuritySettingsSource.DEFAULT_ROLE + ":\n" +
" cluster: [ all ]\n" +
" indices:\n" +
" - names: '*'\n" +
" privileges: [manage]\n" +
" - names: '/.*/'\n" +
" privileges: [write]\n" +
" - names: 'test'\n" +
" privileges: [read]\n" +
" - names: 'test1'\n" +
" privileges: [read]\n" +
"\n" +
"role_a:\n" +
" indices:\n" +
" - names: 'a'\n" +
" privileges: [all]\n" +
"\n" +
"role_b:\n" +
" indices:\n" +
" - names: 'b'\n" +
" privileges: [all]\n";
public static final String USERS =
SecuritySettingsSource.CONFIG_STANDARD_USER +
"user_a:{plain}passwd\n" +
"user_b:{plain}passwd\n";
public static final String USERS_ROLES =
SecuritySettingsSource.CONFIG_STANDARD_USER_ROLES +
"role_a:user_a,user_b\n" +
"role_b:user_b\n";
@Override
protected String configRoles() {
return ROLES;
}
@Override
protected String configUsers() {
return USERS;
}
@Override
protected String configUsersRoles() {
return USERS_ROLES;
}
@Override
public Settings nodeSettings(int nodeOrdinal) {
return Settings.builder().put(super.nodeSettings(nodeOrdinal))
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(MockNetty3Plugin.class); // for http
return plugins;
}
@Before
public void resetLicensing() {
enableLicensing();
}
public void testEnableDisableBehaviour() throws Exception {
IndexResponse indexResponse = index("test", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
indexResponse = index("test1", "type", jsonBuilder()
.startObject()
.field("name", "value1")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
disableLicensing();
assertElasticsearchSecurityException(() -> client.admin().indices().prepareStats().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareClusterStats().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareHealth().get());
assertElasticsearchSecurityException(() -> client.admin().cluster().prepareNodesStats().get());
enableLicensing(randomFrom(License.OperationMode.values()));
IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats().get();
assertNoFailures(indicesStatsResponse);
ClusterStatsResponse clusterStatsNodeResponse = client.admin().cluster().prepareClusterStats().get();
assertThat(clusterStatsNodeResponse, notNullValue());
ClusterStatsIndices indices = clusterStatsNodeResponse.getIndicesStats();
assertThat(indices, notNullValue());
assertThat(indices.getIndexCount(), greaterThanOrEqualTo(2));
ClusterHealthResponse clusterIndexHealth = client.admin().cluster().prepareHealth().get();
assertThat(clusterIndexHealth, notNullValue());
NodesStatsResponse nodeStats = client.admin().cluster().prepareNodesStats().get();
assertThat(nodeStats, notNullValue());
}
public void testRestAuthenticationByLicenseType() throws Exception {
Response response = getRestClient().performRequest("GET", "/");
// the default of the licensing tests is basic
assertThat(response.getStatusLine().getStatusCode(), is(200));
// generate a new license with a mode that enables auth
License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.TRIAL,
License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
enableLicensing(mode);
ResponseException e = expectThrows(ResponseException.class, () -> getRestClient().performRequest("GET", "/"));
assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401));
}
public void testTransportClientAuthenticationByLicenseType() throws Exception {
Settings.Builder builder = Settings.builder()
.put(internalCluster().transportClient().settings());
// remove user info
builder.remove(Security.USER_SETTING.getKey());
builder.remove(ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER);
// basic has no auth
try (TransportClient client = new XPackTransportClient(builder.build())) {
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
assertGreenClusterState(client);
}
// enable a license that enables security
License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.TRIAL,
License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
enableLicensing(mode);
try (TransportClient client = new XPackTransportClient(builder.build())) {
client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress());
client.admin().cluster().prepareHealth().get();
fail("should not have been able to connect to a node!");
} catch (NoNodeAvailableException e) {
// expected
}
}
private static void assertElasticsearchSecurityException(ThrowingRunnable runnable) {
ElasticsearchSecurityException ee = expectThrows(ElasticsearchSecurityException.class, runnable);
assertThat(ee.getHeader("es.license.expired.feature"), hasItem(Security.NAME));
assertThat(ee.status(), is(RestStatus.FORBIDDEN));
}
public static void disableLicensing() {
disableLicensing(License.OperationMode.BASIC);
}
public static void disableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, false);
}
}
public static void enableLicensing() {
enableLicensing(License.OperationMode.BASIC);
}
public static void enableLicensing(License.OperationMode operationMode) {
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
licenseState.update(operationMode, true);
}
}
}

View File

@ -0,0 +1,255 @@
/*
* 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.license.plugin.core;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.XPackLicenseState.AllowedRealmType;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.monitoring.Monitoring;
import org.elasticsearch.xpack.security.Security;
import static org.elasticsearch.license.core.License.OperationMode.MISSING;
import static org.elasticsearch.license.core.License.OperationMode.BASIC;
import static org.elasticsearch.license.core.License.OperationMode.GOLD;
import static org.elasticsearch.license.core.License.OperationMode.PLATINUM;
import static org.elasticsearch.license.core.License.OperationMode.STANDARD;
import static org.elasticsearch.license.core.License.OperationMode.TRIAL;
import static org.hamcrest.Matchers.is;
/**
* Unit tests for the {@link XPackLicenseState}
*/
public class XPackLicenseStateTests extends ESTestCase {
/** Creates a license state with the given license type and active state, and checks the given method returns expected. */
void assertAllowed(OperationMode mode, boolean active, Predicate<XPackLicenseState> predicate, boolean expected) {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(mode, active);
assertEquals(expected, predicate.test(licenseState));
}
/**
* Checks the ack message going from the {@code from} license type to {@code to} license type.
* TODO: check the actual messages, not just the number of them! This was copied from previous license tests...
*/
void assertAckMesssages(String feature, OperationMode from, OperationMode to, int expectedMessages) {
String[] gotMessages = XPackLicenseState.ACKNOWLEDGMENT_MESSAGES.get(feature).apply(from, to);
assertEquals(expectedMessages, gotMessages.length);
}
static <T> T randomFrom(T[] values, Predicate<T> filter) {
return randomFrom(Arrays.stream(values).filter(filter).collect(Collectors.toList()));
}
static OperationMode randomMode() {
return randomFrom(OperationMode.values());
}
static OperationMode randomTrialStandardGoldOrPlatinumMode() {
return randomFrom(TRIAL, STANDARD, GOLD, PLATINUM);
}
static OperationMode randomTrialOrPlatinumMode() {
return randomFrom(TRIAL, PLATINUM);
}
public void testSecurityDefaults() {
XPackLicenseState licenseState = new XPackLicenseState();
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.ALL));
}
public void testSecurityBasic() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(BASIC, true);
assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
assertThat(licenseState.isAuditingAllowed(), is(false));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.NONE));
}
public void testSecurityBasicExpired() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(BASIC, false);
assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
assertThat(licenseState.isAuditingAllowed(), is(false));
assertThat(licenseState.isStatsAndHealthAllowed(), is(false));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.NONE));
}
public void testSecurityStandard() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(STANDARD, true);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
assertThat(licenseState.isAuditingAllowed(), is(false));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.NATIVE));
}
public void testSecurityStandardExpired() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(STANDARD, false);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
assertThat(licenseState.isAuditingAllowed(), is(false));
assertThat(licenseState.isStatsAndHealthAllowed(), is(false));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.NATIVE));
}
public void testSecurityGold() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(GOLD, true);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.DEFAULT));
}
public void testSecurityGoldExpired() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(GOLD, false);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(false));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(false));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.DEFAULT));
}
public void testSecurityPlatinum() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(PLATINUM, true);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.ALL));
}
public void testSecurityPlatinumExpired() {
XPackLicenseState licenseState = new XPackLicenseState();
licenseState.update(PLATINUM, false);
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(false));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(AllowedRealmType.ALL));
}
public void testSecurityAckBasicToNotGoldOrStandard() {
OperationMode toMode = randomFrom(OperationMode.values(), mode -> mode != GOLD && mode != STANDARD);
assertAckMesssages(Security.NAME, BASIC, toMode, 0);
}
public void testSecurityAckAnyToTrialOrPlatinum() {
assertAckMesssages(Security.NAME, randomMode(), randomTrialOrPlatinumMode(), 0);
}
public void testSecurityAckTrialStandardGoldOrPlatinumToBasic() {
assertAckMesssages(Security.NAME, randomTrialStandardGoldOrPlatinumMode(), BASIC, 3);
}
public void testSecurityAckAnyToStandard() {
OperationMode from = randomFrom(BASIC, GOLD, PLATINUM, TRIAL);
assertAckMesssages(Security.NAME, from, STANDARD, 4);
}
public void testSecurityAckBasicStandardTrialOrPlatinumToGold() {
OperationMode from = randomFrom(BASIC, PLATINUM, TRIAL, STANDARD);
assertAckMesssages(Security.NAME, from, GOLD, 2);
}
public void testMonitoringAckBasicToAny() {
assertAckMesssages(Monitoring.NAME, BASIC, randomMode(), 0);
}
public void testMonitoringAckAnyToTrialGoldOrPlatinum() {
assertAckMesssages(Monitoring.NAME, randomMode(), randomTrialStandardGoldOrPlatinumMode(), 0);
}
public void testMonitoringAckNotBasicToBasic() {
OperationMode from = randomFrom(STANDARD, GOLD, PLATINUM, TRIAL);
assertAckMesssages(Monitoring.NAME, from, BASIC, 2);
}
public void testMonitoringAllowed() {
assertAllowed(randomMode(), true, XPackLicenseState::isMonitoringAllowed, true);
assertAllowed(randomMode(), false, XPackLicenseState::isMonitoringAllowed, false);
}
public void testMonitoringUpdateRetention() {
OperationMode mode = randomFrom(STANDARD, GOLD, PLATINUM, TRIAL);
assertAllowed(mode, true, XPackLicenseState::isUpdateRetentionAllowed, true);
assertAllowed(BASIC, true, XPackLicenseState::isUpdateRetentionAllowed, false);
assertAllowed(MISSING, false, XPackLicenseState::isUpdateRetentionAllowed, false);
}
public void testWatcherPlatinumGoldTrial() throws Exception {
assertAllowed(randomFrom(TRIAL, GOLD, PLATINUM), true, XPackLicenseState::isWatcherAllowed, true);
}
public void testWatcherBasicStandardLicense() throws Exception {
assertAllowed(randomFrom(BASIC, STANDARD), true, XPackLicenseState::isWatcherAllowed, false);
}
public void testWatcherInactive() {
assertAllowed(randomFrom(BASIC, STANDARD), false, XPackLicenseState::isWatcherAllowed, false);
}
public void testWatcherInactivePlatinumGoldTrial() throws Exception {
assertAllowed(randomFrom(TRIAL, GOLD, PLATINUM), false, XPackLicenseState::isWatcherAllowed, false);
}
public void testGraphPlatinumTrial() throws Exception {
assertAllowed(TRIAL, true, XPackLicenseState::isGraphAllowed, true);
assertAllowed(PLATINUM, true, XPackLicenseState::isGraphAllowed, true);
}
public void testGraphBasic() throws Exception {
assertAllowed(BASIC, true, XPackLicenseState::isGraphAllowed, false);
}
public void testGraphStandard() throws Exception {
assertAllowed(STANDARD, true, XPackLicenseState::isGraphAllowed, false);
}
public void testGraphInactiveBasic() {
assertAllowed(BASIC, false, XPackLicenseState::isGraphAllowed, false);
}
public void testGraphInactivePlatinumTrial() throws Exception {
assertAllowed(TRIAL, false, XPackLicenseState::isGraphAllowed, false);
assertAllowed(PLATINUM, false, XPackLicenseState::isGraphAllowed, false);
}
}

View File

@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.XPackFeatureSet;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
@ -41,7 +42,7 @@ import static org.mockito.Mockito.when;
public class SecurityFeatureSetTests extends ESTestCase {
private Settings settings;
private SecurityLicenseState licenseState;
private XPackLicenseState licenseState;
private Realms realms;
private NamedWriteableRegistry namedWriteableRegistry;
private IPFilter ipFilter;
@ -52,7 +53,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
@Before
public void init() throws Exception {
settings = Settings.builder().put("path.home", createTempDir()).build();
licenseState = mock(SecurityLicenseState.class);
licenseState = mock(XPackLicenseState.class);
realms = mock(Realms.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
ipFilter = mock(IPFilter.class);
@ -70,7 +71,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
SecurityFeatureSet featureSet = new SecurityFeatureSet(settings, licenseState, realms, namedWriteableRegistry, rolesStore,
ipFilter, auditTrail, cryptoService);
boolean available = randomBoolean();
when(licenseState.authenticationAndAuthorizationEnabled()).thenReturn(available);
when(licenseState.isAuthAllowed()).thenReturn(available);
assertThat(featureSet.available(), is(available));
}
@ -106,7 +107,7 @@ public class SecurityFeatureSetTests extends ESTestCase {
public void testUsage() throws Exception {
boolean authcAuthzAvailable = randomBoolean();
when(licenseState.authenticationAndAuthorizationEnabled()).thenReturn(authcAuthzAvailable);
when(licenseState.isAuthAllowed()).thenReturn(authcAuthzAvailable);
Settings.Builder settings = Settings.builder().put(this.settings);

View File

@ -1,126 +0,0 @@
/*
* 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.xpack.security;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.Licensee;
import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType;
import org.elasticsearch.test.ESTestCase;
import static org.hamcrest.Matchers.is;
/**
* Unit tests for the {@link SecurityLicenseState}
*/
public class SecurityLicenseStateTests extends ESTestCase {
public void testDefaults() {
SecurityLicenseState licenseState = new SecurityLicenseState();
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(true));
assertThat(licenseState.auditingEnabled(), is(true));
assertThat(licenseState.statsAndHealthEnabled(), is(true));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(true));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.ALL));
}
public void testBasic() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.BASIC, true));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(false));
assertThat(licenseState.ipFilteringEnabled(), is(false));
assertThat(licenseState.auditingEnabled(), is(false));
assertThat(licenseState.statsAndHealthEnabled(), is(true));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.NONE));
}
public void testBasicExpired() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.BASIC, false));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(false));
assertThat(licenseState.ipFilteringEnabled(), is(false));
assertThat(licenseState.auditingEnabled(), is(false));
assertThat(licenseState.statsAndHealthEnabled(), is(false));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.NONE));
}
public void testStandard() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(OperationMode.STANDARD, true));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(false));
assertThat(licenseState.auditingEnabled(), is(false));
assertThat(licenseState.statsAndHealthEnabled(), is(true));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.NATIVE));
}
public void testStandardExpired() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(OperationMode.STANDARD, false));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(false));
assertThat(licenseState.auditingEnabled(), is(false));
assertThat(licenseState.statsAndHealthEnabled(), is(false));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.NATIVE));
}
public void testGold() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.GOLD, true));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(true));
assertThat(licenseState.auditingEnabled(), is(true));
assertThat(licenseState.statsAndHealthEnabled(), is(true));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.DEFAULT));
}
public void testGoldExpired() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.GOLD, false));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(true));
assertThat(licenseState.auditingEnabled(), is(true));
assertThat(licenseState.statsAndHealthEnabled(), is(false));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(false));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.DEFAULT));
}
public void testPlatinum() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.PLATINUM, true));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(true));
assertThat(licenseState.auditingEnabled(), is(true));
assertThat(licenseState.statsAndHealthEnabled(), is(true));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(true));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.ALL));
}
public void testPlatinumExpired() {
SecurityLicenseState licenseState = new SecurityLicenseState();
licenseState.updateStatus(new Licensee.Status(License.OperationMode.PLATINUM, false));
assertThat(licenseState.authenticationAndAuthorizationEnabled(), is(true));
assertThat(licenseState.ipFilteringEnabled(), is(true));
assertThat(licenseState.auditingEnabled(), is(true));
assertThat(licenseState.statsAndHealthEnabled(), is(false));
assertThat(licenseState.documentAndFieldLevelSecurityEnabled(), is(true));
assertThat(licenseState.enabledRealmType(), is(EnabledRealmType.ALL));
}
}

View File

@ -1,80 +0,0 @@
/*
* 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.xpack.security;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
import org.elasticsearch.license.plugin.core.Licensee.Status;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* Tests {@link SecurityLicensee}.
* <p>
* If you change the behavior of these tests, then it means that licensing changes for Security!
*/
public class SecurityLicenseeTests extends AbstractLicenseeTestCase {
private final SecurityLicenseState securityLicenseState = mock(SecurityLicenseState.class);
public void testOnChangeModifiesSecurityLicenseState() {
Status status = mock(Status.class);
SecurityLicensee licensee = new SecurityLicensee(Settings.EMPTY, securityLicenseState);
licensee.onChange(status);
assertSame(status, licensee.getStatus());
verify(securityLicenseState).updateStatus(status);
verifyNoMoreInteractions(securityLicenseState);
}
public void testAcknowledgementMessagesFromBasicToAnyNotGoldOrStandardIsNoOp() {
assertEmptyAck(OperationMode.BASIC,
randomFrom(OperationMode.values(), mode -> mode != OperationMode.GOLD && mode != OperationMode.STANDARD),
this::buildLicensee);
}
public void testAcknowledgementMessagesFromAnyToTrialOrPlatinumIsNoOp() {
assertEmptyAck(randomMode(), randomTrialOrPlatinumMode(), this::buildLicensee);
}
public void testAcknowledgementMessagesFromTrialStandardGoldOrPlatinumToBasicNotesLimits() {
OperationMode from = randomTrialStandardGoldOrPlatinumMode();
OperationMode to = OperationMode.BASIC;
String[] messages = ackLicenseChange(from, to, this::buildLicensee);
// leaving messages up to inspection
assertThat(fromToMessage(from, to), messages.length, equalTo(3));
}
public void testAcknowlegmentMessagesFromAnyToStandardNotesLimits() {
OperationMode from = randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.PLATINUM, OperationMode.TRIAL);
OperationMode to = OperationMode.STANDARD;
String[] messages = ackLicenseChange(from, to, this::buildLicensee);
// leaving messages up to inspection
assertThat(fromToMessage(from, to), messages.length, equalTo(4));
}
public void testAcknowledgementMessagesFromBasicStandardTrialOrPlatinumToGoldNotesLimits() {
OperationMode from = randomFrom(OperationMode.BASIC, OperationMode.PLATINUM, OperationMode.TRIAL, OperationMode.STANDARD);
String[] messages = ackLicenseChange(from, OperationMode.GOLD, this::buildLicensee);
// leaving messages up to inspection
assertThat(messages.length, equalTo(2));
}
private SecurityLicensee buildLicensee() {
return new SecurityLicensee(Settings.EMPTY, securityLicenseState);
}
}

View File

@ -1,79 +0,0 @@
/*
* 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.xpack.security;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.integration.LicensingTests;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.security.transport.SecurityServerTransportService;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.BeforeClass;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
public class SecurityPluginEnabledDisabledTests extends SecurityIntegTestCase {
private static boolean enabled;
@BeforeClass
public static void init() {
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 Class<? extends XPackPlugin> xpackPluginClass() {
return LicensingTests.InternalXPackPlugin.class;
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
logger.info("******* security is {}", enabled ? "enabled" : "disabled");
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put(XPackPlugin.featureEnabledSetting(Security.NAME), enabled)
.put(NetworkModule.HTTP_ENABLED.getKey(), true)
.build();
}
@Override
protected Settings transportClientSettings() {
return Settings.builder()
.put(super.transportClientSettings())
.put(XPackPlugin.featureEnabledSetting(Security.NAME), enabled)
.build();
}
public void testTransportEnabledDisabled() throws Exception {
for (TransportService service : internalCluster().getInstances(TransportService.class)) {
Matcher<TransportService> matcher = instanceOf(SecurityServerTransportService.class);
if (!enabled) {
matcher = not(matcher);
}
assertThat(service, matcher);
}
for (Transport transport : internalCluster().getInstances(Transport.class)) {
Matcher<Transport> matcher = instanceOf(SecurityNetty3Transport.class);
if (!enabled) {
matcher = not(matcher);
}
assertThat(transport, matcher);
}
}
}

View File

@ -14,6 +14,7 @@ import java.util.Map;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.extensions.XPackExtension;
@ -52,7 +53,7 @@ public class SecurityTests extends ESTestCase {
Settings settings = Settings.builder().put(testSettings)
.put("path.home", createTempDir()).build();
Environment env = new Environment(settings);
Security security = new Security(settings, env);
Security security = new Security(settings, env, new XPackLicenseState());
ThreadPool threadPool = mock(ThreadPool.class);
ClusterService clusterService = mock(ClusterService.class);
return security.createComponents(null, threadPool, clusterService, null, Arrays.asList(extensions));

View File

@ -27,7 +27,7 @@ import static org.hamcrest.CoreMatchers.is;
public class VersionCompatibilityTests extends ESTestCase {
public void testCompatibility() {
/**
* see https://github.com/elasticsearch/elasticsearch/issues/9372 {@link SecurityLicensee}
* see https://github.com/elasticsearch/elasticsearch/issues/9372 {@link org.elasticsearch.license.plugin.core.XPackLicenseState}
* Once es core supports merging cluster level custom metadata (licenses in our case), the tribe node will see some license
* coming from the tribe and everything will be ok.
*

View File

@ -18,7 +18,6 @@ import org.elasticsearch.tasks.Task;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.SecurityContext;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.action.SecurityActionMapper;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Authentication;
@ -28,6 +27,7 @@ import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.junit.Before;
import static org.hamcrest.Matchers.equalTo;
@ -50,7 +50,7 @@ public class SecurityActionFilterTests extends ESTestCase {
private AuthorizationService authzService;
private CryptoService cryptoService;
private AuditTrailService auditTrail;
private SecurityLicenseState securityLicenseState;
private XPackLicenseState licenseState;
private SecurityActionFilter filter;
@Before
@ -59,12 +59,12 @@ public class SecurityActionFilterTests extends ESTestCase {
authzService = mock(AuthorizationService.class);
cryptoService = mock(CryptoService.class);
auditTrail = mock(AuditTrailService.class);
securityLicenseState = mock(SecurityLicenseState.class);
when(securityLicenseState.authenticationAndAuthorizationEnabled()).thenReturn(true);
when(securityLicenseState.statsAndHealthEnabled()).thenReturn(true);
licenseState = mock(XPackLicenseState.class);
when(licenseState.isAuthAllowed()).thenReturn(true);
when(licenseState.isStatsAndHealthAllowed()).thenReturn(true);
ThreadPool threadPool = mock(ThreadPool.class);
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
filter = new SecurityActionFilter(Settings.EMPTY, authcService, authzService, cryptoService, auditTrail, securityLicenseState,
filter = new SecurityActionFilter(Settings.EMPTY, authcService, authzService, cryptoService, auditTrail, licenseState,
new SecurityActionMapper(), new HashSet<>(), threadPool, mock(SecurityContext.class));
}
@ -135,7 +135,7 @@ public class SecurityActionFilterTests extends ESTestCase {
ActionListener listener = mock(ActionListener.class);
ActionFilterChain chain = mock(ActionFilterChain.class);
Task task = mock(Task.class);
when(securityLicenseState.authenticationAndAuthorizationEnabled()).thenReturn(false);
when(licenseState.isAuthAllowed()).thenReturn(false);
filter.apply(task, "_action", request, listener, chain);
verifyZeroInteractions(authcService);
verifyZeroInteractions(authzService);

View File

@ -7,7 +7,7 @@ package org.elasticsearch.xpack.security.audit;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authc.AuthenticationToken;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
@ -38,8 +38,8 @@ public class AuditTrailServiceTests extends ESTestCase {
private AuthenticationToken token;
private TransportMessage message;
private RestRequest restRequest;
private SecurityLicenseState securityLicenseState;
private boolean auditingEnabled;
private XPackLicenseState licenseState;
private boolean isAuditingAllowed;
@Before
public void init() throws Exception {
@ -48,10 +48,10 @@ public class AuditTrailServiceTests extends ESTestCase {
auditTrailsBuilder.add(mock(AuditTrail.class));
}
auditTrails = unmodifiableList(auditTrailsBuilder);
securityLicenseState = mock(SecurityLicenseState.class);
service = new AuditTrailService(Settings.EMPTY, auditTrails, securityLicenseState);
auditingEnabled = randomBoolean();
when(securityLicenseState.auditingEnabled()).thenReturn(auditingEnabled);
licenseState = mock(XPackLicenseState.class);
service = new AuditTrailService(Settings.EMPTY, auditTrails, licenseState);
isAuditingAllowed = randomBoolean();
when(licenseState.isAuditingAllowed()).thenReturn(isAuditingAllowed);
token = mock(AuthenticationToken.class);
message = mock(TransportMessage.class);
restRequest = mock(RestRequest.class);
@ -59,8 +59,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailed() throws Exception {
service.authenticationFailed(token, "_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed(token, "_action", message);
}
@ -71,8 +71,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailedNoToken() throws Exception {
service.authenticationFailed("_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed("_action", message);
}
@ -83,8 +83,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailedRestNoToken() throws Exception {
service.authenticationFailed(restRequest);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed(restRequest);
}
@ -95,8 +95,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailedRest() throws Exception {
service.authenticationFailed(token, restRequest);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed(token, restRequest);
}
@ -107,8 +107,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailedRealm() throws Exception {
service.authenticationFailed("_realm", token, "_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed("_realm", token, "_action", message);
}
@ -119,8 +119,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAuthenticationFailedRestRealm() throws Exception {
service.authenticationFailed("_realm", token, restRequest);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).authenticationFailed("_realm", token, restRequest);
}
@ -131,8 +131,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAnonymousAccess() throws Exception {
service.anonymousAccessDenied("_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).anonymousAccessDenied("_action", message);
}
@ -144,8 +144,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAccessGranted() throws Exception {
User user = new User("_username", "r1");
service.accessGranted(user, "_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).accessGranted(user, "_action", message);
}
@ -157,8 +157,8 @@ public class AuditTrailServiceTests extends ESTestCase {
public void testAccessDenied() throws Exception {
User user = new User("_username", "r1");
service.accessDenied(user, "_action", message);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).accessDenied(user, "_action", message);
}
@ -171,8 +171,8 @@ public class AuditTrailServiceTests extends ESTestCase {
InetAddress inetAddress = InetAddress.getLoopbackAddress();
SecurityIpFilterRule rule = randomBoolean() ? SecurityIpFilterRule.ACCEPT_ALL : IPFilter.DEFAULT_PROFILE_ACCEPT_ALL;
service.connectionGranted(inetAddress, "client", rule);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).connectionGranted(inetAddress, "client", rule);
}
@ -185,8 +185,8 @@ public class AuditTrailServiceTests extends ESTestCase {
InetAddress inetAddress = InetAddress.getLoopbackAddress();
SecurityIpFilterRule rule = new SecurityIpFilterRule(false, "_all");
service.connectionDenied(inetAddress, "client", rule);
verify(securityLicenseState).auditingEnabled();
if (auditingEnabled) {
verify(licenseState).isAuditingAllowed();
if (isAuditingAllowed) {
for (AuditTrail auditTrail : auditTrails) {
verify(auditTrail).connectionDenied(inetAddress, "client", rule);
}

View File

@ -16,13 +16,12 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.FakeRestRequest;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportMessage;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
import org.elasticsearch.xpack.security.authc.AuthenticationService.Authenticator;
@ -88,11 +87,11 @@ public class AuthenticationServiceTests extends ESTestCase {
.put("path.home", createTempDir())
.put("node.name", "authc_test")
.build();
SecurityLicenseState securityLicenseState = mock(SecurityLicenseState.class);
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.ALL);
when(securityLicenseState.authenticationAndAuthorizationEnabled()).thenReturn(true);
realms = new Realms(Settings.EMPTY, new Environment(settings), Collections.<String, Realm.Factory>emptyMap(), securityLicenseState,
mock(ReservedRealm.class)) {
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.allowedRealmType()).thenReturn(XPackLicenseState.AllowedRealmType.ALL);
when(licenseState.isAuthAllowed()).thenReturn(true);
realms = new Realms(Settings.EMPTY, new Environment(settings), Collections.<String, Realm.Factory>emptyMap(),
licenseState, mock(ReservedRealm.class)) {
@Override
protected void doStart() {

View File

@ -8,13 +8,13 @@ package org.elasticsearch.xpack.security.authc;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.xpack.security.SecurityLicenseState.EnabledRealmType;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
import org.elasticsearch.xpack.security.authc.file.FileRealm;
import org.elasticsearch.xpack.security.authc.ldap.LdapRealm;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState.AllowedRealmType;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
@ -35,7 +35,7 @@ import static org.mockito.Mockito.when;
public class RealmsTests extends ESTestCase {
private Map<String, Realm.Factory> factories;
private SecurityLicenseState securityLicenseState;
private XPackLicenseState licenseState;
private ReservedRealm reservedRealm;
@Before
@ -47,10 +47,10 @@ public class RealmsTests extends ESTestCase {
String name = "type_" + i;
factories.put(name, config -> new DummyRealm(name, config));
}
securityLicenseState = mock(SecurityLicenseState.class);
licenseState = mock(XPackLicenseState.class);
reservedRealm = mock(ReservedRealm.class);
when(securityLicenseState.authenticationAndAuthorizationEnabled()).thenReturn(true);
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.ALL);
when(licenseState.isAuthAllowed()).thenReturn(true);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.ALL);
}
public void testWithSettings() throws Exception {
@ -69,7 +69,7 @@ public class RealmsTests extends ESTestCase {
}
Settings settings = builder.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
Iterator<Realm> iterator = realms.iterator();
@ -98,7 +98,7 @@ public class RealmsTests extends ESTestCase {
.build();
Environment env = new Environment(settings);
try {
new Realms(settings, env, factories, securityLicenseState, reservedRealm).start();
new Realms(settings, env, factories, licenseState, reservedRealm).start();
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("multiple [file] realms are configured"));
@ -107,7 +107,7 @@ public class RealmsTests extends ESTestCase {
public void testWithEmptySettings() throws Exception {
Realms realms = new Realms(Settings.EMPTY, new Environment(Settings.builder().put("path.home", createTempDir()).build()),
factories, securityLicenseState, reservedRealm);
factories, licenseState, reservedRealm);
realms.start();
Iterator<Realm> iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
@ -140,7 +140,7 @@ public class RealmsTests extends ESTestCase {
}
Settings settings = builder.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
// this is the iterator when licensed
@ -158,7 +158,7 @@ public class RealmsTests extends ESTestCase {
i++;
}
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.DEFAULT);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.DEFAULT);
iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
@ -174,7 +174,7 @@ public class RealmsTests extends ESTestCase {
assertThat(realm.name(), equalTo("default_" + NativeRealm.TYPE));
assertThat(iter.hasNext(), is(false));
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.NATIVE);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.NATIVE);
iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
@ -202,7 +202,7 @@ public class RealmsTests extends ESTestCase {
.put("xpack.security.authc.realms.custom.order", "1");
Settings settings = builder.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
Iterator<Realm> iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
@ -219,7 +219,7 @@ public class RealmsTests extends ESTestCase {
}
assertThat(types, contains("ldap", "type_0"));
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.DEFAULT);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.DEFAULT);
iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
realm = iter.next();
@ -232,7 +232,7 @@ public class RealmsTests extends ESTestCase {
}
assertThat(i, is(1));
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.NATIVE);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.NATIVE);
iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
realm = iter.next();
@ -259,7 +259,7 @@ public class RealmsTests extends ESTestCase {
.put("xpack.security.authc.realms.native.order", "1");
Settings settings = builder.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
Iterator<Realm> iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
@ -273,7 +273,7 @@ public class RealmsTests extends ESTestCase {
assertThat(realm.type(), is(type));
assertThat(iter.hasNext(), is(false));
when(securityLicenseState.enabledRealmType()).thenReturn(EnabledRealmType.NATIVE);
when(licenseState.allowedRealmType()).thenReturn(AllowedRealmType.NATIVE);
iter = realms.iterator();
assertThat(iter.hasNext(), is(true));
realm = iter.next();
@ -305,7 +305,7 @@ public class RealmsTests extends ESTestCase {
}
Settings settings = builder.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
Iterator<Realm> iterator = realms.iterator();
Realm realm = iterator.next();
@ -343,12 +343,12 @@ public class RealmsTests extends ESTestCase {
.put("xpack.security.authc.realms.realm_1.order", 0)
.build();
Environment env = new Environment(settings);
Realms realms = new Realms(settings, env, factories, securityLicenseState, reservedRealm);
Realms realms = new Realms(settings, env, factories, licenseState, reservedRealm);
realms.start();
assertThat(realms.iterator().hasNext(), is(true));
when(securityLicenseState.authenticationAndAuthorizationEnabled()).thenReturn(false);
when(licenseState.isAuthAllowed()).thenReturn(false);
assertThat(realms.iterator().hasNext(), is(false));
}

View File

@ -34,8 +34,8 @@ import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
@ -78,8 +78,8 @@ public class SecurityIndexSearcherWrapperIntegrationTests extends ESTestCase {
}
});
SecurityLicenseState licenseState = mock(SecurityLicenseState.class);
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(true);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isDocumentAndFieldLevelSecurityAllowed()).thenReturn(true);
SecurityIndexSearcherWrapper wrapper = new SecurityIndexSearcherWrapper(indexSettings, queryShardContext, mapperService,
bitsetFilterCache, threadContext, licenseState, scriptService) {

View File

@ -63,7 +63,7 @@ import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.aggregations.LeafBucketCollector;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.security.authz.accesscontrol.DocumentSubsetReader.DocumentSubsetDirectoryReader;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
import org.elasticsearch.xpack.security.user.User;
@ -104,7 +104,7 @@ public class SecurityIndexSearcherWrapperUnitTests extends ESTestCase {
private ScriptService scriptService;
private SecurityIndexSearcherWrapper securityIndexSearcherWrapper;
private ElasticsearchDirectoryReader esIn;
private SecurityLicenseState licenseState;
private XPackLicenseState licenseState;
private IndexSettings indexSettings;
@Before
@ -119,8 +119,8 @@ public class SecurityIndexSearcherWrapperUnitTests extends ESTestCase {
new IndicesModule(new NamedWriteableRegistry(), emptyList()).getMapperRegistry(), () -> null);
ShardId shardId = new ShardId(index, 0);
licenseState = mock(SecurityLicenseState.class);
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(true);
licenseState = mock(XPackLicenseState.class);
when(licenseState.isDocumentAndFieldLevelSecurityAllowed()).thenReturn(true);
threadContext = new ThreadContext(Settings.EMPTY);
IndexShard indexShard = mock(IndexShard.class);
when(indexShard.shardId()).thenReturn(shardId);
@ -175,7 +175,7 @@ public class SecurityIndexSearcherWrapperUnitTests extends ESTestCase {
}
public void testWrapReaderWhenFeatureDisabled() throws Exception {
when(licenseState.documentAndFieldLevelSecurityEnabled()).thenReturn(false);
when(licenseState.isDocumentAndFieldLevelSecurityAllowed()).thenReturn(false);
securityIndexSearcherWrapper =
new SecurityIndexSearcherWrapper(indexSettings, null, mapperService, null, threadContext, licenseState, scriptService);
DirectoryReader reader = securityIndexSearcherWrapper.wrap(esIn);

View File

@ -13,10 +13,10 @@ import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestFilterChain;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.junit.Before;
import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError;
@ -34,7 +34,7 @@ public class SecurityRestFilterTests extends ESTestCase {
private RestChannel channel;
private RestFilterChain chain;
private SecurityRestFilter filter;
private SecurityLicenseState licenseState;
private XPackLicenseState licenseState;
@Before
public void init() throws Exception {
@ -42,8 +42,8 @@ public class SecurityRestFilterTests extends ESTestCase {
RestController restController = mock(RestController.class);
channel = mock(RestChannel.class);
chain = mock(RestFilterChain.class);
licenseState = mock(SecurityLicenseState.class);
when(licenseState.authenticationAndAuthorizationEnabled()).thenReturn(true);
licenseState = mock(XPackLicenseState.class);
when(licenseState.isAuthAllowed()).thenReturn(true);
ThreadPool threadPool = mock(ThreadPool.class);
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
filter = new SecurityRestFilter(authcService, restController, Settings.EMPTY, threadPool, licenseState);
@ -61,7 +61,7 @@ public class SecurityRestFilterTests extends ESTestCase {
public void testProcessBasicLicense() throws Exception {
RestRequest request = mock(RestRequest.class);
when(licenseState.authenticationAndAuthorizationEnabled()).thenReturn(false);
when(licenseState.isAuthAllowed()).thenReturn(false);
filter.process(request, channel, null, chain);
verify(chain).continueProcessing(request, channel, null);
verifyZeroInteractions(channel, authcService);

View File

@ -17,7 +17,9 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.transport.MockTcpTransportPlugin;
import org.elasticsearch.xpack.security.action.SecurityActionMapper;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.threadpool.ThreadPool;
@ -288,8 +290,8 @@ public class TransportFilterTests extends ESIntegTestCase {
AuthenticationService authcService, AuthorizationService authzService,
SecurityActionMapper actionMapper, ClientTransportFilter clientTransportFilter) {
super(settings, transport, threadPool, authcService, authzService, actionMapper, clientTransportFilter,
mock(SecurityLicenseState.class));
when(licenseState.authenticationAndAuthorizationEnabled()).thenReturn(true);
mock(XPackLicenseState.class));
when(licenseState.isAuthAllowed()).thenReturn(true);
}
@Override

View File

@ -15,7 +15,7 @@ import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.transport.Transport;
@ -45,7 +45,7 @@ import static org.mockito.Mockito.when;
*/
public class IPFilterTests extends ESTestCase {
private IPFilter ipFilter;
private SecurityLicenseState licenseState;
private XPackLicenseState licenseState;
private AuditTrailService auditTrail;
private Transport transport;
private HttpServerTransport httpTransport;
@ -53,8 +53,8 @@ public class IPFilterTests extends ESTestCase {
@Before
public void init() {
licenseState = mock(SecurityLicenseState.class);
when(licenseState.ipFilteringEnabled()).thenReturn(true);
licenseState = mock(XPackLicenseState.class);
when(licenseState.isIpFilteringAllowed()).thenReturn(true);
auditTrail = mock(AuditTrailService.class);
clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(
IPFilter.HTTP_FILTER_ALLOW_SETTING,
@ -218,7 +218,7 @@ public class IPFilterTests extends ESTestCase {
Settings settings = Settings.builder()
.put("xpack.security.transport.filter.deny", "_all")
.build();
when(licenseState.ipFilteringEnabled()).thenReturn(false);
when(licenseState.isIpFilteringAllowed()).thenReturn(false);
ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState);
ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses());
@ -229,7 +229,7 @@ public class IPFilterTests extends ESTestCase {
verifyZeroInteractions(auditTrail);
// for sanity enable license and check that it is denied
when(licenseState.ipFilteringEnabled()).thenReturn(true);
when(licenseState.isIpFilteringAllowed()).thenReturn(true);
ipFilter = new IPFilter(settings, auditTrail, clusterSettings, licenseState);
ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses());

View File

@ -13,8 +13,7 @@ import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.xpack.security.audit.AuditTrail;
import org.elasticsearch.xpack.security.SecurityLicenseState;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.elasticsearch.test.ESTestCase;
@ -67,8 +66,8 @@ public class IPFilterNetty3UpstreamHandlerTests extends ESTestCase {
IPFilter.TRANSPORT_FILTER_ALLOW_SETTING,
IPFilter.TRANSPORT_FILTER_DENY_SETTING,
TransportSettings.TRANSPORT_PROFILES_SETTING)));
SecurityLicenseState licenseState = mock(SecurityLicenseState.class);
when(licenseState.ipFilteringEnabled()).thenReturn(true);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isIpFilteringAllowed()).thenReturn(true);
AuditTrailService auditTrailService = new AuditTrailService(settings, Collections.emptyList(), licenseState);
IPFilter ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState);
ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses());

View File

@ -0,0 +1,349 @@
/*
* 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.license.plugin.core;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.BiFunction;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.xpack.graph.Graph;
import org.elasticsearch.xpack.monitoring.Monitoring;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.watcher.Watcher;
/**
* A holder for the current state of the license for all xpack features.
*/
public class XPackLicenseState {
/** Messages for each feature which are printed when the license expires. */
static final Map<String, String[]> EXPIRATION_MESSAGES;
static {
Map<String, String[]> messages = new LinkedHashMap<>();
messages.put(Security.NAME, new String[] {
"Cluster health, cluster stats and indices stats operations are blocked",
"All data operations (read and write) continue to work"
});
messages.put(Watcher.NAME, new String[] {
"PUT / GET watch APIs are disabled, DELETE watch API continues to work",
"Watches execute and write to the history",
"The actions of the watches don't execute"
});
messages.put(Monitoring.NAME, new String[] {
"The agent will stop collecting cluster and indices metrics",
"The agent will stop automatically cleaning indices older than [xpack.monitoring.history.duration]"
});
messages.put(Graph.NAME, new String[] {
"Graph explore APIs are disabled"
});
EXPIRATION_MESSAGES = Collections.unmodifiableMap(messages);
}
/**
* Messages for each feature which are printed when the license type changes.
* The value is a function taking the old and new license type, and returns the messages for that feature.
*/
static final Map<String, BiFunction<OperationMode, OperationMode, String[]>> ACKNOWLEDGMENT_MESSAGES;
static {
Map<String, BiFunction<OperationMode, OperationMode, String[]>> messages = new LinkedHashMap<>();
messages.put(Security.NAME, XPackLicenseState::securityAcknowledgementMessages);
messages.put(Watcher.NAME, XPackLicenseState::watcherAcknowledgementMessages);
messages.put(Monitoring.NAME, XPackLicenseState::monitoringAcknowledgementMessages);
messages.put(Graph.NAME, XPackLicenseState::graphAcknowledgementMessages);
ACKNOWLEDGMENT_MESSAGES = Collections.unmodifiableMap(messages);
}
private static String[] securityAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] {
"The following X-Pack security functionality will be disabled: authentication, authorization, " +
"ip filtering, and auditing. Please restart your node after applying the license.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
break;
case GOLD:
switch (currentMode) {
case BASIC:
case STANDARD:
// ^^ though technically it was already disabled, it's not bad to remind them
case TRIAL:
case PLATINUM:
return new String[] {
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
break;
case STANDARD:
switch (currentMode) {
case BASIC:
// ^^ though technically it was already disabled, it's not bad to remind them
case GOLD:
case PLATINUM:
case TRIAL:
return new String[] {
"Authentication will be limited to the native realms.",
"IP filtering and auditing will be disabled.",
"Field and document level access control will be disabled.",
"Custom realms will be ignored."
};
}
}
return Strings.EMPTY_ARRAY;
}
private static String[] watcherAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] { "Watcher will be disabled" };
}
break;
}
return Strings.EMPTY_ARRAY;
}
private static String[] monitoringAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] {
LoggerMessageFormat.format(
"Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
"running multiple clusters, users won't be able to access the clusters with\n" +
"[{}] licenses from within a single X-Pack Kibana instance. You will have to deploy a\n" +
"separate and dedicated X-pack Kibana instance for each [{}] cluster you wish to monitor.",
newMode, newMode, newMode),
LoggerMessageFormat.format(
"Automatic index cleanup is locked to {} days for clusters with [{}] license.",
MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newMode)
};
}
break;
}
return Strings.EMPTY_ARRAY;
}
private static String[] graphAcknowledgementMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
case STANDARD:
case GOLD:
switch (currentMode) {
case TRIAL:
case PLATINUM:
return new String[] { "Graph will be disabled" };
}
break;
}
return Strings.EMPTY_ARRAY;
}
/** A wrapper for the license mode and state, to allow atomically swapping. */
private static class Status {
/** The current "mode" of the license (ie license type). */
final OperationMode mode;
/** True if the license is active, or false if it is expired. */
final boolean active;
Status(OperationMode mode, boolean active) {
this.mode = mode;
this.active = active;
}
}
private volatile Status status = new Status(OperationMode.TRIAL, true);
/** Updates the current state of the license, which will change what features are available. */
void update(OperationMode mode, boolean active) {
status = new Status(mode, active);
}
/** Return the current license type. */
public OperationMode getOperationMode() {
return status.mode;
}
/** Return true if the license is currently within its time boundaries, false otherwise. */
public boolean isActive() {
return status.active;
}
/**
* @return true if authentication and authorization should be enabled. this does not indicate what realms are available
* @see #allowedRealmType() for the enabled realms
*/
public boolean isAuthAllowed() {
OperationMode mode = status.mode;
return mode == OperationMode.STANDARD || mode == OperationMode.GOLD || mode == OperationMode.PLATINUM
|| mode == OperationMode.TRIAL;
}
/**
* @return true if IP filtering should be enabled
*/
public boolean isIpFilteringAllowed() {
OperationMode mode = status.mode;
return mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL;
}
/**
* @return true if auditing should be enabled
*/
public boolean isAuditingAllowed() {
OperationMode mode = status.mode;
return mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL;
}
/**
* Indicates whether the stats and health API calls should be allowed. If a license is expired and past the grace
* period then we deny these calls.
*
* @return true if the license allows for the stats and health APIs to be used.
*/
public boolean isStatsAndHealthAllowed() {
return status.active;
}
/**
* Determine if Document Level Security (DLS) and Field Level Security (FLS) should be enabled.
* <p>
* DLS and FLS are only disabled when the mode is not:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
* Note: This does not consider the <em>state</em> of the license so that Security does not suddenly leak information!
*
* @return {@code true} to enable DLS and FLS. Otherwise {@code false}.
*/
public boolean isDocumentAndFieldLevelSecurityAllowed() {
OperationMode mode = status.mode;
return mode == OperationMode.TRIAL || mode == OperationMode.PLATINUM;
}
/** Classes of realms that may be available based on the license type. */
public enum AllowedRealmType {
NONE,
NATIVE,
DEFAULT,
ALL
}
/**
* @return the type of realms that are enabled based on the license {@link OperationMode}
*/
public AllowedRealmType allowedRealmType() {
switch (status.mode) {
case PLATINUM:
case TRIAL:
return AllowedRealmType.ALL;
case GOLD:
return AllowedRealmType.DEFAULT;
case STANDARD:
return AllowedRealmType.NATIVE;
default:
return AllowedRealmType.NONE;
}
}
/**
* Determine if Watcher is available based on the current license.
* <p>
* Watcher is available if the license is active (hasn't expired) and of one of the following types:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#GOLD}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean isWatcherAllowed() {
// status is volatile, so a local variable is used for a consistent view
Status localStatus = status;
if (localStatus.active == false) {
return false;
}
switch (localStatus.mode) {
case TRIAL:
case GOLD:
case PLATINUM:
return true;
default:
return false;
}
}
/**
* Monitoring is always available as long as there is a valid license
*
* @return true
*/
public boolean isMonitoringAllowed() {
return status.active;
}
/**
* Determine if the current license allows the retention of indices to be modified.
* <p>
* Only users with a non-{@link OperationMode#BASIC} license can update the retention period.
* <p>
* Note: This does not consider the <em>state</em> of the license so that any change is remembered for when they fix their license.
*
* @return {@code true} if the user is allowed to modify the retention. Otherwise {@code false}.
*/
public boolean isUpdateRetentionAllowed() {
final OperationMode mode = status.mode;
return mode != OperationMode.BASIC && mode != OperationMode.MISSING;
}
/**
* Determine if Graph Exploration should be enabled.
* <p>
* Exploration is only disabled when the license has expired or if the mode is not:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean isGraphAllowed() {
// status is volatile
Status localStatus = status;
OperationMode operationMode = localStatus.mode;
boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
return licensed && localStatus.active;
}
}

View File

@ -30,6 +30,7 @@ import org.elasticsearch.common.component.LifecycleComponent;
import org.elasticsearch.common.inject.Binder;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.multibindings.Multibinder;
import org.elasticsearch.common.inject.util.Providers;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
@ -37,6 +38,7 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.license.plugin.Licensing;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.plugins.ActionPlugin;
import org.elasticsearch.plugins.IngestPlugin;
import org.elasticsearch.plugins.Plugin;
@ -121,6 +123,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
protected boolean transportClientMode;
protected final XPackExtensionsService extensionsService;
protected XPackLicenseState licenseState;
protected Licensing licensing;
protected Security security;
protected Monitoring monitoring;
@ -132,9 +135,10 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
this.settings = settings;
this.transportClientMode = transportClientMode(settings);
this.env = transportClientMode ? null : new Environment(settings);
this.licenseState = new XPackLicenseState();
this.licensing = new Licensing(settings);
this.security = new Security(settings, env);
this.security = new Security(settings, env, licenseState);
this.monitoring = new Monitoring(settings);
this.watcher = new Watcher(settings);
this.graph = new Graph(settings);
@ -171,6 +175,8 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
modules.add(new TextTemplateModule());
// Note: this only exists so LicenseService subclasses can be bound in mock tests
modules.addAll(licensing.nodeModules());
} else {
modules.add(b -> b.bind(XPackLicenseState.class).toProvider(Providers.of(null)));
}
return modules;
}
@ -190,8 +196,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I
final InternalClient internalClient = new InternalClient(settings, threadPool, client, security.getCryptoService());
components.add(internalClient);
components.addAll(licensing.createComponents(clusterService, getClock(), env, resourceWatcherService,
security.getSecurityLicenseState()));
components.addAll(licensing.createComponents(clusterService, getClock(), env, resourceWatcherService, licenseState));
components.addAll(security.createComponents(internalClient, threadPool, clusterService, resourceWatcherService,
extensionsService.getExtensions()));

View File

@ -12,6 +12,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.XPackFeatureSet;
import java.io.IOException;
@ -24,15 +25,15 @@ import java.util.Map;
public class WatcherFeatureSet implements XPackFeatureSet {
private final boolean enabled;
private final WatcherLicensee licensee;
private final XPackLicenseState licenseState;
private final WatcherService watcherService;
@Inject
public WatcherFeatureSet(Settings settings, @Nullable WatcherLicensee licensee, NamedWriteableRegistry namedWriteableRegistry,
public WatcherFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, NamedWriteableRegistry namedWriteableRegistry,
@Nullable WatcherService watcherService) {
this.watcherService = watcherService;
this.enabled = Watcher.enabled(settings);
this.licensee = licensee;
this.licenseState = licenseState;
namedWriteableRegistry.register(Usage.class, Usage.writeableName(Watcher.NAME), Usage::new);
}
@ -48,7 +49,7 @@ public class WatcherFeatureSet implements XPackFeatureSet {
@Override
public boolean available() {
return licensee != null && licensee.isAvailable();
return licenseState != null && licenseState.isWatcherAllowed();
}
@Override

View File

@ -1,94 +0,0 @@
/*
* 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.xpack.watcher;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License.OperationMode;
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
public class WatcherLicensee extends AbstractLicenseeComponent {
public static final String ID = Watcher.NAME;
public WatcherLicensee(Settings settings) {
super(settings, ID);
}
@Override
public String[] expirationMessages() {
return new String[] {
"PUT / GET watch APIs are disabled, DELETE watch API continues to work",
"Watches execute and write to the history",
"The actions of the watches don't execute"
};
}
@Override
public String[] acknowledgmentMessages(OperationMode currentMode, OperationMode newMode) {
switch (newMode) {
case BASIC:
switch (currentMode) {
case TRIAL:
case STANDARD:
case GOLD:
case PLATINUM:
return new String[] { "Watcher will be disabled" };
}
break;
}
return Strings.EMPTY_ARRAY;
}
/**
* Determine if Watcher is available based on the current license.
* <p>
* Watcher is available if the license is active (hasn't expired) and of one of the following types:
* <ul>
* <li>{@link OperationMode#PLATINUM}</li>
* <li>{@link OperationMode#GOLD}</li>
* <li>{@link OperationMode#TRIAL}</li>
* </ul>
*
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
*/
public boolean isAvailable() {
// status is volatile, so a local variable is used for a consistent view
Status localStatus = status;
if (localStatus.isActive() == false) {
return false;
}
switch (localStatus.getMode()) {
case TRIAL:
case GOLD:
case PLATINUM:
return true;
default:
return false;
}
}
public boolean isExecutingActionsAllowed() {
return isWatcherTransportActionAllowed();
}
public boolean isGetWatchAllowed() {
return isWatcherTransportActionAllowed();
}
public boolean isPutWatchAllowed() {
return isWatcherTransportActionAllowed();
}
public boolean isWatcherTransportActionAllowed() {
return isAvailable();
}
}

View File

@ -8,7 +8,7 @@ package org.elasticsearch.xpack.watcher.actions;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.support.validation.Validation;
import org.elasticsearch.xpack.watcher.transform.TransformRegistry;
@ -25,15 +25,15 @@ public class ActionRegistry {
private final Map<String, ActionFactory> parsers;
private final TransformRegistry transformRegistry;
private final Clock clock;
private final WatcherLicensee watcherLicensee;
private final XPackLicenseState licenseState;
@Inject
public ActionRegistry(Map<String, ActionFactory> parsers, TransformRegistry transformRegistry, Clock clock,
WatcherLicensee watcherLicensee) {
XPackLicenseState licenseState) {
this.parsers = parsers;
this.transformRegistry = transformRegistry;
this.clock = clock;
this.watcherLicensee = watcherLicensee;
this.licenseState = licenseState;
}
ActionFactory factory(String type) {
@ -57,7 +57,7 @@ public class ActionRegistry {
throw new ElasticsearchParseException("could not parse action [{}] for watch [{}]. {}", id, watchId, error);
}
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
ActionWrapper action = ActionWrapper.parse(watchId, id, parser, this, transformRegistry, clock, watcherLicensee);
ActionWrapper action = ActionWrapper.parse(watchId, id, parser, this, transformRegistry, clock, licenseState);
actions.add(action);
}
}

View File

@ -14,10 +14,10 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.watcher.actions.throttler.ActionThrottler;
import org.elasticsearch.xpack.watcher.actions.throttler.Throttler;
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.transform.ExecutableTransform;
@ -140,7 +140,7 @@ public class ActionWrapper implements ToXContent {
static ActionWrapper parse(String watchId, String actionId, XContentParser parser,
ActionRegistry actionRegistry, TransformRegistry transformRegistry,
Clock clock, WatcherLicensee watcherLicensee) throws IOException {
Clock clock, XPackLicenseState licenseState) throws IOException {
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
@ -178,7 +178,7 @@ public class ActionWrapper implements ToXContent {
throw new ElasticsearchParseException("could not parse watch action [{}/{}]. missing action type", watchId, actionId);
}
ActionThrottler throttler = new ActionThrottler(clock, throttlePeriod, watcherLicensee);
ActionThrottler throttler = new ActionThrottler(clock, throttlePeriod, licenseState);
return new ActionWrapper(actionId, throttler, transform, action);
}

View File

@ -7,8 +7,8 @@ package org.elasticsearch.xpack.watcher.actions.throttler;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.support.clock.Clock;
/**
@ -18,18 +18,18 @@ public class ActionThrottler implements Throttler {
private static final AckThrottler ACK_THROTTLER = new AckThrottler();
private final WatcherLicensee watcherLicensee;
private final XPackLicenseState licenseState;
private final PeriodThrottler periodThrottler;
private final AckThrottler ackThrottler;
public ActionThrottler(Clock clock, @Nullable TimeValue throttlePeriod, WatcherLicensee watcherLicensee) {
this(new PeriodThrottler(clock, throttlePeriod), ACK_THROTTLER, watcherLicensee);
public ActionThrottler(Clock clock, @Nullable TimeValue throttlePeriod, XPackLicenseState licenseState) {
this(new PeriodThrottler(clock, throttlePeriod), ACK_THROTTLER, licenseState);
}
ActionThrottler(PeriodThrottler periodThrottler, AckThrottler ackThrottler, WatcherLicensee watcherLicensee) {
ActionThrottler(PeriodThrottler periodThrottler, AckThrottler ackThrottler, XPackLicenseState licenseState) {
this.periodThrottler = periodThrottler;
this.ackThrottler = ackThrottler;
this.watcherLicensee = watcherLicensee;
this.licenseState = licenseState;
}
public TimeValue throttlePeriod() {
@ -38,7 +38,7 @@ public class ActionThrottler implements Throttler {
@Override
public Result throttle(String actionId, WatchExecutionContext ctx) {
if (!watcherLicensee.isExecutingActionsAllowed()) {
if (licenseState.isWatcherAllowed() == false) {
return Result.throttle("watcher license does not allow action execution");
}
if (periodThrottler != null) {

View File

@ -14,10 +14,11 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.Watcher;
import java.util.function.Supplier;
@ -27,22 +28,22 @@ import java.util.function.Supplier;
public abstract class WatcherTransportAction<Request extends MasterNodeRequest<Request>, Response extends ActionResponse>
extends TransportMasterNodeAction<Request, Response> {
protected final WatcherLicensee watcherLicensee;
protected final XPackLicenseState licenseState;
public WatcherTransportAction(Settings settings, String actionName, TransportService transportService,
ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherLicensee watcherLicensee,
IndexNameExpressionResolver indexNameExpressionResolver, XPackLicenseState licenseState,
Supplier<Request> request) {
super(settings, actionName, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, request);
this.watcherLicensee = watcherLicensee;
this.licenseState = licenseState;
}
@Override
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
if (watcherLicensee.isWatcherTransportActionAllowed()) {
if (licenseState.isWatcherAllowed()) {
super.doExecute(task, request, listener);
} else {
listener.onFailure(LicenseUtils.newComplianceException(WatcherLicensee.ID));
listener.onFailure(LicenseUtils.newComplianceException(Watcher.NAME));
}
}
}

View File

@ -15,10 +15,10 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
import org.elasticsearch.xpack.watcher.watch.WatchStatus;
import org.elasticsearch.xpack.watcher.watch.WatchStore;
@ -34,9 +34,9 @@ public class TransportAckWatchAction extends WatcherTransportAction<AckWatchRequ
public TransportAckWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
WatcherLicensee watcherLicensee) {
XPackLicenseState licenseState) {
super(settings, AckWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, AckWatchRequest::new);
licenseState, AckWatchRequest::new);
this.watcherService = watcherService;
}

View File

@ -15,10 +15,10 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
import org.elasticsearch.xpack.watcher.watch.WatchStatus;
import org.elasticsearch.xpack.watcher.watch.WatchStore;
@ -34,9 +34,9 @@ public class TransportActivateWatchAction extends WatcherTransportAction<Activat
public TransportActivateWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
WatcherLicensee watcherLicensee) {
XPackLicenseState licenseState) {
super(settings, ActivateWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, ActivateWatchRequest::new);
licenseState, ActivateWatchRequest::new);
this.watcherService = watcherService;
}

View File

@ -16,10 +16,10 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
import org.elasticsearch.xpack.watcher.watch.WatchStore;
@ -34,9 +34,9 @@ public class TransportDeleteWatchAction extends WatcherTransportAction<DeleteWat
public TransportDeleteWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
WatcherLicensee watcherLicensee) {
XPackLicenseState licenseState) {
super(settings, DeleteWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, DeleteWatchRequest::new);
licenseState, DeleteWatchRequest::new);
this.watcherService = watcherService;
}

View File

@ -18,6 +18,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.condition.always.AlwaysCondition;
@ -26,7 +27,6 @@ import org.elasticsearch.xpack.watcher.execution.ExecutionService;
import org.elasticsearch.xpack.watcher.execution.ManualExecutionContext;
import org.elasticsearch.xpack.watcher.history.WatchRecord;
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.watcher.support.xcontent.WatcherParams;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
@ -58,10 +58,10 @@ public class TransportExecuteWatchAction extends WatcherTransportAction<ExecuteW
public TransportExecuteWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, ExecutionService executionService,
Clock clock, WatcherLicensee watcherLicensee, WatchStore watchStore, TriggerService triggerService,
Clock clock, XPackLicenseState licenseState, WatchStore watchStore, TriggerService triggerService,
Watch.Parser watchParser) {
super(settings, ExecuteWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, ExecuteWatchRequest::new);
licenseState, ExecuteWatchRequest::new);
this.executionService = executionService;
this.watchStore = watchStore;
this.clock = clock;

View File

@ -19,10 +19,11 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.Watcher;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.support.xcontent.WatcherParams;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
import org.elasticsearch.xpack.watcher.watch.Watch;
@ -43,9 +44,9 @@ public class TransportGetWatchAction extends WatcherTransportAction<GetWatchRequ
public TransportGetWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
WatcherLicensee watcherLicensee) {
super(settings, GetWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, GetWatchRequest::new);
XPackLicenseState licenseState) {
super(settings, GetWatchAction.NAME, transportService, clusterService, threadPool, actionFilters,
indexNameExpressionResolver, licenseState, GetWatchRequest::new);
this.watcherService = watcherService;
}
@ -62,8 +63,8 @@ public class TransportGetWatchAction extends WatcherTransportAction<GetWatchRequ
@Override
protected void masterOperation(GetWatchRequest request, ClusterState state, ActionListener<GetWatchResponse> listener) throws
ElasticsearchException {
if (!watcherLicensee.isGetWatchAllowed()) {
listener.onFailure(LicenseUtils.newComplianceException(WatcherLicensee.ID));
if (licenseState.isWatcherAllowed() == false) {
listener.onFailure(LicenseUtils.newComplianceException(Watcher.NAME));
return;
}

View File

@ -17,10 +17,11 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.LicenseUtils;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.Watcher;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
import org.elasticsearch.xpack.watcher.watch.WatchStore;
@ -34,9 +35,9 @@ public class TransportPutWatchAction extends WatcherTransportAction<PutWatchRequ
public TransportPutWatchAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
WatcherLicensee watcherLicensee) {
super(settings, PutWatchAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, PutWatchRequest::new);
XPackLicenseState licenseState) {
super(settings, PutWatchAction.NAME, transportService, clusterService, threadPool, actionFilters,
indexNameExpressionResolver, licenseState, PutWatchRequest::new);
this.watcherService = watcherService;
}
@ -53,8 +54,8 @@ public class TransportPutWatchAction extends WatcherTransportAction<PutWatchRequ
@Override
protected void masterOperation(PutWatchRequest request, ClusterState state, ActionListener<PutWatchResponse> listener) throws
ElasticsearchException {
if (!watcherLicensee.isPutWatchAllowed()) {
listener.onFailure(LicenseUtils.newComplianceException(WatcherLicensee.ID));
if (licenseState.isWatcherAllowed() == false) {
listener.onFailure(LicenseUtils.newComplianceException(Watcher.NAME));
return;
}

View File

@ -15,10 +15,10 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherLifeCycleService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
/**
@ -31,9 +31,9 @@ public class TransportWatcherServiceAction extends WatcherTransportAction<Watche
public TransportWatcherServiceAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
WatcherLifeCycleService lifeCycleService, WatcherLicensee watcherLicensee) {
WatcherLifeCycleService lifeCycleService, XPackLicenseState licenseState) {
super(settings, WatcherServiceAction.NAME, transportService, clusterService, threadPool, actionFilters,
indexNameExpressionResolver, watcherLicensee, WatcherServiceRequest::new);
indexNameExpressionResolver, licenseState, WatcherServiceRequest::new);
this.lifeCycleService = lifeCycleService;
}

View File

@ -15,13 +15,13 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.watcher.WatcherBuild;
import org.elasticsearch.xpack.watcher.WatcherLifeCycleService;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.execution.ExecutionService;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.transport.actions.WatcherTransportAction;
/**
@ -37,10 +37,10 @@ public class TransportWatcherStatsAction extends WatcherTransportAction<WatcherS
public TransportWatcherStatsAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, WatcherService watcherService,
ExecutionService executionService, WatcherLicensee watcherLicensee,
ExecutionService executionService, XPackLicenseState licenseState,
WatcherLifeCycleService lifeCycleService) {
super(settings, WatcherStatsAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
watcherLicensee, WatcherStatsRequest::new);
licenseState, WatcherStatsRequest::new);
this.watcherService = watcherService;
this.executionService = executionService;
this.lifeCycleService = lifeCycleService;

View File

@ -9,6 +9,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.watcher.support.xcontent.XContentSource;
import org.junit.Before;
@ -31,26 +32,26 @@ import static org.mockito.Mockito.when;
*/
public class WatcherFeatureSetTests extends ESTestCase {
private WatcherLicensee licensee;
private XPackLicenseState licenseState;
private NamedWriteableRegistry namedWriteableRegistry;
private WatcherService watcherService;
@Before
public void init() throws Exception {
licensee = mock(WatcherLicensee.class);
licenseState = mock(XPackLicenseState.class);
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
watcherService = mock(WatcherService.class);
}
public void testWritableRegistration() throws Exception {
new WatcherFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry, watcherService);
new WatcherFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry, watcherService);
verify(namedWriteableRegistry).register(eq(WatcherFeatureSet.Usage.class), eq("xpack.usage.watcher"), anyObject());
}
public void testAvailable() throws Exception {
WatcherFeatureSet featureSet = new WatcherFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry, watcherService);
WatcherFeatureSet featureSet = new WatcherFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry, watcherService);
boolean available = randomBoolean();
when(licensee.isAvailable()).thenReturn(available);
when(licenseState.isWatcherAllowed()).thenReturn(available);
assertThat(featureSet.available(), is(available));
}
@ -64,7 +65,7 @@ public class WatcherFeatureSetTests extends ESTestCase {
} else {
settings.put("xpack.watcher.enabled", enabled);
}
WatcherFeatureSet featureSet = new WatcherFeatureSet(settings.build(), licensee, namedWriteableRegistry, watcherService);
WatcherFeatureSet featureSet = new WatcherFeatureSet(settings.build(), licenseState, namedWriteableRegistry, watcherService);
assertThat(featureSet.enabled(), is(enabled));
}
@ -73,7 +74,7 @@ public class WatcherFeatureSetTests extends ESTestCase {
statsMap.put("foo", "bar");
when(watcherService.usageStats()).thenReturn(statsMap);
WatcherFeatureSet featureSet = new WatcherFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry, watcherService);
WatcherFeatureSet featureSet = new WatcherFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry, watcherService);
XContentBuilder builder = jsonBuilder();
featureSet.usage().toXContent(builder, ToXContent.EMPTY_PARAMS);

View File

@ -5,9 +5,9 @@
*/
package org.elasticsearch.xpack.watcher.actions.throttler;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
@ -26,9 +26,9 @@ public class WatchThrottlerTests extends ESTestCase {
when(periodThrottler.throttle("_action", ctx)).thenReturn(Throttler.Result.NO);
Throttler.Result expectedResult = Throttler.Result.throttle("_reason");
when(ackThrottler.throttle("_action", ctx)).thenReturn(expectedResult);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
assertThat(result, is(expectedResult));
@ -41,9 +41,9 @@ public class WatchThrottlerTests extends ESTestCase {
Throttler.Result expectedResult = Throttler.Result.throttle("_reason");
when(periodThrottler.throttle("_action", ctx)).thenReturn(expectedResult);
when(ackThrottler.throttle("_action", ctx)).thenReturn(Throttler.Result.NO);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
assertThat(result, is(expectedResult));
@ -57,9 +57,9 @@ public class WatchThrottlerTests extends ESTestCase {
when(periodThrottler.throttle("_action", ctx)).thenReturn(periodResult);
Throttler.Result ackResult = Throttler.Result.throttle("_reason_ack");
when(ackThrottler.throttle("_action", ctx)).thenReturn(ackResult);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
// we always check the period first... so the result will come for the period throttler
@ -72,9 +72,9 @@ public class WatchThrottlerTests extends ESTestCase {
WatchExecutionContext ctx = mock(WatchExecutionContext.class);
when(periodThrottler.throttle("_action", ctx)).thenReturn(Throttler.Result.NO);
when(ackThrottler.throttle("_action", ctx)).thenReturn(Throttler.Result.NO);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(periodThrottler, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
assertThat(result, is(Throttler.Result.NO));
@ -85,9 +85,9 @@ public class WatchThrottlerTests extends ESTestCase {
WatchExecutionContext ctx = mock(WatchExecutionContext.class);
Throttler.Result ackResult = mock(Throttler.Result.class);
when(ackThrottler.throttle("_action", ctx)).thenReturn(ackResult);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(null, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(true);
ActionThrottler throttler = new ActionThrottler(null, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
assertThat(result, sameInstance(ackResult));
@ -98,9 +98,9 @@ public class WatchThrottlerTests extends ESTestCase {
WatchExecutionContext ctx = mock(WatchExecutionContext.class);
Throttler.Result ackResult = mock(Throttler.Result.class);
when(ackThrottler.throttle("_action", ctx)).thenReturn(ackResult);
WatcherLicensee watcherLicensee = mock(WatcherLicensee.class);
when(watcherLicensee.isExecutingActionsAllowed()).thenReturn(false);
ActionThrottler throttler = new ActionThrottler(null, ackThrottler, watcherLicensee);
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isWatcherAllowed()).thenReturn(false);
ActionThrottler throttler = new ActionThrottler(null, ackThrottler, licenseState);
Throttler.Result result = throttler.throttle("_action", ctx);
assertThat(result, notNullValue());
assertThat(result.reason(), is("watcher license does not allow action execution"));

View File

@ -1,92 +0,0 @@
/*
* 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.xpack.watcher.license;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.License;
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import static org.elasticsearch.license.core.License.OperationMode.BASIC;
import static org.elasticsearch.license.core.License.OperationMode.GOLD;
import static org.elasticsearch.license.core.License.OperationMode.PLATINUM;
import static org.elasticsearch.license.core.License.OperationMode.STANDARD;
import static org.elasticsearch.license.core.License.OperationMode.TRIAL;
import static org.hamcrest.Matchers.is;
public class LicenseTests extends AbstractLicenseeTestCase {
private WatcherLicensee watcherLicensee;
public void testPlatinumGoldTrialLicenseCanDoEverything() throws Exception {
initLicense(TRIAL, GOLD, PLATINUM);
assertWatcherActionsAllowed(watcherLicensee);
}
public void testBasicStandardLicenseDisablesWatcher() throws Exception {
initLicense(BASIC, STANDARD);
assertWatcherActionsNotAllowed(watcherLicensee);
}
public void testNoLicenseDisablesWatcher() {
initLicense(BASIC, STANDARD);
disable(watcherLicensee);
assertWatcherActionsNotAllowed(watcherLicensee);
}
public void testExpiredPlatinumGoldTrialLicenseDisablesWatcher() throws Exception {
initLicense(TRIAL, GOLD, PLATINUM);
disable(watcherLicensee);
assertWatcherActionsNotAllowed(watcherLicensee);
}
public void testUpgradingFromBasicOrStandardLicenseWorks() {
initLicense(BASIC, STANDARD);
assertWatcherActionsNotAllowed(watcherLicensee);
setOperationMode(watcherLicensee, randomFrom(TRIAL, GOLD, PLATINUM));
assertWatcherActionsAllowed(watcherLicensee);
}
public void testDowngradingToBasicOrStandardLicenseWorks() {
initLicense(TRIAL, GOLD, PLATINUM);
assertWatcherActionsAllowed(watcherLicensee);
setOperationMode(watcherLicensee, randomFrom(BASIC, STANDARD));
assertWatcherActionsNotAllowed(watcherLicensee);
}
public void testUpgradingExpiredLicenseWorks() {
initLicense(TRIAL, GOLD, PLATINUM);
disable(watcherLicensee);
assertWatcherActionsNotAllowed(watcherLicensee);
setOperationMode(watcherLicensee, randomFrom(TRIAL, GOLD, PLATINUM));
assertWatcherActionsAllowed(watcherLicensee);
}
private void assertWatcherActionsAllowed(WatcherLicensee watcherLicensee) {
assertThat("Expected putting a watch to be allowed", watcherLicensee.isPutWatchAllowed(), is(true));
assertThat("Expected getting a watch to be allowed", watcherLicensee.isGetWatchAllowed(), is(true));
assertThat("Expected watcher transport actions to be allowed", watcherLicensee.isWatcherTransportActionAllowed(), is(true));
assertThat("Expected actions of a watch to be executed", watcherLicensee.isExecutingActionsAllowed(), is(true));
}
private void assertWatcherActionsNotAllowed(WatcherLicensee watcherLicensee) {
assertThat("Expected putting a watch not to be allowed", watcherLicensee.isPutWatchAllowed(), is(false));
assertThat("Expected getting a watch not to be allowed", watcherLicensee.isGetWatchAllowed(), is(false));
assertThat("Expected watcher transport actions not to be allowed", watcherLicensee.isWatcherTransportActionAllowed(), is(false));
assertThat("Expected actions of a watch not to be executed", watcherLicensee.isExecutingActionsAllowed(), is(false));
}
private void initLicense(License.OperationMode ... allowedLicenses) {
watcherLicensee = new WatcherLicensee(Settings.EMPTY);
setOperationMode(watcherLicensee, randomFrom(allowedLicenses));
}
}

View File

@ -22,7 +22,7 @@ import org.elasticsearch.common.util.Callback;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.xpack.monitoring.Monitoring;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.MockMustacheScriptEngine;
@ -48,7 +48,6 @@ import org.elasticsearch.xpack.watcher.client.WatcherClient;
import org.elasticsearch.xpack.watcher.execution.ExecutionService;
import org.elasticsearch.xpack.watcher.execution.ExecutionState;
import org.elasticsearch.xpack.watcher.history.HistoryStore;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.support.WatcherIndexTemplateRegistry;
import org.elasticsearch.xpack.support.clock.ClockMock;
import org.elasticsearch.xpack.common.http.HttpClient;
@ -357,10 +356,6 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
return randomBoolean() ? new XPackClient(client).watcher() : new WatcherClient(client);
}
protected ScriptService scriptService() {
return internalCluster().getInstance(ScriptService.class);
}
protected HttpClient watcherHttpClient() {
return internalCluster().getInstance(HttpClient.class);
}
@ -369,10 +364,6 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
return new NoopEmailService();
}
protected WatcherLicensee licenseService() {
return getInstanceFromMaster(WatcherLicensee.class);
}
protected IndexNameExpressionResolver indexNameExpressionResolver() {
return internalCluster().getInstance(IndexNameExpressionResolver.class);
}
@ -541,8 +532,8 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
protected void ensureLicenseEnabled() throws Exception {
assertBusy(() -> {
for (WatcherLicensee service : internalCluster().getInstances(WatcherLicensee.class)) {
assertThat(service.isWatcherTransportActionAllowed(), is(true));
for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) {
assertThat(licenseState.isWatcherAllowed(), is(true));
}
});
}

View File

@ -5,6 +5,14 @@
*/
package org.elasticsearch.xpack.watcher.watch;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.logging.ESLogger;
@ -16,6 +24,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryParser;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.license.plugin.core.XPackLicenseState;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.common.http.HttpClient;
@ -35,7 +44,6 @@ import org.elasticsearch.xpack.notification.email.attachment.EmailAttachmentsPar
import org.elasticsearch.xpack.support.clock.Clock;
import org.elasticsearch.xpack.support.clock.ClockMock;
import org.elasticsearch.xpack.support.clock.SystemClock;
import org.elasticsearch.xpack.watcher.WatcherLicensee;
import org.elasticsearch.xpack.watcher.actions.ActionFactory;
import org.elasticsearch.xpack.watcher.actions.ActionRegistry;
import org.elasticsearch.xpack.watcher.actions.ActionStatus;
@ -117,14 +125,6 @@ import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Before;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap;
@ -148,7 +148,7 @@ public class WatchTests extends ESTestCase {
private TextTemplateEngine templateEngine;
private HtmlSanitizer htmlSanitizer;
private HttpAuthRegistry authRegistry;
private WatcherLicensee watcherLicensee;
private XPackLicenseState licenseState;
private ESLogger logger;
private Settings settings = Settings.EMPTY;
private WatcherSearchTemplateService searchTemplateService;
@ -161,7 +161,7 @@ public class WatchTests extends ESTestCase {
emailService = mock(EmailService.class);
templateEngine = mock(TextTemplateEngine.class);
htmlSanitizer = mock(HtmlSanitizer.class);
watcherLicensee = mock(WatcherLicensee.class);
licenseState = mock(XPackLicenseState.class);
authRegistry = new HttpAuthRegistry(singletonMap("basic", new BasicAuthFactory(null)));
logger = Loggers.getLogger(WatchTests.class);
searchTemplateService = mock(WatcherSearchTemplateService.class);
@ -476,12 +476,12 @@ public class WatchTests extends ESTestCase {
break;
}
}
return new ActionRegistry(unmodifiableMap(parsers), transformRegistry, SystemClock.INSTANCE, watcherLicensee);
return new ActionRegistry(unmodifiableMap(parsers), transformRegistry, SystemClock.INSTANCE, licenseState);
}
private ActionThrottler randomThrottler() {
return new ActionThrottler(SystemClock.INSTANCE, randomBoolean() ? null : TimeValue.timeValueMinutes(randomIntBetween(3, 5)),
watcherLicensee);
licenseState);
}
static class ParseOnlyScheduleTriggerEngine extends ScheduleTriggerEngine {