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.publish'
|
||||
apply plugin: 'elasticsearch.internal-cluster-test'
|
||||
apply plugin: 'elasticsearch.yaml-rest-test'
|
||||
|
||||
archivesBaseName = 'x-pack-core'
|
||||
|
||||
@ -57,6 +58,8 @@ dependencies {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
yamlRestTestImplementation project(':x-pack:plugin:core')
|
||||
|
||||
}
|
||||
|
||||
ext.expansions = [
|
||||
@ -143,7 +146,18 @@ thirdPartyAudit.ignoreMissingClasses(
|
||||
'javax.servlet.ServletContextListener'
|
||||
)
|
||||
|
||||
// xpack modules are installed in real clusters as the meta plugin, so
|
||||
// installing them as individual plugins for integ tests doesn't make sense,
|
||||
// so we disable integ tests
|
||||
integTest.enabled = false
|
||||
restResources {
|
||||
restApi {
|
||||
includeCore '*'
|
||||
}
|
||||
}
|
||||
|
||||
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<>(GetTrialStatusAction.INSTANCE, TransportGetTrialStatusAction.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
|
||||
@ -81,6 +82,7 @@ public class Licensing implements ActionPlugin {
|
||||
handlers.add(new RestGetBasicStatus());
|
||||
handlers.add(new RestPostStartTrialLicense());
|
||||
handlers.add(new RestPostStartBasicLicense());
|
||||
handlers.add(new RestGetFeatureUsageAction());
|
||||
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 java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.LongAccumulator;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
static final Map<String, String[]> EXPIRATION_MESSAGES;
|
||||
static {
|
||||
@ -398,6 +411,8 @@ public class XPackLicenseState {
|
||||
private final List<LicenseStateListener> listeners;
|
||||
private final boolean isSecurityEnabled;
|
||||
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
|
||||
// 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.
|
||||
private volatile Status status = new Status(OperationMode.TRIAL, true);
|
||||
|
||||
public XPackLicenseState(Settings settings) {
|
||||
public XPackLicenseState(Settings settings, LongSupplier epochMillisProvider) {
|
||||
this.listeners = new CopyOnWriteArrayList<>();
|
||||
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(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,
|
||||
Status status) {
|
||||
Status status, Map<Feature, LongAccumulator> lastUsed, LongSupplier epochMillisProvider) {
|
||||
this.listeners = listeners;
|
||||
this.isSecurityEnabled = isSecurityEnabled;
|
||||
this.isSecurityExplicitlyEnabled = isSecurityExplicitlyEnabled;
|
||||
this.status = status;
|
||||
this.lastUsed = lastUsed;
|
||||
this.epochMillisProvider = epochMillisProvider;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
public boolean checkFeature(Feature feature) {
|
||||
// TODO: usage tracking is not yet implemented
|
||||
return isAllowed(feature);
|
||||
boolean allowed = 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM);
|
||||
}
|
||||
@ -566,7 +609,7 @@ public class XPackLicenseState {
|
||||
*/
|
||||
public XPackLicenseState copyCurrentLicenseState() {
|
||||
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.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
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<SSLService> sslService = new SetOnce<>();
|
||||
private static final SetOnce<LicenseService> licenseService = new SetOnce<>();
|
||||
private static final SetOnce<LongSupplier> epochMillisSupplier = new SetOnce<>();
|
||||
|
||||
public XPackPlugin(
|
||||
final Settings settings,
|
||||
@ -146,7 +148,7 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
||||
this.settings = settings;
|
||||
this.transportClientMode = transportClientMode(settings);
|
||||
|
||||
setLicenseState(new XPackLicenseState(settings));
|
||||
setLicenseState(new XPackLicenseState(settings, () -> getEpochMillisSupplier().getAsLong()));
|
||||
|
||||
this.licensing = new Licensing(settings);
|
||||
}
|
||||
@ -159,9 +161,13 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
||||
protected SSLService getSslService() { return getSharedSslService(); }
|
||||
protected LicenseService getLicenseService() { return getSharedLicenseService(); }
|
||||
protected XPackLicenseState getLicenseState() { return getSharedLicenseState(); }
|
||||
protected LongSupplier getEpochMillisSupplier() { return getSharedEpochMillisSupplier(); }
|
||||
protected void setSslService(SSLService sslService) { XPackPlugin.sslService.set(sslService); }
|
||||
protected void setLicenseService(LicenseService licenseService) { XPackPlugin.licenseService.set(licenseService); }
|
||||
protected void setLicenseState(XPackLicenseState licenseState) { XPackPlugin.licenseState.set(licenseState); }
|
||||
protected void setEpochMillisSupplier(LongSupplier epochMillisSupplier) {
|
||||
XPackPlugin.epochMillisSupplier.set(epochMillisSupplier);
|
||||
}
|
||||
|
||||
public static SSLService getSharedSslService() {
|
||||
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 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,
|
||||
@ -268,6 +275,8 @@ public class XPackPlugin extends XPackClientPlugin implements ExtensiblePlugin,
|
||||
setLicenseService(new LicenseService(settings, clusterService, getClock(),
|
||||
environment, resourceWatcherService, getLicenseState()));
|
||||
|
||||
setEpochMillisSupplier(threadPool::absoluteTimeInMillis);
|
||||
|
||||
// It is useful to override these as they are what guice is injecting into actions
|
||||
components.add(sslService);
|
||||
components.add(getLicenseService());
|
||||
|
@ -28,7 +28,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", true)
|
||||
.put("xpack.security.fips_mode.enabled", randomBoolean())
|
||||
.build();
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
@ -52,7 +52,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", true)
|
||||
.put("xpack.security.fips_mode.enabled", true)
|
||||
.build();
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
@ -67,7 +67,7 @@ public class LicenseFIPSTests extends AbstractLicenseServiceTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", true)
|
||||
.put("xpack.security.fips_mode.enabled", false)
|
||||
.build();
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
|
@ -33,7 +33,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
||||
request.acknowledge(true);
|
||||
request.license(newLicense);
|
||||
Settings settings = Settings.builder().put("xpack.security.enabled", true).build();
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings);
|
||||
XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
inetAddress = InetAddress.getLoopbackAddress();
|
||||
|
||||
setInitialState(null, licenseState, settings);
|
||||
@ -48,7 +48,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
||||
.put("discovery.type", "single-node")
|
||||
.build();
|
||||
licenseService.stop();
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
licenseService.registerLicense(request, responseFuture);
|
||||
@ -62,7 +62,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
||||
request.acknowledge(true);
|
||||
request.license(newLicense);
|
||||
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;
|
||||
|
||||
setInitialState(null, licenseState, settings);
|
||||
@ -74,7 +74,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
||||
|
||||
settings = Settings.builder().put("xpack.security.enabled", false).build();
|
||||
licenseService.stop();
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
licenseService.registerLicense(request, responseFuture);
|
||||
@ -85,7 +85,7 @@ public class LicenseTLSTests extends AbstractLicenseServiceTestCase {
|
||||
.put("xpack.security.transport.ssl.enabled", true)
|
||||
.build();
|
||||
licenseService.stop();
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
setInitialState(null, licenseState, settings);
|
||||
licenseService.start();
|
||||
licenseService.registerLicense(request, responseFuture);
|
||||
|
@ -362,7 +362,7 @@ public class TestUtils {
|
||||
public final List<Version> trialVersionUpdates = new ArrayList<>();
|
||||
|
||||
public AssertingLicenseState() {
|
||||
super(Settings.EMPTY);
|
||||
super(Settings.EMPTY, () -> 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -383,7 +383,7 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
public UpdatableLicenseState(Settings settings) {
|
||||
super(settings);
|
||||
super(settings, () -> 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -393,7 +393,7 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
public static XPackLicenseState newTestLicenseState() {
|
||||
return new XPackLicenseState(Settings.EMPTY);
|
||||
return new XPackLicenseState(Settings.EMPTY, () -> 0);
|
||||
}
|
||||
|
||||
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 java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Predicate;
|
||||
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.TRIAL;
|
||||
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}
|
||||
@ -77,7 +81,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
|
||||
public void testSecurityDefaults() {
|
||||
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.checkFeature(Feature.SECURITY_IP_FILTERING), is(true));
|
||||
assertThat(licenseState.checkFeature(Feature.SECURITY_AUDITING), is(true));
|
||||
@ -92,8 +96,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
|
||||
public void testTransportSslDoesNotAutomaticallyEnableSecurityOnTrialLicense() {
|
||||
Settings settings = Settings.builder().put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), true).build();
|
||||
final XPackLicenseState licenseState;
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
final XPackLicenseState licenseState= new XPackLicenseState(settings, () -> 0);
|
||||
assertSecurityNotAllowed(licenseState);
|
||||
}
|
||||
|
||||
@ -116,7 +119,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
|
||||
public void testSecurityBasicWithExplicitSecurityEnabled() {
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -148,7 +151,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
|
||||
public void testSecurityEnabledBasicExpired() {
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -164,7 +167,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityStandard() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -178,7 +181,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityStandardExpired() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -192,7 +195,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityGold() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -209,7 +212,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityGoldExpired() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -226,7 +229,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityPlatinum() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -243,7 +246,7 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testSecurityPlatinumExpired() {
|
||||
Settings settings = randomFrom(Settings.EMPTY,
|
||||
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);
|
||||
|
||||
assertThat(licenseState.isSecurityEnabled(), is(true));
|
||||
@ -566,4 +569,24 @@ public class XPackLicenseStateTests extends ESTestCase {
|
||||
public void testTransformInactiveBasic() {
|
||||
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.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.UnaryOperator;
|
||||
@ -103,6 +104,7 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
||||
private XPackLicenseState licenseState;
|
||||
private SSLService sslService;
|
||||
private LicenseService licenseService;
|
||||
private LongSupplier epochMillisSupplier;
|
||||
protected List<Plugin> plugins = new ArrayList<>();
|
||||
|
||||
public LocalStateCompositeXPackPlugin(final Settings settings, final Path configPath) {
|
||||
@ -150,6 +152,15 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
||||
return modules;
|
||||
}
|
||||
|
||||
protected LongSupplier getEpochMillisSupplier() {
|
||||
return epochMillisSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEpochMillisSupplier(LongSupplier epochMillisSupplier) {
|
||||
this.epochMillisSupplier = epochMillisSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Object> createComponents(Client client, ClusterService clusterService, ThreadPool threadPool,
|
||||
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
|
||||
public void licenseStateChanged() {
|
||||
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
|
||||
threadPool.generic().execute(new AbstractRunnable() {
|
||||
@Override
|
||||
|
@ -338,7 +338,7 @@ public class MachineLearningFeatureSetTests extends ESTestCase {
|
||||
}
|
||||
|
||||
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.put("xpack.ml.enabled", true);
|
||||
|
||||
|
@ -1057,11 +1057,14 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
|
||||
if (enabled) {
|
||||
return index -> {
|
||||
XPackLicenseState licenseState = getLicenseState();
|
||||
if (licenseState.isSecurityEnabled() == false || licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||
if (licenseState.isSecurityEnabled() == false) {
|
||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||
}
|
||||
IndicesAccessControl indicesAccessControl = threadContext.get().getTransient(
|
||||
AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
if (indicesAccessControl == null) {
|
||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||
}
|
||||
IndicesAccessControl.IndexAccessControl indexPermissions = indicesAccessControl.getIndexPermissions(index);
|
||||
if (indexPermissions == null) {
|
||||
return MapperPlugin.NOOP_FIELD_PREDICATE;
|
||||
@ -1073,6 +1076,10 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
|
||||
if (fieldPermissions.hasFieldLevelSecurity() == false) {
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.bulk.BulkItemRequest;
|
||||
import org.elasticsearch.action.bulk.BulkShardRequest;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.common.MemoizedSupplier;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||
@ -41,7 +42,8 @@ public class BulkShardRequestInterceptor implements RequestInterceptor {
|
||||
@Override
|
||||
public void intercept(RequestInfo requestInfo, AuthorizationEngine authzEngine, AuthorizationInfo authorizationInfo,
|
||||
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) {
|
||||
IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
|
||||
@ -54,7 +56,7 @@ public class BulkShardRequestInterceptor implements RequestInterceptor {
|
||||
boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||
boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||
if (fls || dls) {
|
||||
if (bulkItemRequest.request() instanceof UpdateRequest) {
|
||||
if (licenseChecker.get() && bulkItemRequest.request() instanceof UpdateRequest) {
|
||||
found = true;
|
||||
logger.trace("aborting bulk item update request for index [{}]", bulkItemRequest.index());
|
||||
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.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.IndicesRequest;
|
||||
import org.elasticsearch.common.MemoizedSupplier;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||
@ -39,7 +40,8 @@ abstract class FieldAndDocumentLevelSecurityRequestInterceptor implements Reques
|
||||
ActionListener<Void> listener) {
|
||||
if (requestInfo.getRequest() instanceof IndicesRequest) {
|
||||
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) {
|
||||
final IndicesAccessControl indicesAccessControl =
|
||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
@ -48,7 +50,7 @@ abstract class FieldAndDocumentLevelSecurityRequestInterceptor implements Reques
|
||||
if (indexAccessControl != null) {
|
||||
boolean fieldLevelSecurityEnabled = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||
boolean documentLevelSecurityEnabled = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||
if (fieldLevelSecurityEnabled || documentLevelSecurityEnabled) {
|
||||
if ((fieldLevelSecurityEnabled || documentLevelSecurityEnabled) && licenseChecker.get()) {
|
||||
logger.trace("intercepted request for index [{}] with field level access controls [{}] " +
|
||||
"document level access controls [{}]. disabling conflicting features",
|
||||
index, fieldLevelSecurityEnabled, documentLevelSecurityEnabled);
|
||||
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.security.authz.interceptor;
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.common.MemoizedSupplier;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
@ -52,7 +53,8 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
||||
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
||||
final AuditTrail auditTrail = auditTrailService.get();
|
||||
if (frozenLicenseState.isSecurityEnabled()) {
|
||||
if (frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
||||
MemoizedSupplier<Boolean> licenseChecker =
|
||||
new MemoizedSupplier<>(() -> frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||
IndicesAccessControl indicesAccessControl =
|
||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
for (IndicesAliasesRequest.AliasActions aliasAction : request.getAliasActions()) {
|
||||
@ -63,7 +65,7 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
||||
if (indexAccessControl != null) {
|
||||
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||
final boolean dls = indexAccessControl.getDocumentPermissions().hasDocumentLevelPermissions();
|
||||
if (fls || dls) {
|
||||
if ((fls || dls) && licenseChecker.get()) {
|
||||
listener.onFailure(new ElasticsearchSecurityException("Alias requests are not allowed for " +
|
||||
"users who have field or document level security enabled on one of the indices",
|
||||
RestStatus.BAD_REQUEST));
|
||||
@ -73,7 +75,6 @@ public final class IndicesAliasesRequestInterceptor implements RequestIntercepto
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, List<String>> indexToAliasesMap = request.getAliasActions().stream()
|
||||
.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.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.common.MemoizedSupplier;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.license.XPackLicenseState.Feature;
|
||||
@ -48,7 +49,8 @@ public final class ResizeRequestInterceptor implements RequestInterceptor {
|
||||
final XPackLicenseState frozenLicenseState = licenseState.copyCurrentLicenseState();
|
||||
final AuditTrail auditTrail = auditTrailService.get();
|
||||
if (frozenLicenseState.isSecurityEnabled()) {
|
||||
if (frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
||||
MemoizedSupplier<Boolean> licenseChecker =
|
||||
new MemoizedSupplier<>(() -> frozenLicenseState.checkFeature(Feature.SECURITY_DLS_FLS));
|
||||
IndicesAccessControl indicesAccessControl =
|
||||
threadContext.getTransient(AuthorizationServiceField.INDICES_PERMISSIONS_KEY);
|
||||
IndicesAccessControl.IndexAccessControl indexAccessControl =
|
||||
@ -56,13 +58,12 @@ public final class ResizeRequestInterceptor implements RequestInterceptor {
|
||||
if (indexAccessControl != null) {
|
||||
final boolean fls = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
|
||||
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 " +
|
||||
"field or document level security is enabled on the source index", RestStatus.BAD_REQUEST));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
authorizationEngine.validateIndexPermissionsAreSubset(requestInfo, authorizationInfo,
|
||||
Collections.singletonMap(request.getSourceIndex(), Collections.singletonList(request.getTargetIndexRequest().index())),
|
||||
|
@ -168,12 +168,14 @@ public class CompositeRolesStore {
|
||||
rolesRetrievalResult.getMissingRoles()));
|
||||
}
|
||||
final Set<RoleDescriptor> effectiveDescriptors;
|
||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
||||
effectiveDescriptors = rolesRetrievalResult.getRoleDescriptors();
|
||||
} else {
|
||||
effectiveDescriptors = rolesRetrievalResult.getRoleDescriptors().stream()
|
||||
.filter((rd) -> rd.isUsingDocumentOrFieldLevelSecurity() == false)
|
||||
Set<RoleDescriptor> roleDescriptors = rolesRetrievalResult.getRoleDescriptors();
|
||||
if (roleDescriptors.stream().anyMatch(RoleDescriptor::isUsingDocumentOrFieldLevelSecurity) &&
|
||||
licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||
effectiveDescriptors = roleDescriptors.stream()
|
||||
.filter(r -> r.isUsingDocumentOrFieldLevelSecurity() == false)
|
||||
.collect(Collectors.toSet());
|
||||
} else {
|
||||
effectiveDescriptors = roleDescriptors;
|
||||
}
|
||||
logger.trace(() -> new ParameterizedMessage("Exposing effective role descriptors [{}] for role names [{}]",
|
||||
effectiveDescriptors, roleNames));
|
||||
|
@ -12,6 +12,7 @@ import org.apache.logging.log4j.util.Supplier;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.common.MemoizedSupplier;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
@ -176,14 +177,15 @@ public class FileRolesStore implements BiConsumer<Set<String>, ActionListener<Ro
|
||||
if (Files.exists(path)) {
|
||||
try {
|
||||
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) {
|
||||
RoleDescriptor descriptor = parseRoleDescriptor(segment, path, logger, resolvePermission, settings, xContentRegistry);
|
||||
if (descriptor != null) {
|
||||
if (ReservedRolesStore.isReserved(descriptor.getName())) {
|
||||
logger.warn("role [{}] is reserved. the relevant role definition in the mapping file will be ignored",
|
||||
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" +
|
||||
". this role will be ignored", descriptor.getName());
|
||||
// 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) {
|
||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
||||
innerPutRole(request, role, listener);
|
||||
} else if (role.isUsingDocumentOrFieldLevelSecurity()) {
|
||||
if (role.isUsingDocumentOrFieldLevelSecurity() && licenseState.checkFeature(Feature.SECURITY_DLS_FLS) == false) {
|
||||
listener.onFailure(LicenseUtils.newComplianceException("field and document level security"));
|
||||
} else {
|
||||
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
|
||||
// are given in 2.x syntax
|
||||
RoleDescriptor roleDescriptor = RoleDescriptor.parse(name, sourceBytes, true, XContentType.JSON);
|
||||
if (licenseState.checkFeature(Feature.SECURITY_DLS_FLS)) {
|
||||
return roleDescriptor;
|
||||
} else {
|
||||
final boolean dlsEnabled =
|
||||
Arrays.stream(roleDescriptor.getIndicesPrivileges()).anyMatch(IndicesPrivileges::isUsingDocumentLevelSecurity);
|
||||
final boolean flsEnabled =
|
||||
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);
|
||||
if (flsEnabled) {
|
||||
unlicensedFeatures.add("fls");
|
||||
@ -405,8 +400,6 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
||||
} else {
|
||||
return roleDescriptor;
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(new ParameterizedMessage("error in the format of data for role [{}]", name), e);
|
||||
return null;
|
||||
|
@ -90,7 +90,7 @@ public class LoggingAuditTrailFilterTests extends ESTestCase {
|
||||
arg0.updateLocalNodeInfo(localNode);
|
||||
return null;
|
||||
}).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));
|
||||
}
|
||||
|
||||
|
@ -220,7 +220,7 @@ public class LoggingAuditTrailTests extends ESTestCase {
|
||||
}
|
||||
logger = CapturingLogger.newCapturingLogger(randomFrom(Level.OFF, Level.FATAL, Level.ERROR, Level.WARN, Level.INFO), patternLayout);
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -689,7 +689,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
||||
final AnonymousUser anonymousUser = new AnonymousUser(settings);
|
||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
||||
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,
|
||||
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));
|
||||
authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrailService,
|
||||
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,
|
||||
new IndicesPrivileges[]{IndicesPrivileges.builder().indices("a").privileges("all").build()}, null);
|
||||
|
@ -354,7 +354,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final DocumentSubsetBitsetCache documentSubsetBitsetCache = buildBitsetCache();
|
||||
final CompositeRolesStore compositeRolesStore = new CompositeRolesStore(settings, fileRolesStore, nativeRolesStore,
|
||||
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));
|
||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||
|
||||
@ -393,7 +393,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||
|
||||
@ -480,7 +480,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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,
|
||||
rds -> effectiveRoleDescriptors.set(rds));
|
||||
|
||||
@ -709,7 +709,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
|
||||
final Set<String> roleNames = Sets.newHashSet("roleA", "roleB", "unknown");
|
||||
@ -821,7 +821,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(
|
||||
Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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 -> {}) {
|
||||
@Override
|
||||
public void invalidateAll() {
|
||||
@ -875,7 +875,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
CompositeRolesStore compositeRolesStore = new CompositeRolesStore(SECURITY_ENABLED_SETTINGS,
|
||||
fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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 -> {}) {
|
||||
@Override
|
||||
public void invalidateAll() {
|
||||
@ -971,7 +971,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||
|
||||
@ -1012,7 +1012,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
verify(fileRolesStore).addListener(any(Consumer.class)); // adds a listener in ctor
|
||||
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
|
||||
@ -1035,7 +1035,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final ReservedRolesStore reservedRolesStore = spy(new ReservedRolesStore());
|
||||
ThreadContext threadContext = new ThreadContext(SECURITY_ENABLED_SETTINGS);
|
||||
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)));
|
||||
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
||||
doAnswer(invocationOnMock -> {
|
||||
@ -1050,7 +1050,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
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);
|
||||
|
||||
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)));
|
||||
NativePrivilegeStore nativePrivStore = mock(NativePrivilegeStore.class);
|
||||
doAnswer(invocationOnMock -> {
|
||||
@ -1103,7 +1103,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
final CompositeRolesStore compositeRolesStore =
|
||||
new CompositeRolesStore(SECURITY_ENABLED_SETTINGS, fileRolesStore, nativeRolesStore, reservedRolesStore,
|
||||
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));
|
||||
AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
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,
|
||||
Collections.emptyList(),
|
||||
new ThreadContext(SECURITY_ENABLED_SETTINGS),
|
||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS),
|
||||
new XPackLicenseState(SECURITY_ENABLED_SETTINGS, () -> 0),
|
||||
cache,
|
||||
apiKeyService,
|
||||
documentSubsetBitsetCache,
|
||||
@ -1364,7 +1364,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
||||
}).when(privilegeStore).getPrivileges(isA(Set.class), isA(Set.class), any(ActionListener.class));
|
||||
}
|
||||
if (licenseState == null) {
|
||||
licenseState = new XPackLicenseState(settings);
|
||||
licenseState = new XPackLicenseState(settings, () -> 0);
|
||||
}
|
||||
if (apiKeyService == null) {
|
||||
apiKeyService = mock(ApiKeyService.class);
|
||||
|
@ -215,13 +215,13 @@ public class ServerTransportFilterTests extends ESTestCase {
|
||||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||
ThreadContext threadContext = new ThreadContext(settings);
|
||||
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 {
|
||||
Settings settings = Settings.builder().put("path.home", createTempDir()).build();
|
||||
ThreadContext threadContext = new ThreadContext(settings);
|
||||
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