浏览代码

Enable Universal Profiling as Enterprise feature (#100333)

With this commit we ensure that Universal Profiling can only be used
with an Enterprise license.
Daniel Mitterdorfer 2 年之前
父节点
当前提交
dfaec0dbf0
共有 18 个文件被更改,包括 310 次插入10 次删除
  1. 5 0
      docs/changelog/100333.yaml
  2. 4 0
      docs/reference/rest-api/info.asciidoc
  3. 4 0
      docs/reference/rest-api/usage.asciidoc
  4. 2 0
      server/src/main/java/org/elasticsearch/TransportVersions.java
  5. 3 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java
  6. 2 0
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java
  7. 3 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/action/XPackInfoFeatureAction.java
  8. 3 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/action/XPackUsageFeatureAction.java
  9. 31 0
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/application/ProfilingUsage.java
  10. 25 0
      x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/LocalStateProfilingXPackPlugin.java
  11. 3 3
      x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/ProfilingTestCase.java
  12. 49 0
      x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingInfoTransportAction.java
  13. 39 0
      x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingLicenseChecker.java
  14. 11 4
      x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingPlugin.java
  15. 64 0
      x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingUsageTransportAction.java
  16. 4 0
      x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java
  17. 56 0
      x-pack/plugin/profiling/src/test/java/org/elasticsearch/xpack/profiling/ProfilingInfoTransportActionTests.java
  18. 2 0
      x-pack/plugin/security/qa/operator-privileges-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/operator/Constants.java

+ 5 - 0
docs/changelog/100333.yaml

@@ -0,0 +1,5 @@
+pr: 100333
+summary: Enable Universal Profiling as Enterprise feature
+area: Application
+type: enhancement
+issues: []

+ 4 - 0
docs/reference/rest-api/info.asciidoc

@@ -168,6 +168,10 @@ Example response:
       "enterprise_search": {
          "available": true,
          "enabled": true
+      },
+      "universal_profiling": {
+         "available": true,
+         "enabled": true
       }
    },
    "tagline" : "You know, for X"

+ 4 - 0
docs/reference/rest-api/usage.asciidoc

@@ -473,6 +473,10 @@ GET /_xpack/usage
       "min_rule_count": 0,
       "max_rule_count": 0
     }
+  },
+  "universal_profiling" : {
+    "available" : true,
+    "enabled" : true
   }
 }
 ------------------------------------------------------------

+ 2 - 0
server/src/main/java/org/elasticsearch/TransportVersions.java

@@ -135,6 +135,8 @@ public class TransportVersions {
     public static final TransportVersion NESTED_KNN_VECTOR_QUERY_V = def(8_511_00_0);
     public static final TransportVersion ML_PACKAGE_LOADER_PLATFORM_ADDED = def(8_512_00_0);
     public static final TransportVersion PLUGIN_DESCRIPTOR_OPTIONAL_CLASSNAME = def(8_513_00_0);
+    public static final TransportVersion UNIVERSAL_PROFILING_LICENSE_ADDED = def(8_514_00_0);
+
     /*
      * STOP! READ THIS FIRST! No, really,
      *        ____ _____ ___  ____  _        ____  _____    _    ____    _____ _   _ ___ ____    _____ ___ ____  ____ _____ _

+ 3 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java

@@ -23,6 +23,7 @@ import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xpack.core.aggregatemetric.AggregateMetricFeatureSetUsage;
 import org.elasticsearch.xpack.core.analytics.AnalyticsFeatureSetUsage;
 import org.elasticsearch.xpack.core.application.EnterpriseSearchFeatureSetUsage;
+import org.elasticsearch.xpack.core.application.ProfilingUsage;
 import org.elasticsearch.xpack.core.archive.ArchiveFeatureSetUsage;
 import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
 import org.elasticsearch.xpack.core.datastreams.DataStreamFeatureSetUsage;
@@ -277,7 +278,8 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl
                 XPackFeatureSet.Usage.class,
                 XPackField.ENTERPRISE_SEARCH,
                 EnterpriseSearchFeatureSetUsage::new
-            )
+            ),
+            new NamedWriteableRegistry.Entry(XPackFeatureSet.Usage.class, XPackField.UNIVERSAL_PROFILING, ProfilingUsage::new)
         ).filter(Objects::nonNull).toList();
     }
 

+ 2 - 0
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackField.java

@@ -85,6 +85,8 @@ public final class XPackField {
 
     /** Name constant for the redact processor feature. */
     public static final String REDACT_PROCESSOR = "redact_processor";
+    /* Name for Universal Profiling. */
+    public static final String UNIVERSAL_PROFILING = "universal_profiling";
 
     private XPackField() {}
 

+ 3 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/action/XPackInfoFeatureAction.java

@@ -50,6 +50,7 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
     public static final XPackInfoFeatureAction AGGREGATE_METRIC = new XPackInfoFeatureAction(XPackField.AGGREGATE_METRIC);
     public static final XPackInfoFeatureAction ARCHIVE = new XPackInfoFeatureAction(XPackField.ARCHIVE);
     public static final XPackInfoFeatureAction ENTERPRISE_SEARCH = new XPackInfoFeatureAction(XPackField.ENTERPRISE_SEARCH);
+    public static final XPackInfoFeatureAction UNIVERSAL_PROFILING = new XPackInfoFeatureAction(XPackField.UNIVERSAL_PROFILING);
 
     public static final List<XPackInfoFeatureAction> ALL;
     static {
@@ -80,7 +81,8 @@ public class XPackInfoFeatureAction extends ActionType<XPackInfoFeatureResponse>
                 DATA_TIERS,
                 AGGREGATE_METRIC,
                 ARCHIVE,
-                ENTERPRISE_SEARCH
+                ENTERPRISE_SEARCH,
+                UNIVERSAL_PROFILING
             )
         );
         ALL = Collections.unmodifiableList(actions);

