mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
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:
commit
c44b668605
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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() &&
|
||||
* (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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() {}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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()));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"));
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user