mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
This commit adds a new api to track when gold+ features are used within x-pack. The tracking is done internally whenever a feature is checked against the current license. The output of the api is a list of each used feature, which includes the name, license level, and last time it was used. In addition to a unit test for the tracking, a rest test is added which ensures starting up a default configured node does not result in any features registering as used. There are a couple features which currently do not work well with the tracking, as they are checked in a manner that makes them look always used. Those features will be fixed in followups, and in this PR they are omitted from the feature usage output.
This commit is contained in:
parent
e5baacbe2e
commit
3b688bfee5
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.common;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class MemoizedSupplier<T> implements Supplier<T> {
|
||||||
|
private Supplier<T> supplier;
|
||||||
|
private T value;
|
||||||
|
|
||||||
|
public MemoizedSupplier(Supplier<T> supplier) {
|
||||||
|
this.supplier = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get() {
|
||||||
|
if (supplier != null) {
|
||||||
|
value = supplier.get();
|
||||||
|
supplier = null;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import java.nio.file.Paths
|
|||||||
apply plugin: 'elasticsearch.esplugin'
|
apply plugin: 'elasticsearch.esplugin'
|
||||||
apply plugin: 'elasticsearch.publish'
|
apply plugin: 'elasticsearch.publish'
|
||||||
apply plugin: 'elasticsearch.internal-cluster-test'
|
apply plugin: 'elasticsearch.internal-cluster-test'
|
||||||
|
apply plugin: 'elasticsearch.yaml-rest-test'
|
||||||
|
|
||||||
archivesBaseName = 'x-pack-core'
|
archivesBaseName = 'x-pack-core'
|
||||||
|
|
||||||
@ -57,6 +58,8 @@ dependencies {
|
|||||||
transitive = false
|
transitive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yamlRestTestImplementation project(':x-pack:plugin:core')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.expansions = [
|
ext.expansions = [
|
||||||
@ -143,7 +146,18 @@ thirdPartyAudit.ignoreMissingClasses(
|
|||||||
'javax.servlet.ServletContextListener'
|
'javax.servlet.ServletContextListener'
|
||||||
)
|
)
|
||||||
|
|
||||||
// xpack modules are installed in real clusters as the meta plugin, so
|
restResources {
|
||||||
// installing them as individual plugins for integ tests doesn't make sense,
|
restApi {
|
||||||
// so we disable integ tests
|
includeCore '*'
|
||||||
integTest.enabled = false
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testClusters.yamlRestTest {
|
||||||
|
testDistribution = 'default'
|
||||||
|
setting 'xpack.security.enabled', 'true'
|
||||||
|
setting 'xpack.license.self_generated.type', 'trial'
|
||||||
|
keystore 'bootstrap.password', 'x-pack-test-password'
|
||||||
|
user username: "x_pack_rest_user", password: "x-pack-test-password"
|
||||||
|
}
|
||||||
|
|
||||||
|
testingConventions.enabled = false
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionRequest;
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class GetFeatureUsageRequest extends ActionRequest {
|
||||||
|
|
||||||
|
public GetFeatureUsageRequest() {}
|
||||||
|
|
||||||
|
public GetFeatureUsageRequest(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionRequestValidationException validate() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionResponse;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetFeatureUsageResponse extends ActionResponse implements ToXContentObject {
|
||||||
|
|
||||||
|
public static class FeatureUsageInfo implements Writeable {
|
||||||
|
public final String name;
|
||||||
|
public final ZonedDateTime lastUsedTime;
|
||||||
|
public final String licenseLevel;
|
||||||
|
|
||||||
|
public FeatureUsageInfo(String name, ZonedDateTime lastUsedTime, String licenseLevel) {
|
||||||
|
this.name = name;
|
||||||
|
this.lastUsedTime = lastUsedTime;
|
||||||
|
this.licenseLevel = licenseLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeatureUsageInfo(StreamInput in) throws IOException {
|
||||||
|
this.name = in.readString();
|
||||||
|
this.lastUsedTime = ZonedDateTime.ofInstant(Instant.ofEpochSecond(in.readLong()), ZoneOffset.UTC);
|
||||||
|
this.licenseLevel = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeString(name);
|
||||||
|
out.writeLong(lastUsedTime.toEpochSecond());
|
||||||
|
out.writeString(licenseLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FeatureUsageInfo> features;
|
||||||
|
|
||||||
|
public GetFeatureUsageResponse(List<FeatureUsageInfo> features) {
|
||||||
|
this.features = Collections.unmodifiableList(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetFeatureUsageResponse(StreamInput in) throws IOException {
|
||||||
|
this.features = in.readList(FeatureUsageInfo::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FeatureUsageInfo> getFeatures() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeList(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
builder.startArray("features");
|
||||||
|
for (FeatureUsageInfo feature : features) {
|
||||||
|
builder.startObject();
|
||||||
|
builder.field("name", feature.name);
|
||||||
|
builder.field("last_used", feature.lastUsedTime.toString());
|
||||||
|
builder.field("license_level", feature.licenseLevel);
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
@ -66,7 +66,8 @@ public class Licensing implements ActionPlugin {
|
|||||||
new ActionHandler<>(PostStartTrialAction.INSTANCE, TransportPostStartTrialAction.class),
|
new ActionHandler<>(PostStartTrialAction.INSTANCE, TransportPostStartTrialAction.class),
|
||||||
new ActionHandler<>(GetTrialStatusAction.INSTANCE, TransportGetTrialStatusAction.class),
|
new ActionHandler<>(GetTrialStatusAction.INSTANCE, TransportGetTrialStatusAction.class),
|
||||||
new ActionHandler<>(PostStartBasicAction.INSTANCE, TransportPostStartBasicAction.class),
|
new ActionHandler<>(PostStartBasicAction.INSTANCE, TransportPostStartBasicAction.class),
|
||||||
new ActionHandler<>(GetBasicStatusAction.INSTANCE, TransportGetBasicStatusAction.class));
|
new ActionHandler<>(GetBasicStatusAction.INSTANCE, TransportGetBasicStatusAction.class),
|
||||||
|
new ActionHandler<>(TransportGetFeatureUsageAction.TYPE, TransportGetFeatureUsageAction.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -81,6 +82,7 @@ public class Licensing implements ActionPlugin {
|
|||||||
handlers.add(new RestGetBasicStatus());
|
handlers.add(new RestGetBasicStatus());
|
||||||
handlers.add(new RestPostStartTrialLicense());
|
handlers.add(new RestPostStartTrialLicense());
|
||||||
handlers.add(new RestPostStartBasicLicense());
|
handlers.add(new RestPostStartBasicLicense());
|
||||||
|
handlers.add(new RestGetFeatureUsageAction());
|
||||||
return handlers;
|
return handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.rest.BaseRestHandler;
|
||||||
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||||
|
|
||||||
|
public class RestGetFeatureUsageAction extends BaseRestHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "get_feature_usage";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Route> routes() {
|
||||||
|
return Collections.singletonList(new Route(GET, "/_license/feature_usage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
|
||||||
|
return channel -> client.execute(TransportGetFeatureUsageAction.TYPE, new GetFeatureUsageRequest(),
|
||||||
|
new RestToXContentListener<>(channel));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.ActionType;
|
||||||
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
|
import org.elasticsearch.action.support.HandledTransportAction;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.tasks.Task;
|
||||||
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TransportGetFeatureUsageAction extends HandledTransportAction<GetFeatureUsageRequest, GetFeatureUsageResponse> {
|
||||||
|
|
||||||
|
public static final ActionType<GetFeatureUsageResponse> TYPE =
|
||||||
|
new ActionType<>("cluster:admin/xpack/license/feature_usage", GetFeatureUsageResponse::new);
|
||||||
|
|
||||||
|
private final XPackLicenseState licenseState;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransportGetFeatureUsageAction(TransportService transportService, ActionFilters actionFilters,
|
||||||
|
XPackLicenseState licenseState) {
|
||||||
|
super(TYPE.name(), transportService, actionFilters, GetFeatureUsageRequest::new);
|
||||||
|
this.licenseState = licenseState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doExecute(Task task, GetFeatureUsageRequest request, ActionListener<GetFeatureUsageResponse> listener) {
|
||||||
|
Map<XPackLicenseState.Feature, Long> featureUsage = licenseState.getLastUsed();
|
||||||
|
List<GetFeatureUsageResponse.FeatureUsageInfo> usageInfos = new ArrayList<>();
|
||||||
|
for (Map.Entry<XPackLicenseState.Feature, Long> entry : featureUsage.entrySet()) {
|
||||||
|
XPackLicenseState.Feature feature = entry.getKey();
|
||||||
|
String name = feature.name().toLowerCase(Locale.ROOT);
|
||||||
|
ZonedDateTime lastUsedTime = Instant.ofEpochMilli(entry.getValue()).atZone(ZoneOffset.UTC);
|
||||||
|
String licenseLevel = feature.minimumOperationMode.name().toLowerCase(Locale.ROOT);
|
||||||
|
usageInfos.add(new GetFeatureUsageResponse.FeatureUsageInfo(name, lastUsedTime, licenseLevel));
|
||||||
|
}
|
||||||
|
listener.onResponse(new GetFeatureUsageResponse(usageInfos));
|
||||||
|
}
|
||||||
|
}
|
@ -16,14 +16,19 @@ import org.elasticsearch.xpack.core.XPackSettings;
|
|||||||
import org.elasticsearch.xpack.core.monitoring.MonitoringField;
|
import org.elasticsearch.xpack.core.monitoring.MonitoringField;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.atomic.LongAccumulator;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.LongSupplier;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A holder for the current state of the license for all xpack features.
|
* A holder for the current state of the license for all xpack features.
|
||||||
@ -106,6 +111,14 @@ public class XPackLicenseState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temporarily non tracked feeatures which need rework in how they are checked
|
||||||
|
// so they are not tracked as always used
|
||||||
|
private static final Set<Feature> NON_TRACKED_FEATURES = org.elasticsearch.common.collect.Set.of(
|
||||||
|
Feature.SECURITY_IP_FILTERING,
|
||||||
|
Feature.SECURITY_ALL_REALMS,
|
||||||
|
Feature.SECURITY_STANDARD_REALMS
|
||||||
|
);
|
||||||
|
|
||||||
/** Messages for each feature which are printed when the license expires. */
|
/** Messages for each feature which are printed when the license expires. */
|
||||||
static final Map<String, String[]> EXPIRATION_MESSAGES;
|
static final Map<String, String[]> EXPIRATION_MESSAGES;
|
||||||
static {
|
static {
|
||||||
@ -398,6 +411,8 @@ public class XPackLicenseState {
|
|||||||
private final List<LicenseStateListener> listeners;
|
private final List<LicenseStateListener> listeners;
|
||||||
private final boolean isSecurityEnabled;
|
private final boolean isSecurityEnabled;
|
||||||
private final boolean isSecurityExplicitlyEnabled;
|
private final boolean isSecurityExplicitlyEnabled;
|
||||||
|
private final Map<Feature, LongAccumulator> lastUsed;
|
||||||
|
private final LongSupplier epochMillisProvider;
|
||||||
|
|
||||||
// Since Status is the only field that can be updated, we do not need to synchronize access to
|
// Since Status is the only field that can be updated, we do not need to synchronize access to
|
||||||
// XPackLicenseState. However, if status is read multiple times in a method, it can change in between
|
// XPackLicenseState. However, if status is read multiple times in a method, it can change in between
|
||||||
@ -405,18 +420,31 @@ public class XPackLicenseState {
|
|||||||
// is only read once.
|
// is only read once.
|
||||||
private volatile Status status = new Status(OperationMode.TRIAL, true);
|
private volatile Status status = new Status(OperationMode.TRIAL, true);
|
||||||
|
|
||||||
public XPackLicenseState(Settings settings) {
|
public XPackLicenseState(Settings settings, LongSupplier epochMillisProvider) {
|
||||||
this.listeners = new CopyOnWriteArrayList<>();
|
this.listeners = new CopyOnWriteArrayList<>();
|
||||||
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
|
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
|
||||||
this.isSecurityExplicitlyEnabled = isSecurityEnabled && isSecurityExplicitlyEnabled(settings);
|
this.isSecurityExplicitlyEnabled = isSecurityEnabled && isSecurityExplicitlyEnabled(settings);
|
||||||
|
|
||||||
|
// prepopulate feature last used map with entries for non basic features, which are the ones we
|
||||||
|
// care to actually keep track of
|
||||||
|
Map<Feature, LongAccumulator> lastUsed = new EnumMap<>(Feature.class);
|
||||||
|
for (Feature feature : Feature.values()) {
|
||||||
|
if (feature.minimumOperationMode.compareTo(OperationMode.BASIC) > 0 && NON_TRACKED_FEATURES.contains(feature) == false) {
|
||||||
|
lastUsed.put(feature, new LongAccumulator(Long::max, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lastUsed = lastUsed;
|
||||||
|
this.epochMillisProvider = epochMillisProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private XPackLicenseState(List<LicenseStateListener> listeners, boolean isSecurityEnabled, boolean isSecurityExplicitlyEnabled,
|
private XPackLicenseState(List<LicenseStateListener> listeners, boolean isSecurityEnabled, boolean isSecurityExplicitlyEnabled,
|
||||||
Status status) {
|
Status status, Map<Feature, LongAccumulator> lastUsed, LongSupplier epochMillisProvider) {
|
||||||
this.listeners = listeners;
|
this.listeners = listeners;
|
||||||
this.isSecurityEnabled = isSecurityEnabled;
|
this.isSecurityEnabled = isSecurityEnabled;
|
||||||
this.isSecurityExplicitlyEnabled = isSecurityExplicitlyEnabled;
|
this.isSecurityExplicitlyEnabled = isSecurityExplicitlyEnabled;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
this.lastUsed = lastUsed;
|
||||||
|
this.epochMillisProvider = epochMillisProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSecurityExplicitlyEnabled(Settings settings) {
|
private static boolean isSecurityExplicitlyEnabled(Settings settings) {
|
||||||
@ -480,8 +508,12 @@ public class XPackLicenseState {
|
|||||||
* Checks whether the given feature is allowed, tracking the last usage time.
|
* Checks whether the given feature is allowed, tracking the last usage time.
|
||||||
*/
|
*/
|
||||||
public boolean checkFeature(Feature feature) {
|
public boolean checkFeature(Feature feature) {
|
||||||
// TODO: usage tracking is not yet implemented
|
boolean allowed = isAllowed(feature);
|
||||||
return isAllowed(feature);
|
LongAccumulator maxEpochAccumulator = lastUsed.get(feature);
|
||||||
|
if (maxEpochAccumulator != null) {
|
||||||
|
maxEpochAccumulator.accumulate(epochMillisProvider.getAsLong());
|
||||||
|
}
|
||||||
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -493,6 +525,17 @@ public class XPackLicenseState {
|
|||||||
return isAllowedByLicense(feature.minimumOperationMode, feature.needsActive);
|
return isAllowedByLicense(feature.minimumOperationMode, feature.needsActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mapping of gold+ features to the last time that feature was used.
|
||||||
|
*
|
||||||
|
* Note that if a feature has not been used, it will not appear in the map.
|
||||||
|
*/
|
||||||
|
public Map<Feature, Long> getLastUsed() {
|
||||||
|
return lastUsed.entrySet().stream()
|
||||||
|
.filter(e -> e.getValue().get() != 0) // feature was never used
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get()));
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isMachineLearningAllowedForOperationMode(final OperationMode operationMode) {
|
public static boolean isMachineLearningAllowedForOperationMode(final OperationMode operationMode) {
|
||||||
return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM);
|
return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM);
|
||||||
}
|
}
|
||||||
@ -566,7 +609,7 @@ public class XPackLicenseState {
|
|||||||
*/
|
*/
|
||||||
public XPackLicenseState copyCurrentLicenseState() {
|
public XPackLicenseState copyCurrentLicenseState() {
|
||||||
return executeAgainstStatus(status ->
|
return executeAgainstStatus(status ->
|
||||||
new XPackLicenseState(listeners, isSecurityEnabled, isSecurityExplicitlyEnabled, status));
|
new XPackLicenseState(listeners, isSecurityEnabled, isSecurityExplicitlyEnabled, status, lastUsed, epochMillisProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,6 +85,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.LongSupplier;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
@ -136,6 +137,7 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
|||||||
private static final SetOnce<XPackLicenseState> licenseState = new SetOnce<>();
|
private static final SetOnce<XPackLicenseState> licenseState = new SetOnce<>();
|
||||||
private static final SetOnce<SSLService> sslService = new SetOnce<>();
|
private static final SetOnce<SSLService> sslService = new SetOnce<>();
|
||||||
private static final SetOnce<LicenseService> licenseService = new SetOnce<>();
|
private static final SetOnce<LicenseService> licenseService = new SetOnce<>();
|
||||||
|
private static final SetOnce<LongSupplier> epochMillisSupplier = new SetOnce<>();
|
||||||
|
|
||||||
public XPackPlugin(
|
public XPackPlugin(
|
||||||
final Settings settings,
|
final Settings settings,
|
||||||
@ -146,7 +148,7 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
|||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.transportClientMode = transportClientMode(settings);
|
this.transportClientMode = transportClientMode(settings);
|
||||||
|
|
||||||
setLicenseState(new XPackLicenseState(settings));
|
setLicenseState(new XPackLicenseState(settings, () -> getEpochMillisSupplier().getAsLong()));
|
||||||
|
|
||||||
this.licensing = new Licensing(settings);
|
this.licensing = new Licensing(settings);
|
||||||
}
|
}
|
||||||
@ -159,9 +161,13 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
|||||||
protected SSLService getSslService() { return getSharedSslService(); }
|
protected SSLService getSslService() { return getSharedSslService(); }
|
||||||
protected LicenseService getLicenseService() { return getSharedLicenseService(); }
|
protected LicenseService getLicenseService() { return getSharedLicenseService(); }
|
||||||
protected XPackLicenseState getLicenseState() { return getSharedLicenseState(); }
|
protected XPackLicenseState getLicenseState() { return getSharedLicenseState(); }
|
||||||
|
protected LongSupplier getEpochMillisSupplier() { return getSharedEpochMillisSupplier(); }
|
||||||
protected void setSslService(SSLService sslService) { XPackPlugin.sslService.set(sslService); }
|
protected void setSslService(SSLService sslService) { XPackPlugin.sslService.set(sslService); }
|
||||||
protected void setLicenseService(LicenseService licenseService) { XPackPlugin.licenseService.set(licenseService); }
|
protected void setLicenseService(LicenseService licenseService) { XPackPlugin.licenseService.set(licenseService); }
|
||||||
protected void setLicenseState(XPackLicenseState licenseState) { XPackPlugin.licenseState.set(licenseState); }
|
protected void setLicenseState(XPackLicenseState licenseState) { XPackPlugin.licenseState.set(licenseState); }
|
||||||
|
protected void setEpochMillisSupplier(LongSupplier epochMillisSupplier) {
|
||||||
|
XPackPlugin.epochMillisSupplier.set(epochMillisSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
public static SSLService getSharedSslService() {
|
public static SSLService getSharedSslService() {
|
||||||
final SSLService ssl = XPackPlugin.sslService.get();
|
final SSLService ssl = XPackPlugin.sslService.get();
|
||||||
@ -172,6 +178,7 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
|||||||
}
|
}
|
||||||
public static LicenseService getSharedLicenseService() { return licenseService.get(); }
|
public static LicenseService getSharedLicenseService() { return licenseService.get(); }
|
||||||
public static XPackLicenseState getSharedLicenseState() { return licenseState.get(); }
|
public static XPackLicenseState getSharedLicenseState() { return licenseState.get(); }
|
||||||
|
public static LongSupplier getSharedEpochMillisSupplier() { return epochMillisSupplier.get(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the cluster state allows this node to add x-pack metadata to the cluster state,
|
* Checks if the cluster state allows this node to add x-pack metadata to the cluster state,
|
||||||
@ -268,6 +275,8 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
|||||||
setLicenseService(new LicenseService(settings, clusterService, getClock(),
|
setLicenseService(new LicenseService(settings, clusterService, getClock(),
|
||||||
environment, resourceWatcherService, getLicenseState()));
|
environment, resourceWatcherService, getLicenseState()));
|
||||||
|
|
||||||
|
setEpochMillisSupplier(threadPool::absoluteTimeInMillis);
|
||||||
|
|
||||||
// It is useful to override these as they are what guice is injecting into actions
|
// It is useful to override these as they are what guice is injecting into actions
|
||||||
components.add(sslService);
|
components.add(sslService);
|
||||||
components.add(getLicenseService());
|
components.add(getLicenseService());
|
||||||
|
@ -28,7 +28,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
|||||||
.put("xpack.security.transport.ssl.enabled", true)
|
.put("xpack.security.transport.ssl.enabled", true)
|
||||||
.put("xpack.security.fips_mode.enabled", randomBoolean())
|
.put("xpack.security.fips_mode.enabled", randomBoolean())
|
||||||
.build();
|
.build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
|
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
@ -52,7 +52,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
|||||||
.put("xpack.security.transport.ssl.enabled", true)
|
.put("xpack.security.transport.ssl.enabled", true)
|
||||||
.put("xpack.security.fips_mode.enabled", true)
|
.put("xpack.security.fips_mode.enabled", true)
|
||||||
.build();
|
.build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
|
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
@ -67,7 +67,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
|||||||
.put("xpack.security.transport.ssl.enabled", true)
|
.put("xpack.security.transport.ssl.enabled", true)
|
||||||
.put("xpack.security.fips_mode.enabled", false)
|
.put("xpack.security.fips_mode.enabled", false)
|
||||||
.build();
|
.build();
|
||||||
licenseState = new XPackLicenseState(settings);
|
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
|
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
|
@ -33,7 +33,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
|||||||
request.acknowledge(true);
|
request.acknowledge(true);
|
||||||
request.license(newLicense);
|
request.license(newLicense);
|
||||||
Settings settings = Settings.builder().put("xpack.security.enabled", true).build();
|
Settings settings = Settings.builder().put("xpack.security.enabled", true).build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
inetAddress = InetAddress.getLoopbackAddress();
|
inetAddress = InetAddress.getLoopbackAddress();
|
||||||
|
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
@ -48,7 +48,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
|||||||
.put("discovery.type", "single-node")
|
.put("discovery.type", "single-node")
|
||||||
.build();
|
.build();
|
||||||
licenseService.stop();
|
licenseService.stop();
|
||||||
licenseState = new XPackLicenseState(settings);
|
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
licenseService.registerLicense(request, responseFuture);
|
licenseService.registerLicense(request, responseFuture);
|
||||||
@ -62,7 +62,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
|||||||
request.acknowledge(true);
|
request.acknowledge(true);
|
||||||
request.license(newLicense);
|
request.license(newLicense);
|
||||||
Settings settings = Settings.builder().put("xpack.security.enabled", true).build();
|
Settings settings = Settings.builder().put("xpack.security.enabled", true).build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
inetAddress = TransportAddress.META_ADDRESS;
|
inetAddress = TransportAddress.META_ADDRESS;
|
||||||
|
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
@ -74,7 +74,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
|||||||
|
|
||||||
settings = Settings.builder().put("xpack.security.enabled", false).build();
|
settings = Settings.builder().put("xpack.security.enabled", false).build();
|
||||||
licenseService.stop();
|
licenseService.stop();
|
||||||
licenseState = new XPackLicenseState(settings);
|
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
licenseService.registerLicense(request, responseFuture);
|
licenseService.registerLicense(request, responseFuture);
|
||||||
@ -85,7 +85,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
|||||||
.put("xpack.security.transport.ssl.enabled", true)
|
.put("xpack.security.transport.ssl.enabled", true)
|
||||||
.build();
|
.build();
|
||||||
licenseService.stop();
|
licenseService.stop();
|
||||||
licenseState = new XPackLicenseState(settings);
|
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
setInitialState(null, licenseState, settings);
|
setInitialState(null, licenseState, settings);
|
||||||
licenseService.start();
|
licenseService.start();
|
||||||
licenseService.registerLicense(request, responseFuture);
|
licenseService.registerLicense(request, responseFuture);
|
||||||
|
@ -362,7 +362,7 @@ public class TestUtils {
|
|||||||
public final List<Version> trialVersionUpdates = new ArrayList<>();
|
public final List<Version> trialVersionUpdates = new ArrayList<>();
|
||||||
|
|
||||||
public AssertingLicenseState() {
|
public AssertingLicenseState() {
|
||||||
super(Settings.EMPTY);
|
super(Settings.EMPTY, () -> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -383,7 +383,7 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UpdatableLicenseState(Settings settings) {
|
public UpdatableLicenseState(Settings settings) {
|
||||||
super(settings);
|
super(settings, () -> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -393,7 +393,7 @@ public class TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static XPackLicenseState newTestLicenseState() {
|
public static XPackLicenseState newTestLicenseState() {
|
||||||
return new XPackLicenseState(Settings.EMPTY);
|
return new XPackLicenseState(Settings.EMPTY, () -> 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void putLicense(Metadata.Builder builder, License license) {
|
public static void putLicense(Metadata.Builder builder, License license) {
|
||||||
|
@ -15,6 +15,7 @@ import org.elasticsearch.xpack.core.XPackField;
|
|||||||
import org.elasticsearch.xpack.core.XPackSettings;
|
import org.elasticsearch.xpack.core.XPackSettings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ import static org.elasticsearch.license.License.OperationMode.PLATINUM;
|
|||||||
import static org.elasticsearch.license.License.OperationMode.STANDARD;
|
import static org.elasticsearch.license.License.OperationMode.STANDARD;
|
||||||
import static org.elasticsearch.license.License.OperationMode.TRIAL;
|
import static org.elasticsearch.license.License.OperationMode.TRIAL;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.collection.IsMapContaining.hasEntry;
|
||||||
|
import static org.hamcrest.collection.IsMapContaining.hasKey;
|
||||||
|
import static org.hamcrest.core.IsNot.not;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the {@link XPackLicenseState}
|
* Unit tests for the {@link XPackLicenseState}
|
||||||
@ -77,7 +81,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testSecurityDefaults() {
|
public void testSecurityDefaults() {
|
||||||
Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true));
|
assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true));
|
||||||
assertThat(licenseState.checkFeature(Feature.SECURITY_AUDITING), is(true));
|
assertThat(licenseState.checkFeature(Feature.SECURITY_AUDITING), is(true));
|
||||||
@ -92,8 +96,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testTransportSslDoesNotAutomaticallyEnableSecurityOnTrialLicense() {
|
public void testTransportSslDoesNotAutomaticallyEnableSecurityOnTrialLicense() {
|
||||||
Settings settings = Settings.builder().put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), true).build();
|
Settings settings = Settings.builder().put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), true).build();
|
||||||
final XPackLicenseState licenseState;
|
final XPackLicenseState licenseState= new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState = new XPackLicenseState(settings);
|
|
||||||
assertSecurityNotAllowed(licenseState);
|
assertSecurityNotAllowed(licenseState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +119,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testSecurityBasicWithExplicitSecurityEnabled() {
|
public void testSecurityBasicWithExplicitSecurityEnabled() {
|
||||||
final Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
final Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(BASIC, true, null);
|
licenseState.update(BASIC, true, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -148,7 +151,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
|
|
||||||
public void testSecurityEnabledBasicExpired() {
|
public void testSecurityEnabledBasicExpired() {
|
||||||
Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build();
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(BASIC, false, null);
|
licenseState.update(BASIC, false, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -164,7 +167,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityStandard() {
|
public void testSecurityStandard() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(STANDARD, true, null);
|
licenseState.update(STANDARD, true, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -178,7 +181,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityStandardExpired() {
|
public void testSecurityStandardExpired() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(STANDARD, false, null);
|
licenseState.update(STANDARD, false, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -192,7 +195,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityGold() {
|
public void testSecurityGold() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(GOLD, true, null);
|
licenseState.update(GOLD, true, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -209,7 +212,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityGoldExpired() {
|
public void testSecurityGoldExpired() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(GOLD, false, null);
|
licenseState.update(GOLD, false, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -226,7 +229,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityPlatinum() {
|
public void testSecurityPlatinum() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(PLATINUM, true, null);
|
licenseState.update(PLATINUM, true, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -243,7 +246,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testSecurityPlatinumExpired() {
|
public void testSecurityPlatinumExpired() {
|
||||||
Settings settings = randomFrom(Settings.EMPTY,
|
Settings settings = randomFrom(Settings.EMPTY,
|
||||||
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build());
|
||||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
licenseState.update(PLATINUM, false, null);
|
licenseState.update(PLATINUM, false, null);
|
||||||
|
|
||||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||||
@ -566,4 +569,24 @@ public class XPackLicenseStateTests extends ESTestCase {
|
|||||||
public void testTransformInactiveBasic() {
|
public void testTransformInactiveBasic() {
|
||||||
assertAllowed(BASIC, false, s -> s.checkFeature(Feature.TRANSFORM), false);
|
assertAllowed(BASIC, false, s -> s.checkFeature(Feature.TRANSFORM), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testLastUsed() {
|
||||||
|
Feature basicFeature = Feature.SECURITY;
|
||||||
|
Feature goldFeature = Feature.SECURITY_DLS_FLS;
|
||||||
|
AtomicInteger currentTime = new AtomicInteger(100); // non zero start time
|
||||||
|
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY, currentTime::get);
|
||||||
|
assertThat("basic features not tracked", licenseState.getLastUsed(), not(hasKey(basicFeature)));
|
||||||
|
assertThat("initial epoch time", licenseState.getLastUsed(), not(hasKey(goldFeature)));
|
||||||
|
licenseState.isAllowed(basicFeature);
|
||||||
|
assertThat("basic features still not tracked", licenseState.getLastUsed(), not(hasKey(basicFeature)));
|
||||||
|
licenseState.isAllowed(goldFeature);
|
||||||
|
assertThat("isAllowed does not track", licenseState.getLastUsed(), not(hasKey(goldFeature)));
|
||||||
|
licenseState.checkFeature(basicFeature);
|
||||||
|
assertThat("basic features still not tracked", licenseState.getLastUsed(), not(hasKey(basicFeature)));
|
||||||
|
licenseState.checkFeature(goldFeature);
|
||||||
|
assertThat("checkFeature tracks used time", licenseState.getLastUsed(), hasEntry(goldFeature, 100L));
|
||||||
|
currentTime.set(200);
|
||||||
|
licenseState.checkFeature(goldFeature);
|
||||||
|
assertThat("checkFeature updates tracked time", licenseState.getLastUsed(), hasEntry(goldFeature, 200L));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ import java.util.Optional;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.LongSupplier;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
@ -103,6 +104,7 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
|||||||
private XPackLicenseState licenseState;
|
private XPackLicenseState licenseState;
|
||||||
private SSLService sslService;
|
private SSLService sslService;
|
||||||
private LicenseService licenseService;
|
private LicenseService licenseService;
|
||||||
|
private LongSupplier epochMillisSupplier;
|
||||||
protected List<Plugin> plugins = new ArrayList<>();
|
protected List<Plugin> plugins = new ArrayList<>();
|
||||||
|
|
||||||
public LocalStateCompositeXPackPlugin(final Settings settings, final Path configPath) {
|
public LocalStateCompositeXPackPlugin(final Settings settings, final Path configPath) {
|
||||||
@ -150,6 +152,15 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
|||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected LongSupplier getEpochMillisSupplier() {
|
||||||
|
return epochMillisSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setEpochMillisSupplier(LongSupplier epochMillisSupplier) {
|
||||||
|
this.epochMillisSupplier = epochMillisSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Object> createComponents(Client client, ClusterService clusterService, ThreadPool threadPool,
|
public Collection<Object> createComponents(Client client, ClusterService clusterService, ThreadPool threadPool,
|
||||||
ResourceWatcherService resourceWatcherService, ScriptService scriptService,
|
ResourceWatcherService resourceWatcherService, ScriptService scriptService,
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||||
|
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||||
|
import org.elasticsearch.common.settings.SecureString;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
|
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||||
|
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||||
|
|
||||||
|
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||||
|
|
||||||
|
public class XPackCoreClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||||
|
|
||||||
|
private static final String BASIC_AUTH_VALUE =
|
||||||
|
basicAuthHeaderValue("x_pack_rest_user", new SecureString("x-pack-test-password"));
|
||||||
|
|
||||||
|
public XPackCoreClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||||
|
super(testCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParametersFactory
|
||||||
|
public static Iterable<Object[]> parameters() throws Exception {
|
||||||
|
return ESClientYamlSuiteTestCase.createParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings restClientSettings() {
|
||||||
|
return Settings.builder()
|
||||||
|
.put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"license.get_feature_usage":{
|
||||||
|
"stability":"experimental",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_license/feature_usage",
|
||||||
|
"methods":[
|
||||||
|
"GET"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params":{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"No features should be used just by starting up with default configuration":
|
||||||
|
- do:
|
||||||
|
license.get_feature_usage: {}
|
||||||
|
|
||||||
|
- length: { features: 0 }
|
@ -48,7 +48,7 @@ public class InvalidLicenseEnforcer implements LicenseStateListener {
|
|||||||
@Override
|
@Override
|
||||||
public void licenseStateChanged() {
|
public void licenseStateChanged() {
|
||||||
assert licenseStateListenerRegistered;
|
assert licenseStateListenerRegistered;
|
||||||
if (licenseState.checkFeature(XPackLicenseState.Feature.MACHINE_LEARNING) == false) {
|
if (licenseState.isAllowed(XPackLicenseState.Feature.MACHINE_LEARNING) == false) {
|
||||||
// if the license has expired, close jobs and datafeeds
|
// if the license has expired, close jobs and datafeeds
|
||||||
threadPool.generic().execute(new AbstractRunnable() {
|
threadPool.generic().execute(new AbstractRunnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -338,7 +338,7 @@ public class MachineLearningFeatureSetTests extends ESTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testUsageWithOrphanedTask() throws Exception {
|
public void testUsageWithOrphanedTask() throws Exception {
|
||||||
when(licenseState.checkFeature(XPackLicenseState.Feature.MACHINE_LEARNING)).thenReturn(true);
|
when(licenseState.isAllowed(XPackLicenseState.Feature.MACHINE_LEARNING)).thenReturn(true);
|
||||||
Settings.Builder settings = Settings.builder().put(commonSettings);
|
Settings.Builder settings = Settings.builder().put(commonSettings);
|
||||||
settings.put("xpack.ml.enabled", true);
|
settings.put("xpack.ml.enabled", true);
|
||||||
|
|
||||||
|
@ -1057,11 +1057,14 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
return index -> {
|
return index -> {
|
||||||
XPackLicenseState licenseState = getLicenseState();
|
XPackLicenseState licenseState = getLicenseState();
|
||||||
if (licenseState.isSecurityEnabled() == false || licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
if (licenseState.isSecurityEnabled() == false) {
|
||||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||||
}
|
}
|
||||||
IndicesAccessControl indicesAccessControl = threadContext.get().getTransient(
|
IndicesAccessControl indicesAccessControl = threadContext.get().getTransient(
|
||||||
AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||||
|
if (indicesAccessControl == null) {
|
||||||
|
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||||
|
}
|
||||||
IndicesAccessControl.IndexAccessControl indexPermissions = indicesAccessControl.getIndexPermissions(index);
|
IndicesAccessControl.IndexAccessControl indexPermissions = indicesAccessControl.getIndexPermissions(index);
|
||||||
if (indexPermissions == null) {
|
if (indexPermissions == null) {
|
||||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||||
@ -1073,6 +1076,10 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
|
|||||||
if (fieldPermissions.hasFieldLevelSecurity() == false) {
|
if (fieldPermissions.hasFieldLevelSecurity() == false) {
|
||||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||||
}
|
}
|
||||||
|
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||||
|
// check license last, once we know FLS is actually used
|
||||||
|
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||||
|
}
|
||||||
return fieldPermissions::grantsAccessTo;
|
return fieldPermissions::grantsAccessTo;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import org.elasticsearch.action.ActionListener;
|
|||||||
import org.elasticsearch.action.bulk.BulkItemRequest;
|
import org.elasticsearch.action.bulk.BulkItemRequest;
|
||||||
import org.elasticsearch.action.bulk.BulkShardRequest;
|
import org.elasticsearch.action.bulk.BulkShardRequest;
|
||||||
import org.elasticsearch.action.update.UpdateRequest;
|
import org.elasticsearch.action.update.UpdateRequest;
|
||||||
|
import org.elasticsearch.common.MemoizedSupplier;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||||
@ -41,7 +42,8 @@ public class BulkShardRequestInterceptor implements RequestInterceptor {
|
|||||||
@Override
|
@Override
|
||||||
public void intercept(RequestInfo requestInfo, AuthorizationEngine authzEngine, AuthorizationInfo authorizationInfo,
|
public void intercept(RequestInfo requestInfo, AuthorizationEngine authzEngine, AuthorizationInfo authorizationInfo,
|
||||||
ActionListener<Void> listener) {
|
ActionListener<Void> listener) {
|
||||||
boolean shouldIntercept = licenseState.isSecurityEnabled() && licenseState.checkFeature(Feature.SECURITY_DLS_FLS);
|
boolean shouldIntercept = licenseState.isSecurityEnabled();
|
||||||
|
MemoizedSupplier<Boolean> licenseChecker = new MemoizedSupplier<>(() -> licenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||||
if (requestInfo.getRequest() instanceof BulkShardRequest && shouldIntercept) {
|
if (requestInfo.getRequest() instanceof BulkShardRequest && shouldIntercept) {
|
||||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ public class BulkShardRequestInterceptor implements RequestInterceptor {
|
|||||||
boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||||
boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||||
if (fls || dls) {
|
if (fls || dls) {
|
||||||
if (bulkItemRequest.request() instanceof UpdateRequest) {
|
if (licenseChecker.get() && bulkItemRequest.request() instanceof UpdateRequest) {
|
||||||
found = true;
|
found = true;
|
||||||
logger.trace("aborting bulk item update request for index [{}]", bulkItemRequest.index());
|
logger.trace("aborting bulk item update request for index [{}]", bulkItemRequest.index());
|
||||||
bulkItemRequest.abort(bulkItemRequest.index(), new ElasticsearchSecurityException("Can't execute a bulk " +
|
bulkItemRequest.abort(bulkItemRequest.index(), new ElasticsearchSecurityException("Can't execute a bulk " +
|
||||||
|
@ -9,6 +9,7 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.IndicesRequest;
|
import org.elasticsearch.action.IndicesRequest;
|
||||||
|
import org.elasticsearch.common.MemoizedSupplier;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||||
@ -39,7 +40,8 @@ abstract class FieldAndDocumentLevelSecurityRequestInterceptor implements Reques
|
|||||||
ActionListener<Void> listener) {
|
ActionListener<Void> listener) {
|
||||||
if (requestInfo.getRequest() instanceof IndicesRequest) {
|
if (requestInfo.getRequest() instanceof IndicesRequest) {
|
||||||
IndicesRequest indicesRequest = (IndicesRequest) requestInfo.getRequest();
|
IndicesRequest indicesRequest = (IndicesRequest) requestInfo.getRequest();
|
||||||
boolean shouldIntercept = licenseState.isSecurityEnabled() && licenseState.checkFeature(Feature.SECURITY_DLS_FLS);
|
boolean shouldIntercept = licenseState.isSecurityEnabled();
|
||||||
|
MemoizedSupplier<Boolean> licenseChecker = new MemoizedSupplier<>(() -> licenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||||
if (supports(indicesRequest) && shouldIntercept) {
|
if (supports(indicesRequest) && shouldIntercept) {
|
||||||
final IndicesAccessControl indicesAccessControl =
|
final IndicesAccessControl indicesAccessControl =
|
||||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||||
@ -48,7 +50,7 @@ abstract class FieldAndDocumentLevelSecurityRequestInterceptor implements Reques
|
|||||||
if (indexAccessControl != null) {
|
if (indexAccessControl != null) {
|
||||||
boolean fieldLevelSecurityEnabled = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
boolean fieldLevelSecurityEnabled = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||||
boolean documentLevelSecurityEnabled = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
boolean documentLevelSecurityEnabled = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||||
if (fieldLevelSecurityEnabled || documentLevelSecurityEnabled) {
|
if ((fieldLevelSecurityEnabled || documentLevelSecurityEnabled) && licenseChecker.get()) {
|
||||||
logger.trace("intercepted request for index [{}] with field level access controls [{}] " +
|
logger.trace("intercepted request for index [{}] with field level access controls [{}] " +
|
||||||
"document level access controls [{}]. disabling conflicting features",
|
"document level access controls [{}]. disabling conflicting features",
|
||||||
index, fieldLevelSecurityEnabled, documentLevelSecurityEnabled);
|
index, fieldLevelSecurityEnabled, documentLevelSecurityEnabled);
|
||||||
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.authz.interceptor;
|
|||||||
import org.elasticsearch.ElasticsearchSecurityException;
|
import org.elasticsearch.ElasticsearchSecurityException;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||||
|
import org.elasticsearch.common.MemoizedSupplier;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
@ -52,7 +53,8 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
|||||||
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
||||||
final AuditTrail auditTrail = auditTrailService.get();
|
final AuditTrail auditTrail = auditTrailService.get();
|
||||||
if (frozenLicenseState.isSecurityEnabled()) {
|
if (frozenLicenseState.isSecurityEnabled()) {
|
||||||
if (frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
MemoizedSupplier<Boolean> licenseChecker =
|
||||||
|
new MemoizedSupplier<>(() -> frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||||
IndicesAccessControl indicesAccessControl =
|
IndicesAccessControl indicesAccessControl =
|
||||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||||
for (IndicesAliasesRequest.AliasActions aliasAction : request.getAliasActions()) {
|
for (IndicesAliasesRequest.AliasActions aliasAction : request.getAliasActions()) {
|
||||||
@ -63,7 +65,7 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
|||||||
if (indexAccessControl != null) {
|
if (indexAccessControl != null) {
|
||||||
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||||
final boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
final boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||||
if (fls || dls) {
|
if ((fls || dls) && licenseChecker.get()) {
|
||||||
listener.onFailure(new ElasticsearchSecurityException("Alias requests are not allowed for " +
|
listener.onFailure(new ElasticsearchSecurityException("Alias requests are not allowed for " +
|
||||||
"users who have field or document level security enabled on one of the indices",
|
"users who have field or document level security enabled on one of the indices",
|
||||||
RestStatus.BAD_REQUEST));
|
RestStatus.BAD_REQUEST));
|
||||||
@ -73,7 +75,6 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<String>> indexToAliasesMap = request.getAliasActions().stream()
|
Map<String, List<String>> indexToAliasesMap = request.getAliasActions().stream()
|
||||||
.filter(aliasAction -> aliasAction.actionType() == IndicesAliasesRequest.AliasActions.Type.ADD)
|
.filter(aliasAction -> aliasAction.actionType() == IndicesAliasesRequest.AliasActions.Type.ADD)
|
||||||
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.authz.interceptor;
|
|||||||
import org.elasticsearch.ElasticsearchSecurityException;
|
import org.elasticsearch.ElasticsearchSecurityException;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||||
|
import org.elasticsearch.common.MemoizedSupplier;
|
||||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
import org.elasticsearch.license.XPackLicenseState;
|
import org.elasticsearch.license.XPackLicenseState;
|
||||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||||
@ -48,7 +49,8 @@ public final class ResizeRequestInterceptor implements RequestInterceptor {
|
|||||||
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
||||||
final AuditTrail auditTrail = auditTrailService.get();
|
final AuditTrail auditTrail = auditTrailService.get();
|
||||||
if (frozenLicenseState.isSecurityEnabled()) {
|
if (frozenLicenseState.isSecurityEnabled()) {
|
||||||
if (frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
MemoizedSupplier<Boolean> licenseChecker =
|
||||||
|
new MemoizedSupplier<>(() -> frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||||
IndicesAccessControl indicesAccessControl =
|
IndicesAccessControl indicesAccessControl =
|
||||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||||
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
||||||
@ -56,13 +58,12 @@ public final class ResizeRequestInterceptor implements RequestInterceptor {
|
|||||||
if (indexAccessControl != null) {
|
if (indexAccessControl != null) {
|
||||||
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||||
final boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
final boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||||
if (fls || dls) {
|
if ((fls || dls) && licenseChecker.get()) {
|
||||||
listener.onFailure(new ElasticsearchSecurityException("Resize requests are not allowed for users when " +
|
listener.onFailure(new ElasticsearchSecurityException("Resize requests are not allowed for users when " +
|
||||||
"field or document level security is enabled on the source index", RestStatus.BAD_REQUEST));
|
"field or document level security is enabled on the source index", RestStatus.BAD_REQUEST));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
authorizationEngine.validateIndexPermissionsAreSubset(requestInfo, authorizationInfo,
|
authorizationEngine.validateIndexPermissionsAreSubset(requestInfo, authorizationInfo,
|
||||||
Collections.singletonMap(request.getSourceIndex(), Collections.singletonList(request.getTargetIndexRequest().index())),
|
Collections.singletonMap(request.getSourceIndex(), Collections.singletonList(request.getTargetIndexRequest().index())),
|
||||||
|
@ -168,12 +168,14 @@ public class CompositeRolesStore {
|
|||||||
rolesRetrievalResult.getMissingRoles()));
|
rolesRetrievalResult.getMissingRoles()));
|
||||||
}
|
}
|
||||||
final Set<RoleDescriptor> effectiveDescriptors;
|
final Set<RoleDescriptor> effectiveDescriptors;
|
||||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
Set<RoleDescriptor> roleDescriptors = rolesRetrievalResult.getRoleDescriptors();
|
||||||
effectiveDescriptors = rolesRetrievalResult.getRoleDescriptors();
|
if (roleDescriptors.stream().anyMatch(RoleDescriptor::isUsingDocumentOrFieldLevelSecurity) &&
|
||||||
} else {
|
licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||||
effectiveDescriptors = rolesRetrievalResult.getRoleDescriptors().stream()
|
effectiveDescriptors = roleDescriptors.stream()
|
||||||
.filter((rd) -> rd.isUsingDocumentOrFieldLevelSecurity() == false)
|
.filter(r -> r.isUsingDocumentOrFieldLevelSecurity() == false)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
} else {
|
||||||
|
effectiveDescriptors = roleDescriptors;
|
||||||
}
|
}
|
||||||
logger.trace(() -> new ParameterizedMessage("Exposing effective role descriptors [{}] for role names [{}]",
|
logger.trace(() -> new ParameterizedMessage("Exposing effective role descriptors [{}] for role names [{}]",
|
||||||
effectiveDescriptors, roleNames));
|
effectiveDescriptors, roleNames));
|
||||||
|
@ -12,6 +12,7 @@ import org.apache.logging.log4j.util.Supplier;
|
|||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.ElasticsearchParseException;
|
import org.elasticsearch.ElasticsearchParseException;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.common.MemoizedSupplier;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.util.set.Sets;
|
import org.elasticsearch.common.util.set.Sets;
|
||||||
@ -176,14 +177,15 @@ public class FileRolesStore implements BiConsumer<Set<String>, ActionListener<Ro
|
|||||||
if (Files.exists(path)) {
|
if (Files.exists(path)) {
|
||||||
try {
|
try {
|
||||||
List<String> roleSegments = roleSegments(path);
|
List<String> roleSegments = roleSegments(path);
|
||||||
final boolean flsDlsLicensed = licenseState.checkFeature(Feature.SECURITY_DLS_FLS);
|
MemoizedSupplier<Boolean> licenseChecker =
|
||||||
|
new MemoizedSupplier<>(() -> licenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||||
for (String segment : roleSegments) {
|
for (String segment : roleSegments) {
|
||||||
RoleDescriptor descriptor = parseRoleDescriptor(segment, path, logger, resolvePermission, settings, xContentRegistry);
|
RoleDescriptor descriptor = parseRoleDescriptor(segment, path, logger, resolvePermission, settings, xContentRegistry);
|
||||||
if (descriptor != null) {
|
if (descriptor != null) {
|
||||||
if (ReservedRolesStore.isReserved(descriptor.getName())) {
|
if (ReservedRolesStore.isReserved(descriptor.getName())) {
|
||||||
logger.warn("role [{}] is reserved. the relevant role definition in the mapping file will be ignored",
|
logger.warn("role [{}] is reserved. the relevant role definition in the mapping file will be ignored",
|
||||||
descriptor.getName());
|
descriptor.getName());
|
||||||
} else if (flsDlsLicensed == false && descriptor.isUsingDocumentOrFieldLevelSecurity()) {
|
} else if (descriptor.isUsingDocumentOrFieldLevelSecurity() && licenseChecker.get() == false) {
|
||||||
logger.warn("role [{}] uses document and/or field level security, which is not enabled by the current license" +
|
logger.warn("role [{}] uses document and/or field level security, which is not enabled by the current license" +
|
||||||
". this role will be ignored", descriptor.getName());
|
". this role will be ignored", descriptor.getName());
|
||||||
// we still put the role in the map to avoid unnecessary negative lookups
|
// we still put the role in the map to avoid unnecessary negative lookups
|
||||||
|
@ -201,9 +201,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void putRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
public void putRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
||||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
if (role.isUsingDocumentOrFieldLevelSecurity() && licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||||
innerPutRole(request, role, listener);
|
|
||||||
} else if (role.isUsingDocumentOrFieldLevelSecurity()) {
|
|
||||||
listener.onFailure(LicenseUtils.newComplianceException("field and document level security"));
|
listener.onFailure(LicenseUtils.newComplianceException("field and document level security"));
|
||||||
} else {
|
} else {
|
||||||
innerPutRole(request, role, listener);
|
innerPutRole(request, role, listener);
|
||||||
@ -382,14 +380,11 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||||||
// we pass true as last parameter because we do not want to reject permissions if the field permissions
|
// we pass true as last parameter because we do not want to reject permissions if the field permissions
|
||||||
// are given in 2.x syntax
|
// are given in 2.x syntax
|
||||||
RoleDescriptor roleDescriptor = RoleDescriptor.parse(name, sourceBytes, true, XContentType.JSON);
|
RoleDescriptor roleDescriptor = RoleDescriptor.parse(name, sourceBytes, true, XContentType.JSON);
|
||||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
|
||||||
return roleDescriptor;
|
|
||||||
} else {
|
|
||||||
final boolean dlsEnabled =
|
final boolean dlsEnabled =
|
||||||
Arrays.stream(roleDescriptor.getIndicesPrivileges()).anyMatch(IndicesPrivileges::isUsingDocumentLevelSecurity);
|
Arrays.stream(roleDescriptor.getIndicesPrivileges()).anyMatch(IndicesPrivileges::isUsingDocumentLevelSecurity);
|
||||||
final boolean flsEnabled =
|
final boolean flsEnabled =
|
||||||
Arrays.stream(roleDescriptor.getIndicesPrivileges()).anyMatch(IndicesPrivileges::isUsingFieldLevelSecurity);
|
Arrays.stream(roleDescriptor.getIndicesPrivileges()).anyMatch(IndicesPrivileges::isUsingFieldLevelSecurity);
|
||||||
if (dlsEnabled || flsEnabled) {
|
if ((dlsEnabled || flsEnabled) && licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||||
List<String> unlicensedFeatures = new ArrayList<>(2);
|
List<String> unlicensedFeatures = new ArrayList<>(2);
|
||||||
if (flsEnabled) {
|
if (flsEnabled) {
|
||||||
unlicensedFeatures.add("fls");
|
unlicensedFeatures.add("fls");
|
||||||
@ -405,8 +400,6 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||||||
} else {
|
} else {
|
||||||
return roleDescriptor;
|
return roleDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(new ParameterizedMessage("error in the format of data for role [{}]", name), e);
|
logger.error(new ParameterizedMessage("error in the format of data for role [{}]", name), e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -90,7 +90,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
|||||||
arg0.updateLocalNodeInfo(localNode);
|
arg0.updateLocalNodeInfo(localNode);
|
||||||
return null;
|
return null;
|
||||||
}).when(clusterService).addListener(Mockito.isA(LoggingAuditTrail.class));
|
}).when(clusterService).addListener(Mockito.isA(LoggingAuditTrail.class));
|
||||||
apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), mock(Client.class), new XPackLicenseState(settings),
|
apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), mock(Client.class), new XPackLicenseState(settings, () -> 0),
|
||||||
mock(SecurityIndexManager.class), clusterService, mock(ThreadPool.class));
|
mock(SecurityIndexManager.class), clusterService, mock(ThreadPool.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
|||||||
}
|
}
|
||||||
logger = CapturingLogger.newCapturingLogger(randomFrom(Level.OFF, Level.FATAL, Level.ERROR, Level.WARN, Level.INFO), patternLayout);
|
logger = CapturingLogger.newCapturingLogger(randomFrom(Level.OFF, Level.FATAL, Level.ERROR, Level.WARN, Level.INFO), patternLayout);
|
||||||
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
auditTrail = new LoggingAuditTrail(settings, clusterService, logger, threadContext);
|
||||||
apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), client, new XPackLicenseState(settings),
|
apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), client, new XPackLicenseState(settings, () -> 0),
|
||||||
securityIndexManager, clusterService, mock(ThreadPool.class));
|
securityIndexManager, clusterService, mock(ThreadPool.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +689,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||||||
final AnonymousUser anonymousUser = new AnonymousUser(settings);
|
final AnonymousUser anonymousUser = new AnonymousUser(settings);
|
||||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
||||||
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, null, Collections.emptySet(),
|
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, anonymousUser, null, Collections.emptySet(),
|
||||||
new XPackLicenseState(settings), new IndexNameExpressionResolver());
|
new XPackLicenseState(settings, () -> 0), new IndexNameExpressionResolver());
|
||||||
|
|
||||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a").privileges("all").build() }, null);
|
||||||
@ -717,7 +717,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||||||
final Authentication authentication = createAuthentication(new AnonymousUser(settings));
|
final Authentication authentication = createAuthentication(new AnonymousUser(settings));
|
||||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
||||||
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null,
|
new DefaultAuthenticationFailureHandler(Collections.emptyMap()), threadPool, new AnonymousUser(settings), null,
|
||||||
Collections.emptySet(), new XPackLicenseState(settings), new IndexNameExpressionResolver());
|
Collections.emptySet(), new XPackLicenseState(settings, () -> 0), new IndexNameExpressionResolver());
|
||||||
|
|
||||||
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
RoleDescriptor role = new RoleDescriptor("a_all", null,
|
||||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||||
|
@ -354,7 +354,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final DocumentSubsetBitsetCache documentSubsetBitsetCache = buildBitsetCache();
|
final DocumentSubsetBitsetCache documentSubsetBitsetCache = buildBitsetCache();
|
||||||
final CompositeRolesStore compositeRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
|
final CompositeRolesStore compositeRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
|
||||||
reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings),
|
reservedRolesStore, mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(settings),
|
||||||
new XPackLicenseState(settings), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
new XPackLicenseState(settings, () -> 0), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||||
|
|
||||||
@ -393,7 +393,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||||
|
|
||||||
@ -480,7 +480,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, inMemoryProvider2),
|
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, inMemoryProvider2),
|
||||||
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
|
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0),
|
||||||
cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
|
|
||||||
@ -709,7 +709,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, failingProvider),
|
mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider1, failingProvider),
|
||||||
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
|
new ThreadContext(SECURITY_ENABLED_SETTINGS), new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0),
|
||||||
cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
|
cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
|
||||||
|
|
||||||
final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown");
|
final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown");
|
||||||
@ -821,7 +821,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
|
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
|
||||||
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(Settings.EMPTY),
|
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(Settings.EMPTY),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> {}) {
|
rds -> {}) {
|
||||||
@Override
|
@Override
|
||||||
public void invalidateAll() {
|
public void invalidateAll() {
|
||||||
@ -875,7 +875,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(SECURITY_ENABLED_SETTINGS,
|
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(SECURITY_ENABLED_SETTINGS,
|
||||||
fileRolesStore, nativeRolesStore, reservedRolesStore,
|
fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class),
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, mock(ApiKeyService.class),
|
||||||
documentSubsetBitsetCache, rds -> {}) {
|
documentSubsetBitsetCache, rds -> {}) {
|
||||||
@Override
|
@Override
|
||||||
public void invalidateAll() {
|
public void invalidateAll() {
|
||||||
@ -971,7 +971,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||||
|
|
||||||
@ -1012,7 +1012,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
mock(NativePrivilegeStore.class), Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, mock(ApiKeyService.class), documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||||
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
|
||||||
@ -1035,7 +1035,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
|
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
|
||||||
ThreadContext threadContext = new ThreadContext(SECURITY_ENABLED_SETTINGS);
|
ThreadContext threadContext = new ThreadContext(SECURITY_ENABLED_SETTINGS);
|
||||||
ApiKeyService apiKeyService = spy(new ApiKeyService(SECURITY_ENABLED_SETTINGS, Clock.systemUTC(), mock(Client.class),
|
ApiKeyService apiKeyService = spy(new ApiKeyService(SECURITY_ENABLED_SETTINGS, Clock.systemUTC(), mock(Client.class),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), mock(SecurityIndexManager.class), mock(ClusterService.class),
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), mock(SecurityIndexManager.class), mock(ClusterService.class),
|
||||||
mock(ThreadPool.class)));
|
mock(ThreadPool.class)));
|
||||||
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
||||||
doAnswer(invocationOnMock -> {
|
doAnswer(invocationOnMock -> {
|
||||||
@ -1050,7 +1050,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, apiKeyService, documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||||
final Version version = randomFrom(Version.CURRENT, VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_8_1));
|
final Version version = randomFrom(Version.CURRENT, VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_8_1));
|
||||||
@ -1088,7 +1088,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
ThreadContext threadContext = new ThreadContext(SECURITY_ENABLED_SETTINGS);
|
ThreadContext threadContext = new ThreadContext(SECURITY_ENABLED_SETTINGS);
|
||||||
|
|
||||||
ApiKeyService apiKeyService = spy(new ApiKeyService(SECURITY_ENABLED_SETTINGS, Clock.systemUTC(), mock(Client.class),
|
ApiKeyService apiKeyService = spy(new ApiKeyService(SECURITY_ENABLED_SETTINGS, Clock.systemUTC(), mock(Client.class),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), mock(SecurityIndexManager.class), mock(ClusterService.class),
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), mock(SecurityIndexManager.class), mock(ClusterService.class),
|
||||||
mock(ThreadPool.class)));
|
mock(ThreadPool.class)));
|
||||||
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
||||||
doAnswer(invocationOnMock -> {
|
doAnswer(invocationOnMock -> {
|
||||||
@ -1103,7 +1103,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
final CompositeRolesStore compositeRolesStore =
|
final CompositeRolesStore compositeRolesStore =
|
||||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||||
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
nativePrivStore, Collections.emptyList(), new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS), cache, apiKeyService, documentSubsetBitsetCache,
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0), cache, apiKeyService, documentSubsetBitsetCache,
|
||||||
rds -> effectiveRoleDescriptors.set(rds));
|
rds -> effectiveRoleDescriptors.set(rds));
|
||||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||||
final Version version = randomFrom(Version.CURRENT, VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_8_1));
|
final Version version = randomFrom(Version.CURRENT, VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_8_1));
|
||||||
@ -1238,7 +1238,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
nativePrivStore,
|
nativePrivStore,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
|
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0),
|
||||||
cache,
|
cache,
|
||||||
apiKeyService,
|
apiKeyService,
|
||||||
documentSubsetBitsetCache,
|
documentSubsetBitsetCache,
|
||||||
@ -1364,7 +1364,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||||||
}).when(privilegeStore).getPrivileges(isA(Set.class), isA(Set.class), any(ActionListener.class));
|
}).when(privilegeStore).getPrivileges(isA(Set.class), isA(Set.class), any(ActionListener.class));
|
||||||
}
|
}
|
||||||
if (licenseState == null) {
|
if (licenseState == null) {
|
||||||
licenseState = new XPackLicenseState(settings);
|
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||||
}
|
}
|
||||||
if (apiKeyService == null) {
|
if (apiKeyService == null) {
|
||||||
apiKeyService = mock(ApiKeyService.class);
|
apiKeyService = mock(ApiKeyService.class);
|
||||||
|
@ -215,13 +215,13 @@ public class ServerTransportFilterTests extends ESTestCase {
|
|||||||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||||
ThreadContext threadContext = new ThreadContext(settings);
|
ThreadContext threadContext = new ThreadContext(settings);
|
||||||
return new ServerTransportFilter.ClientProfile(authcService, authzService, threadContext, false, destructiveOperations,
|
return new ServerTransportFilter.ClientProfile(authcService, authzService, threadContext, false, destructiveOperations,
|
||||||
reservedRealmEnabled, new SecurityContext(settings, threadContext), new XPackLicenseState(settings));
|
reservedRealmEnabled, new SecurityContext(settings, threadContext), new XPackLicenseState(settings, () -> 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerTransportFilter.NodeProfile getNodeFilter(boolean reservedRealmEnabled) throws IOException {
|
private ServerTransportFilter.NodeProfile getNodeFilter(boolean reservedRealmEnabled) throws IOException {
|
||||||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||||
ThreadContext threadContext = new ThreadContext(settings);
|
ThreadContext threadContext = new ThreadContext(settings);
|
||||||
return new ServerTransportFilter.NodeProfile(authcService, authzService, threadContext, false, destructiveOperations,
|
return new ServerTransportFilter.NodeProfile(authcService, authzService, threadContext, false, destructiveOperations,
|
||||||
reservedRealmEnabled, new SecurityContext(settings, threadContext), new XPackLicenseState(settings));
|
reservedRealmEnabled, new SecurityContext(settings, threadContext), new XPackLicenseState(settings, () -> 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user