+ 3 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/action/XPackUsageFeatureAction.java

@@ -50,6 +50,7 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
     public static final XPackUsageFeatureAction HEALTH = new XPackUsageFeatureAction(XPackField.HEALTH_API);
     public static final XPackUsageFeatureAction REMOTE_CLUSTERS = new XPackUsageFeatureAction(XPackField.REMOTE_CLUSTERS);
     public static final XPackUsageFeatureAction ENTERPRISE_SEARCH = new XPackUsageFeatureAction(XPackField.ENTERPRISE_SEARCH);
+    public static final XPackUsageFeatureAction UNIVERSAL_PROFILING = new XPackUsageFeatureAction(XPackField.UNIVERSAL_PROFILING);
 
     static final List<XPackUsageFeatureAction> ALL = List.of(
         AGGREGATE_METRIC,
@@ -78,7 +79,8 @@ public class XPackUsageFeatureAction extends ActionType<XPackUsageFeatureRespons
         ARCHIVE,
         HEALTH,
         REMOTE_CLUSTERS,
-        ENTERPRISE_SEARCH
+        ENTERPRISE_SEARCH,
+        UNIVERSAL_PROFILING
     );
 
     // public for testing

+ 31 - 0
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/application/ProfilingUsage.java

@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.core.application;
+
+import org.elasticsearch.TransportVersion;
+import org.elasticsearch.TransportVersions;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.xpack.core.XPackFeatureSet;
+import org.elasticsearch.xpack.core.XPackField;
+
+import java.io.IOException;
+
+public class ProfilingUsage extends XPackFeatureSet.Usage {
+    public ProfilingUsage(StreamInput input) throws IOException {
+        super(input);
+    }
+
+    public ProfilingUsage(boolean available, boolean enabled) {
+        super(XPackField.UNIVERSAL_PROFILING, available, enabled);
+    }
+
+    @Override
+    public TransportVersion getMinimalSupportedVersion() {
+        return TransportVersions.UNIVERSAL_PROFILING_LICENSE_ADDED;
+    }
+}

+ 25 - 0
x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/LocalStateProfilingXPackPlugin.java

@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
+
+import java.nio.file.Path;
+
+public class LocalStateProfilingXPackPlugin extends LocalStateCompositeXPackPlugin {
+    public LocalStateProfilingXPackPlugin(final Settings settings, final Path configPath) {
+        super(settings, configPath);
+        plugins.add(new ProfilingPlugin(settings) {
+            @Override
+            protected ProfilingLicenseChecker createLicenseChecker() {
+                return new ProfilingLicenseChecker(LocalStateProfilingXPackPlugin.this::getLicenseState);
+            }
+        });
+    }
+}

+ 3 - 3
x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/ProfilingTestCase.java

@@ -14,11 +14,11 @@ import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.common.network.NetworkModule;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.datastreams.DataStreamsPlugin;
+import org.elasticsearch.license.LicenseSettings;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.transport.netty4.Netty4Plugin;
-import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
 import org.elasticsearch.xpack.core.XPackSettings;
 import org.elasticsearch.xpack.core.ilm.LifecycleSettings;
 import org.elasticsearch.xpack.ilm.IndexLifecycle;
@@ -37,9 +37,8 @@ public abstract class ProfilingTestCase extends ESIntegTestCase {
     @Override
     protected Collection<Class<? extends Plugin>> nodePlugins() {
         return List.of(
-            LocalStateCompositeXPackPlugin.class,
             DataStreamsPlugin.class,
-            ProfilingPlugin.class,
+            LocalStateProfilingXPackPlugin.class,
             IndexLifecycle.class,
             UnsignedLongMapperPlugin.class,
             VersionFieldPlugin.class,
@@ -58,6 +57,7 @@ public abstract class ProfilingTestCase extends ESIntegTestCase {
             // .put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
             // Disable ILM history index so that the tests don't have to clean it up
             .put(LifecycleSettings.LIFECYCLE_HISTORY_INDEX_ENABLED_SETTING.getKey(), false)
+            .put(LicenseSettings.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
             .build();
     }
 

+ 49 - 0
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingInfoTransportAction.java

@@ -0,0 +1,49 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.transport.TransportService;
+import org.elasticsearch.xpack.core.XPackField;
+import org.elasticsearch.xpack.core.XPackSettings;
+import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
+import org.elasticsearch.xpack.core.action.XPackInfoFeatureTransportAction;
+
+public class ProfilingInfoTransportAction extends XPackInfoFeatureTransportAction {
+    private final boolean enabled;
+    private final ProfilingLicenseChecker licenseChecker;
+
+    @Inject
+    public ProfilingInfoTransportAction(
+        TransportService transportService,
+        ActionFilters actionFilters,
+        Settings settings,
+        ProfilingLicenseChecker licenseChecker
+    ) {
+        super(XPackInfoFeatureAction.UNIVERSAL_PROFILING.name(), transportService, actionFilters);
+        this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
+        this.licenseChecker = licenseChecker;
+    }
+
+    @Override
+    public String name() {
+        return XPackField.UNIVERSAL_PROFILING;
+    }
+
+    @Override
+    public boolean available() {
+        return licenseChecker.isSupportedLicense();
+    }
+
+    @Override
+    public boolean enabled() {
+        return enabled;
+    }
+}

+ 39 - 0
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingLicenseChecker.java

@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import org.elasticsearch.license.License;
+import org.elasticsearch.license.LicenseUtils;
+import org.elasticsearch.license.LicensedFeature;
+import org.elasticsearch.license.XPackLicenseState;
+
+import java.util.function.Supplier;
+
+public final class ProfilingLicenseChecker {
+    private static final LicensedFeature.Momentary UNIVERSAL_PROFILING_FEATURE = LicensedFeature.momentary(
+        null,
+        "universal_profiling",
+        License.OperationMode.ENTERPRISE
+    );
+
+    private final Supplier<XPackLicenseState> licenseStateResolver;
+
+    public ProfilingLicenseChecker(Supplier<XPackLicenseState> licenseStateResolver) {
+        this.licenseStateResolver = licenseStateResolver;
+    }
+
+    public boolean isSupportedLicense() {
+        return UNIVERSAL_PROFILING_FEATURE.checkWithoutTracking(licenseStateResolver.get());
+    }
+
+    public void requireSupportedLicense() {
+        if (UNIVERSAL_PROFILING_FEATURE.check(licenseStateResolver.get()) == false) {
+            throw LicenseUtils.newComplianceException(UNIVERSAL_PROFILING_FEATURE.getName());
+        }
+    }
+}

+ 11 - 4
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingPlugin.java

@@ -39,7 +39,10 @@ import org.elasticsearch.threadpool.ScalingExecutorBuilder;
 import org.elasticsearch.threadpool.ThreadPool;
 import org.elasticsearch.watcher.ResourceWatcherService;
 import org.elasticsearch.xcontent.NamedXContentRegistry;
+import org.elasticsearch.xpack.core.XPackPlugin;
 import org.elasticsearch.xpack.core.XPackSettings;
+import org.elasticsearch.xpack.core.action.XPackInfoFeatureAction;
+import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -108,10 +111,12 @@ public class ProfilingPlugin extends Plugin implements ActionPlugin {
             registry.get().initialize();
             indexManager.get().initialize();
             dataStreamManager.get().initialize();
-            return List.of(registry.get(), indexManager.get(), dataStreamManager.get());
-        } else {
-            return Collections.emptyList();
         }
+        return Collections.singletonList(createLicenseChecker());
+    }
+
+    protected ProfilingLicenseChecker createLicenseChecker() {
+        return new ProfilingLicenseChecker(XPackPlugin::getSharedLicenseState);
     }
 
     public void updateCheckOutdatedIndices(boolean newValue) {
@@ -179,7 +184,9 @@ public class ProfilingPlugin extends Plugin implements ActionPlugin {
         return List.of(
             new ActionHandler<>(GetStackTracesAction.INSTANCE, TransportGetStackTracesAction.class),
             new ActionHandler<>(GetFlamegraphAction.INSTANCE, TransportGetFlamegraphAction.class),
-            new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class)
+            new ActionHandler<>(GetStatusAction.INSTANCE, TransportGetStatusAction.class),
+            new ActionHandler<>(XPackUsageFeatureAction.UNIVERSAL_PROFILING, ProfilingUsageTransportAction.class),
+            new ActionHandler<>(XPackInfoFeatureAction.UNIVERSAL_PROFILING, ProfilingInfoTransportAction.class)
         );
     }
 

+ 64 - 0
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/ProfilingUsageTransportAction.java

@@ -0,0 +1,64 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.cluster.ClusterState;
+import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
+import org.elasticsearch.cluster.service.ClusterService;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.protocol.xpack.XPackUsageRequest;
+import org.elasticsearch.tasks.Task;
+import org.elasticsearch.threadpool.ThreadPool;
+import org.elasticsearch.transport.TransportService;
+import org.elasticsearch.xpack.core.XPackSettings;
+import org.elasticsearch.xpack.core.action.XPackUsageFeatureAction;
+import org.elasticsearch.xpack.core.action.XPackUsageFeatureResponse;
+import org.elasticsearch.xpack.core.action.XPackUsageFeatureTransportAction;
+import org.elasticsearch.xpack.core.application.ProfilingUsage;
+
+public class ProfilingUsageTransportAction extends XPackUsageFeatureTransportAction {
+    private final ProfilingLicenseChecker licenseChecker;
+
+    private final boolean enabled;
+
+    @Inject
+    public ProfilingUsageTransportAction(
+        TransportService transportService,
+        ClusterService clusterService,
+        ThreadPool threadPool,
+        ActionFilters actionFilters,
+        IndexNameExpressionResolver indexNameExpressionResolver,
+        ProfilingLicenseChecker licenseChecker,
+        Settings settings
+    ) {
+        super(
+            XPackUsageFeatureAction.UNIVERSAL_PROFILING.name(),
+            transportService,
+            clusterService,
+            threadPool,
+            actionFilters,
+            indexNameExpressionResolver
+        );
+        this.licenseChecker = licenseChecker;
+        this.enabled = XPackSettings.PROFILING_ENABLED.get(settings);
+    }
+
+    @Override
+    protected void masterOperation(
+        Task task,
+        XPackUsageRequest request,
+        ClusterState state,
+        ActionListener<XPackUsageFeatureResponse> listener
+    ) {
+        ProfilingUsage profilingUsage = new ProfilingUsage(licenseChecker.isSupportedLicense(), enabled);
+        listener.onResponse(new XPackUsageFeatureResponse(profilingUsage));
+    }
+}

+ 4 - 0
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java

@@ -88,6 +88,7 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
     );
 
     private final NodeClient nodeClient;
+    private final ProfilingLicenseChecker licenseChecker;
     private final ClusterService clusterService;
     private final TransportService transportService;
     private final Executor responseExecutor;
@@ -105,10 +106,12 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
         TransportService transportService,
         ActionFilters actionFilters,
         NodeClient nodeClient,
+        ProfilingLicenseChecker licenseChecker,
         IndexNameExpressionResolver resolver
     ) {
         super(GetStackTracesAction.NAME, transportService, actionFilters, GetStackTracesRequest::new, EsExecutors.DIRECT_EXECUTOR_SERVICE);
         this.nodeClient = nodeClient;
+        this.licenseChecker = licenseChecker;
         this.clusterService = clusterService;
         this.transportService = transportService;
         this.responseExecutor = threadPool.executor(ProfilingPlugin.PROFILING_THREAD_POOL_NAME);
@@ -120,6 +123,7 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
 
     @Override
     protected void doExecute(Task submitTask, GetStackTracesRequest request, ActionListener<GetStackTracesResponse> submitListener) {
+        licenseChecker.requireSupportedLicense();
         long start = System.nanoTime();
         Client client = new ParentTaskAssigningClient(this.nodeClient, transportService.getLocalNode(), submitTask);
         EventsIndex mediumDownsampled = EventsIndex.MEDIUM_DOWNSAMPLED;

+ 56 - 0
x-pack/plugin/profiling/src/test/java/org/elasticsearch/xpack/profiling/ProfilingInfoTransportActionTests.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import org.elasticsearch.action.support.ActionFilters;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.license.License;
+import org.elasticsearch.license.XPackLicenseState;
+import org.elasticsearch.license.internal.XPackLicenseStatus;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.transport.TransportService;
+import org.elasticsearch.xpack.core.XPackSettings;
+
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Mockito.mock;
+
+public class ProfilingInfoTransportActionTests extends ESTestCase {
+    public void testAvailable() {
+        // trial mode - allow feature
+        XPackLicenseState licenseState = new XPackLicenseState(() -> 0);
+
+        boolean enabled = randomBoolean();
+        Settings settings = Settings.builder().put(XPackSettings.PROFILING_ENABLED.getKey(), enabled).build();
+
+        ProfilingInfoTransportAction featureSet = new ProfilingInfoTransportAction(
+            mock(TransportService.class),
+            mock(ActionFilters.class),
+            settings,
+            new ProfilingLicenseChecker(() -> licenseState)
+        );
+        assertThat(featureSet.available(), is(true));
+        assertThat(featureSet.enabled(), is(enabled));
+    }
+
+    public void testUnavailable() {
+        // won't work in BASIC
+        XPackLicenseState licenseState = new XPackLicenseState(() -> 0, new XPackLicenseStatus(License.OperationMode.BASIC, true, null));
+
+        boolean enabled = randomBoolean();
+        Settings settings = Settings.builder().put(XPackSettings.PROFILING_ENABLED.getKey(), enabled).build();
+
+        ProfilingInfoTransportAction featureSet = new ProfilingInfoTransportAction(
+            mock(TransportService.class),
+            mock(ActionFilters.class),
+            settings,
+            new ProfilingLicenseChecker(() -> licenseState)
+        );
+        assertThat(featureSet.available(), is(false));
+        assertThat(featureSet.enabled(), is(enabled));
+    }
+}

+ 2 - 0
x-pack/plugin/security/qa/operator-privileges-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/operator/Constants.java

@@ -347,6 +347,7 @@ public class Constants {
         "cluster:monitor/xpack/info/spatial",
         "cluster:monitor/xpack/info/sql",
         "cluster:monitor/xpack/info/transform",
+        "cluster:monitor/xpack/info/universal_profiling",
         "cluster:monitor/xpack/info/voting_only",
         "cluster:monitor/xpack/info/watcher",
         "cluster:monitor/xpack/license/get",
@@ -410,6 +411,7 @@ public class Constants {
         "cluster:monitor/xpack/usage/spatial",
         "cluster:monitor/xpack/usage/sql",
         "cluster:monitor/xpack/usage/transform",
+        "cluster:monitor/xpack/usage/universal_profiling",
         "cluster:monitor/xpack/usage/voting_only",
         "cluster:monitor/xpack/usage/watcher",
         "cluster:monitor/xpack/watcher/stats/dist",