Browse Source

Add enterprise mode and refactor license check (#51864)

Add enterprise operation mode to properly map enterprise license.

Aslo refactor XPackLicenstate class to consolidate license status and mode checks.
This class has many sychronised methods to check basically three things:
* Minimum operation mode required
* Whether security is enabled
* Whether current license needs to be active

Depends on the actual feature, either 1, 2 or all of above checks are performed. 
These are now consolidated in to 3 helper methods (2 of them are new).
The synchronization is pushed down to the helper methods so actual checking
methods no longer need to worry about it.

resolves: #51081
Yang Wang 5 years ago
parent
commit
4ab16c6711
21 changed files with 205 additions and 220 deletions
  1. 2 2
      x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java
  2. 4 2
      x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java
  3. 1 0
      x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java
  4. 2 2
      x-pack/plugin/core/src/main/java/org/elasticsearch/license/RemoteClusterLicenseChecker.java
  5. 112 169
      x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java
  6. 2 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/TrainedModelConfig.java
  7. 3 3
      x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseOperationModeTests.java
  8. 15 9
      x-pack/plugin/core/src/test/java/org/elasticsearch/license/RemoteClusterLicenseCheckerTests.java
  9. 5 0
      x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java
  10. 12 12
      x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java
  11. 12 6
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/common/validation/SourceDestValidatorTests.java
  12. 18 0
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/inference/TrainedModelConfigTests.java
  13. 2 2
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java
  14. 1 1
      x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java
  15. 1 1
      x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java
  16. 1 0
      x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java
  17. 1 2
      x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
  18. 3 2
      x-pack/plugin/security/src/test/java/org/elasticsearch/license/LicensingTests.java
  19. 4 3
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java
  20. 2 2
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java
  21. 2 1
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java

+ 2 - 2
x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java

@@ -412,7 +412,7 @@ public class CcrLicenseChecker {
                 RemoteClusterLicenseChecker.buildErrorMessage(
                         "ccr",
                         licenseCheck.remoteClusterLicenseInfo(),
-                        RemoteClusterLicenseChecker::isLicensePlatinumOrTrial));
+                        RemoteClusterLicenseChecker::isAllowedByLicense));
         return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST);
     }
 
@@ -426,7 +426,7 @@ public class CcrLicenseChecker {
                 RemoteClusterLicenseChecker.buildErrorMessage(
                         "ccr",
                         licenseCheck.remoteClusterLicenseInfo(),
-                        RemoteClusterLicenseChecker::isLicensePlatinumOrTrial));
+                        RemoteClusterLicenseChecker::isAllowedByLicense));
         return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST);
     }
 

+ 4 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java

@@ -175,7 +175,8 @@ public class License implements ToXContentObject {
         BASIC((byte) 2),
         STANDARD((byte) 3),
         GOLD((byte) 4),
-        PLATINUM((byte) 5);
+        PLATINUM((byte) 5),
+        ENTERPRISE((byte) 6);
 
         private final byte id;
 
@@ -208,8 +209,9 @@ public class License implements ToXContentObject {
                 case GOLD:
                     return GOLD;
                 case PLATINUM:
-                case ENTERPRISE: // TODO Add an explicit enterprise operating mode
                     return PLATINUM;
+                case ENTERPRISE:
+                    return ENTERPRISE;
                 case TRIAL:
                     return TRIAL;
                 default:

+ 1 - 0
x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java

@@ -256,6 +256,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
                         "] license unless TLS is configured or security is disabled");
                 } else if (XPackSettings.FIPS_MODE_ENABLED.get(settings)
                     && newLicense.operationMode() != License.OperationMode.PLATINUM
+                    && newLicense.operationMode() != License.OperationMode.ENTERPRISE
                     && newLicense.operationMode() != License.OperationMode.TRIAL) {
                     throw new IllegalStateException("Cannot install a [" + newLicense.operationMode() +
                         "] license unless FIPS mode is disabled");

+ 2 - 2
x-pack/plugin/core/src/main/java/org/elasticsearch/license/RemoteClusterLicenseChecker.java

@@ -138,9 +138,9 @@ public final class RemoteClusterLicenseChecker {
         this.predicate = predicate;
     }
 
-    public static boolean isLicensePlatinumOrTrial(final XPackInfoResponse.LicenseInfo licenseInfo) {
+    public static boolean isAllowedByLicense(final XPackInfoResponse.LicenseInfo licenseInfo) {
         final License.OperationMode mode = License.OperationMode.parse(licenseInfo.getMode());
-        return mode == License.OperationMode.PLATINUM || mode == License.OperationMode.TRIAL;
+        return XPackLicenseState.isAllowedByOperationMode(mode, License.OperationMode.PLATINUM, true);
     }
 
     /**

+ 112 - 169
x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java

@@ -16,12 +16,10 @@ import org.elasticsearch.xpack.core.XPackSettings;
 import org.elasticsearch.xpack.core.monitoring.MonitoringField;
 
 import java.util.Collections;
-import java.util.EnumSet;
 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.function.BiFunction;
 
@@ -30,9 +28,6 @@ import java.util.function.BiFunction;
  */
 public class XPackLicenseState {
 
-    public static final Set<OperationMode> FIPS_ALLOWED_LICENSE_OPERATION_MODES =
-        EnumSet.of(License.OperationMode.PLATINUM, License.OperationMode.TRIAL);
-
     /** Messages for each feature which are printed when the license expires. */
     static final Map<String, String[]> EXPIRATION_MESSAGES;
     static {
@@ -114,6 +109,7 @@ public class XPackLicenseState {
                     case TRIAL:
                     case GOLD:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] {
                             "Security will default to disabled (set " + XPackSettings.SECURITY_ENABLED.getKey() + " to enable security).",
                             "Authentication will be limited to the native and file realms.",
@@ -132,6 +128,7 @@ public class XPackLicenseState {
                         // ^^ though technically it was already disabled, it's not bad to remind them
                     case TRIAL:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] {
                             "Field and document level access control will be disabled.",
                             "Custom realms will be ignored.",
@@ -145,6 +142,7 @@ public class XPackLicenseState {
                         // ^^ though technically it doesn't change the feature set, it's not bad to remind them
                     case GOLD:
                     case PLATINUM:
+                    case ENTERPRISE:
                     case TRIAL:
                         return new String[] {
                             "Authentication will be limited to the native realms.",
@@ -166,6 +164,7 @@ public class XPackLicenseState {
                     case STANDARD:
                     case GOLD:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] { "Watcher will be disabled" };
                 }
                 break;
@@ -181,6 +180,7 @@ public class XPackLicenseState {
                     case STANDARD:
                     case GOLD:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] {
                             LoggerMessageFormat.format(
                                 "Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
@@ -206,6 +206,7 @@ public class XPackLicenseState {
                 switch (currentMode) {
                     case TRIAL:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] { "Graph will be disabled" };
                 }
                 break;
@@ -221,6 +222,7 @@ public class XPackLicenseState {
                 switch (currentMode) {
                     case TRIAL:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] { "Machine learning will be disabled" };
                 }
                 break;
@@ -258,6 +260,7 @@ public class XPackLicenseState {
                 switch (currentMode) {
                     case TRIAL:
                     case PLATINUM:
+                    case ENTERPRISE:
                         return new String[] {
                                 "JDBC and ODBC support will be disabled, but you can continue to use SQL CLI and REST endpoint" };
                 }
@@ -348,41 +351,22 @@ public class XPackLicenseState {
      * @return true if authentication and authorization should be enabled. this does not indicate what realms are available
      * @see #allowedRealmType() for the enabled realms
      */
-    public synchronized boolean isAuthAllowed() {
-        OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        if (isSecurityCurrentlyEnabled) {
-            switch (mode) {
-                case BASIC:
-                case STANDARD:
-                case GOLD:
-                case PLATINUM:
-                case TRIAL:
-                    return true;
-            }
-        }
-        return false;
+    public boolean isAuthAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.BASIC, true, false, true);
     }
 
     /**
      * @return true if IP filtering should be enabled
      */
-    public synchronized boolean isIpFilteringAllowed() {
-        OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL);
+    public boolean isIpFilteringAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.GOLD, true, false, true);
     }
 
     /**
      * @return true if auditing should be enabled
      */
-    public synchronized boolean isAuditingAllowed() {
-        OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL);
+    public boolean isAuditingAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.GOLD, true, false, true);
     }
 
     /**
@@ -391,8 +375,8 @@ public class XPackLicenseState {
      *
      * @return true if the license allows for the stats and health APIs to be used.
      */
-    public synchronized boolean isStatsAndHealthAllowed() {
-        return status.active;
+    public boolean isStatsAndHealthAllowed() {
+        return isActive();
     }
 
     /**
@@ -407,11 +391,8 @@ public class XPackLicenseState {
      *
      * @return {@code true} to enable DLS and FLS. Otherwise {@code false}.
      */
-    public synchronized boolean isDocumentAndFieldLevelSecurityAllowed() {
-        OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (mode == OperationMode.TRIAL || mode == OperationMode.PLATINUM);
+    public boolean isDocumentAndFieldLevelSecurityAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, true, false, true);
     }
 
     /** Classes of realms that may be available based on the license type. */
@@ -431,6 +412,7 @@ public class XPackLicenseState {
         if (isSecurityCurrentlyEnabled) {
             switch (status.mode) {
                 case PLATINUM:
+                case ENTERPRISE:
                 case TRIAL:
                     return AllowedRealmType.ALL;
                 case GOLD:
@@ -449,51 +431,38 @@ public class XPackLicenseState {
     /**
      * @return whether custom role providers are allowed based on the license {@link OperationMode}
      */
-    public synchronized boolean isCustomRoleProvidersAllowed() {
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (status.mode == OperationMode.PLATINUM || status.mode == OperationMode.TRIAL)
-                && status.active;
+    public boolean isCustomRoleProvidersAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, true, true, true);
     }
 
     /**
      * @return whether the Elasticsearch {@code TokenService} is allowed based on the license {@link OperationMode}
      */
-    public synchronized boolean isTokenServiceAllowed() {
-        final OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled = isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.TRIAL);
+    public boolean isTokenServiceAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.GOLD, true, false, true);
     }
 
     /**
      * @return whether the Elasticsearch {@code ApiKeyService} is allowed based on the current node/cluster state
      */
-    public synchronized boolean isApiKeyServiceAllowed() {
-        final OperationMode mode = status.mode;
-        final boolean isSecurityCurrentlyEnabled = isSecurityEnabled(mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled;
+    public boolean isApiKeyServiceAllowed() {
+        return isAllowedBySecurity();
     }
 
     /**
      * @return whether "authorization_realms" are allowed based on the license {@link OperationMode}
      * @see org.elasticsearch.xpack.core.security.authc.support.DelegatedAuthorizationSettings
      */
-    public synchronized boolean isAuthorizationRealmAllowed() {
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (status.mode == OperationMode.PLATINUM || status.mode == OperationMode.TRIAL)
-            && status.active;
+    public boolean isAuthorizationRealmAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, true, true, true);
     }
 
     /**
      * @return whether a custom authorization engine is allowed based on the license {@link OperationMode}
      * @see org.elasticsearch.xpack.core.security.authc.support.DelegatedAuthorizationSettings
      */
-    public synchronized boolean isAuthorizationEngineAllowed() {
-        final boolean isSecurityCurrentlyEnabled =
-            isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
-        return isSecurityCurrentlyEnabled && (status.mode == OperationMode.PLATINUM || status.mode == OperationMode.TRIAL)
-            && status.active;
+    public boolean isAuthorizationEngineAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, true, true, true);
     }
 
     /**
@@ -509,22 +478,8 @@ public class XPackLicenseState {
      *
      * @return {@code true} as long as the license is valid. Otherwise {@code false}.
      */
-    public synchronized boolean isWatcherAllowed() {
-        Status localStatus = status;
-
-        if (localStatus.active == false) {
-            return false;
-        }
-
-        switch (localStatus.mode) {
-            case TRIAL:
-            case GOLD:
-            case PLATINUM:
-            case STANDARD:
-                return true;
-            default:
-                return false;
-        }
+    public boolean isWatcherAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.STANDARD, false, true, true);
     }
 
     /**
@@ -532,8 +487,8 @@ public class XPackLicenseState {
      *
      * @return true if the license is active
      */
-    public synchronized boolean isMonitoringAllowed() {
-        return status.active;
+    public boolean isMonitoringAllowed() {
+        return isActive();
     }
 
     /**
@@ -542,7 +497,7 @@ public class XPackLicenseState {
      * @return {@link #isWatcherAllowed()}
      * @see #isWatcherAllowed()
      */
-    public synchronized boolean isMonitoringClusterAlertsAllowed() {
+    public boolean isMonitoringClusterAlertsAllowed() {
         return isWatcherAllowed();
     }
 
@@ -555,9 +510,8 @@ public class XPackLicenseState {
      *
      * @return {@code true} if the user is allowed to modify the retention. Otherwise {@code false}.
      */
-    public synchronized boolean isUpdateRetentionAllowed() {
-        final OperationMode mode = status.mode;
-        return mode != OperationMode.BASIC && mode != OperationMode.MISSING;
+    public boolean isUpdateRetentionAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.STANDARD, false, false, true);
     }
 
     /**
@@ -571,13 +525,8 @@ public class XPackLicenseState {
      *
      * @return {@code true} as long as the license is valid. Otherwise {@code false}.
      */
-    public synchronized boolean isGraphAllowed() {
-        Status localStatus = status;
-        OperationMode operationMode = localStatus.mode;
-
-        boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
-
-        return licensed && localStatus.active;
+    public boolean isGraphAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, false, true, true);
     }
 
     /**
@@ -593,13 +542,12 @@ public class XPackLicenseState {
      * @return {@code true} as long as the license is valid. Otherwise
      *         {@code false}.
      */
-    public synchronized boolean isMachineLearningAllowed() {
-        final Status currentStatus = status;
-        return currentStatus.active && isMachineLearningAllowedForOperationMode(currentStatus.mode);
+    public boolean isMachineLearningAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, false, true, true);
     }
 
     public static boolean isMachineLearningAllowedForOperationMode(final OperationMode operationMode) {
-        return isPlatinumOrTrialOperationMode(operationMode);
+        return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM, true);
     }
 
     /**
@@ -607,8 +555,8 @@ public class XPackLicenseState {
      *
      * @return true if the license is active
      */
-    public synchronized boolean isTransformAllowed() {
-        return status.active;
+    public boolean isTransformAllowed() {
+        return isActive();
     }
 
     public static boolean isTransformAllowedForOperationMode(final OperationMode operationMode) {
@@ -616,13 +564,17 @@ public class XPackLicenseState {
         return operationMode != License.OperationMode.MISSING;
     }
 
+    public static boolean isFipsAllowedForOperationMode(final OperationMode operationMode) {
+        return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM, true);
+    }
+
     /**
      * Rollup is always available as long as there is a valid license
      *
      * @return true if the license is active
      */
-    public synchronized boolean isRollupAllowed() {
-        return status.active;
+    public boolean isRollupAllowed() {
+        return isActive();
     }
 
     /**
@@ -630,80 +582,62 @@ public class XPackLicenseState {
      *
      * @return true if the license is active
      */
-    public synchronized boolean isVotingOnlyAllowed() {
-        return status.active;
+    public boolean isVotingOnlyAllowed() {
+        return isActive();
     }
 
     /**
      * Logstash is allowed as long as there is an active license of type TRIAL, STANDARD, GOLD or PLATINUM
      * @return {@code true} as long as there is a valid license
      */
-    public synchronized boolean isLogstashAllowed() {
-        Status localStatus = status;
-        return localStatus.active && (isBasic(localStatus.mode) == false);
+    public boolean isLogstashAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.STANDARD, false, true, true);
     }
 
     /**
      * Beats is allowed as long as there is an active license of type TRIAL, STANDARD, GOLD or PLATINUM
      * @return {@code true} as long as there is a valid license
      */
-    public synchronized boolean isBeatsAllowed() {
-        Status localStatus = status;
-        return localStatus.active && (isBasic(localStatus.mode) == false);
-
+    public boolean isBeatsAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.STANDARD, false, true, true);
     }
 
     /**
      * Deprecation APIs are always allowed as long as there is an active license
      * @return {@code true} as long as there is a valid license
      */
-    public synchronized boolean isDeprecationAllowed() {
-        return status.active;
+    public boolean isDeprecationAllowed() {
+        return isActive();
     }
 
     /**
      * Determine if Upgrade API should be enabled.
-     * <p>
-     *  Upgrade API is not available in for all license types except {@link OperationMode#MISSING}
      *
      * @return {@code true} as long as the license is valid. Otherwise
      *         {@code false}.
      */
-    public synchronized boolean isUpgradeAllowed() {
-        // Should work on all active licenses
-        return status.active;
+    public boolean isUpgradeAllowed() {
+        return isActive();
     }
 
     /**
      * Determine if Index Lifecycle API should be enabled.
-     * <p>
-     * Index Lifecycle API is available in for all license types except
-     * {@link OperationMode#MISSING}
      *
      * @return {@code true} as long as the license is valid. Otherwise
      *         {@code false}.
      */
     public boolean isIndexLifecycleAllowed() {
-        // status is volatile
-        Status localStatus = status;
-        // Should work on all active licenses
-        return localStatus.active;
+        return isActive();
     }
 
     /**
      * Determine if the enrich processor and related APIs are allowed to be used.
-     * <p>
-     * This is available in for all license types except
-     * {@link OperationMode#MISSING}
      *
      * @return {@code true} as long as the license is valid. Otherwise
      *         {@code false}.
      */
     public boolean isEnrichAllowed() {
-        // status is volatile
-        Status localStatus = status;
-        // Should work on all active licenses
-        return localStatus.active;
+        return isActive();
     }
 
     /**
@@ -717,11 +651,9 @@ public class XPackLicenseState {
 
     /**
      * Determine if SQL support should be enabled.
-     * <p>
-     *  SQL is available for all license types except {@link OperationMode#MISSING}
      */
-    public synchronized boolean isSqlAllowed() {
-        return status.active;
+    public boolean isSqlAllowed() {
+        return isActive();
     }
 
     /**
@@ -729,31 +661,22 @@ public class XPackLicenseState {
      * <p>
      *  JDBC is available only in for {@link OperationMode#PLATINUM} and {@link OperationMode#TRIAL} licences
      */
-    public synchronized boolean isJdbcAllowed() {
-        Status localStatus = status;
-        OperationMode operationMode = localStatus.mode;
-
-        boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
-
-        return licensed && localStatus.active;
+    public boolean isJdbcAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, false, true, true);
     }
 
     /**
      * Determine if support for flattened object fields should be enabled.
-     * <p>
-     * Flattened fields are available for all license types except {@link OperationMode#MISSING}.
      */
-    public synchronized boolean isFlattenedAllowed() {
-        return status.active;
+    public boolean isFlattenedAllowed() {
+        return isActive();
     }
 
     /**
      * Determine if Vectors support should be enabled.
-     * <p>
-     *  Vectors is available for all license types except {@link OperationMode#MISSING}
      */
-    public synchronized boolean isVectorsAllowed() {
-        return status.active;
+    public boolean isVectorsAllowed() {
+        return isActive();
     }
 
     /**
@@ -761,29 +684,18 @@ public class XPackLicenseState {
      * <p>
      * ODBC is available only in for {@link OperationMode#PLATINUM} and {@link OperationMode#TRIAL} licences
      */
-    public synchronized boolean isOdbcAllowed() {
-        Status localStatus = status;
-        OperationMode operationMode = localStatus.mode;
-
-        boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
-
-        return licensed && localStatus.active;
+    public boolean isOdbcAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, false, true, true);
     }
 
     /**
      * Determine if Spatial features should be enabled.
-     * <p>
-     * Spatial features are available in for all license types except
-     * {@link OperationMode#MISSING}
      *
      * @return {@code true} as long as the license is valid. Otherwise
      *         {@code false}.
      */
     public boolean isSpatialAllowed() {
-        // status is volatile
-        Status localStatus = status;
-        // Should work on all active licenses
-        return localStatus.active;
+        return isActive();
     }
 
     /**
@@ -791,8 +703,8 @@ public class XPackLicenseState {
      *
      * @return true if the license is active
      */
-    public synchronized boolean isDataScienceAllowed() {
-        return status.active;
+    public boolean isDataScienceAllowed() {
+        return isActive();
     }
 
     public synchronized boolean isTrialLicense() {
@@ -805,7 +717,7 @@ public class XPackLicenseState {
     public synchronized boolean isSecurityAvailable() {
         OperationMode mode = status.mode;
         return mode == OperationMode.GOLD || mode == OperationMode.PLATINUM || mode == OperationMode.STANDARD ||
-                mode == OperationMode.TRIAL || mode == OperationMode.BASIC;
+                mode == OperationMode.TRIAL || mode == OperationMode.BASIC || mode == OperationMode.ENTERPRISE;
     }
 
     /**
@@ -833,6 +745,7 @@ public class XPackLicenseState {
             case STANDARD:
             case GOLD:
             case PLATINUM:
+            case ENTERPRISE:
                 return XPackSettings.SECURITY_ENABLED.get(settings);
             case BASIC:
                 return XPackSettings.SECURITY_ENABLED.get(settings) && isSecurityExplicitlyEnabled(settings);
@@ -866,17 +779,20 @@ public class XPackLicenseState {
      *
      * @return true is the license is compatible, otherwise false
      */
-    public synchronized boolean isCcrAllowed() {
-        final Status currentStatus = status;
-        return currentStatus.active && isCcrAllowedForOperationMode(currentStatus.mode);
+    public boolean isCcrAllowed() {
+        return isAllowedByLicenseAndSecurity(OperationMode.PLATINUM, false, true, true);
     }
 
     public static boolean isCcrAllowedForOperationMode(final OperationMode operationMode) {
-        return isPlatinumOrTrialOperationMode(operationMode);
+        return isAllowedByOperationMode(operationMode, OperationMode.PLATINUM, true);
     }
 
-    public static boolean isPlatinumOrTrialOperationMode(final OperationMode operationMode) {
-        return operationMode == OperationMode.PLATINUM || operationMode == OperationMode.TRIAL;
+    public static boolean isAllowedByOperationMode(
+        final OperationMode operationMode, final OperationMode minimumMode, final boolean allowTrial) {
+        if (allowTrial && OperationMode.TRIAL == operationMode) {
+            return true;
+        }
+        return operationMode.compareTo(minimumMode) >= 0;
     }
 
     /**
@@ -889,4 +805,31 @@ public class XPackLicenseState {
     public synchronized XPackLicenseState copyCurrentLicenseState() {
         return new XPackLicenseState(this);
     }
+
+    private synchronized boolean isAllowedBySecurity() {
+        return isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled);
+    }
+
+    /**
+     * Test whether a feature is allowed by the status of current license and security configuration.
+     *
+     * @param minimumMode  The minimum license to meet or exceed
+     * @param needSecurity Whether security is required for feature to be allowed
+     * @param needActive   Whether current license needs to be active
+     * @param allowTrial   Whether the feature is allowed for trial license
+     *
+     * @return true if feature is allowed, otherwise false
+     */
+    private synchronized boolean isAllowedByLicenseAndSecurity(
+        OperationMode minimumMode, boolean needSecurity, boolean needActive, boolean allowTrial) {
+
+        if (needSecurity && false == isSecurityEnabled(status.mode, isSecurityExplicitlyEnabled, isSecurityEnabled)) {
+            return false;
+        }
+        if (needActive && false == status.active) {
+            return false;
+        }
+        return isAllowedByOperationMode(status.mode, minimumMode, allowTrial);
+    }
+
 }

+ 2 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/inference/TrainedModelConfig.java

@@ -243,7 +243,8 @@ public class TrainedModelConfig implements ToXContentObject, Writeable {
         }
 
         // The model license does not matter, this is the highest licensed level
-        if (licenseState.isActive() && XPackLicenseState.isPlatinumOrTrialOperationMode(licenseState.getOperationMode())) {
+        if (licenseState.isActive() && XPackLicenseState.isAllowedByOperationMode(
+            licenseState.getOperationMode(), License.OperationMode.PLATINUM, true)) {
             return true;
         }
 

+ 3 - 3
x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseOperationModeTests.java

@@ -47,9 +47,9 @@ public class LicenseOperationModeTests extends ESTestCase {
         assertResolve(OperationMode.PLATINUM, "PlAtINum", "platinum");
     }
 
-    public void testResolveEnterpriseAsPlatinum() {
-        assertResolve(OperationMode.PLATINUM, License.LicenseType.ENTERPRISE.getTypeName());
-        assertResolve(OperationMode.PLATINUM, License.LicenseType.ENTERPRISE.name());
+    public void testResolveEnterprise() {
+        assertResolve(OperationMode.ENTERPRISE, License.LicenseType.ENTERPRISE.getTypeName());
+        assertResolve(OperationMode.ENTERPRISE, License.LicenseType.ENTERPRISE.name());
     }
 
     public void testResolveUnknown() {

+ 15 - 9
x-pack/plugin/core/src/test/java/org/elasticsearch/license/RemoteClusterLicenseCheckerTests.java

@@ -146,7 +146,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         responses.add(new XPackInfoResponse(null, createPlatinumLicenseResponse(), null));
 
         final RemoteClusterLicenseChecker licenseChecker =
-                new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+                new RemoteClusterLicenseChecker(client, operationMode ->
+                    XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
         final AtomicReference<RemoteClusterLicenseChecker.LicenseCheck> licenseCheck = new AtomicReference<>();
 
         licenseChecker.checkRemoteClusterLicenses(
@@ -188,7 +189,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         }).when(client).execute(same(XPackInfoAction.INSTANCE), any(), any());
 
         final RemoteClusterLicenseChecker licenseChecker =
-                new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+                new RemoteClusterLicenseChecker(client, operationMode ->
+                    XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
         final AtomicReference<RemoteClusterLicenseChecker.LicenseCheck> licenseCheck = new AtomicReference<>();
 
         licenseChecker.checkRemoteClusterLicenses(
@@ -234,7 +236,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         responses.add(new XPackInfoResponse(null, createPlatinumLicenseResponse(), null));
 
         final RemoteClusterLicenseChecker licenseChecker =
-                new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+                new RemoteClusterLicenseChecker(client, operationMode ->
+                    XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
         final AtomicReference<Exception> exception = new AtomicReference<>();
 
         licenseChecker.checkRemoteClusterLicenses(
@@ -274,7 +277,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
             }).when(client).execute(same(XPackInfoAction.INSTANCE), any(), any());
 
             final RemoteClusterLicenseChecker licenseChecker =
-                    new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+                    new RemoteClusterLicenseChecker(client, operationMode ->
+                        XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
 
             final List<String> remoteClusterAliases = Collections.singletonList("valid");
             licenseChecker.checkRemoteClusterLicenses(
@@ -313,7 +317,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
             responses.add(new XPackInfoResponse(null, createPlatinumLicenseResponse(), null));
 
             final RemoteClusterLicenseChecker licenseChecker =
-                    new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+                    new RemoteClusterLicenseChecker(client, operationMode ->
+                        XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
 
             final AtomicBoolean listenerInvoked = new AtomicBoolean();
             threadPool.getThreadContext().putHeader("key", "value");
@@ -355,7 +360,7 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
                 new RemoteClusterLicenseChecker.RemoteClusterLicenseInfo("platinum-cluster", platinumLicence);
         final AssertionError e = expectThrows(
                 AssertionError.class,
-                () -> RemoteClusterLicenseChecker.buildErrorMessage("", info, RemoteClusterLicenseChecker::isLicensePlatinumOrTrial));
+                () -> RemoteClusterLicenseChecker.buildErrorMessage("", info, RemoteClusterLicenseChecker::isAllowedByLicense));
         assertThat(e, hasToString(containsString("license must be incompatible to build error message")));
     }
 
@@ -364,7 +369,7 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         final RemoteClusterLicenseChecker.RemoteClusterLicenseInfo info =
                 new RemoteClusterLicenseChecker.RemoteClusterLicenseInfo("basic-cluster", basicLicense);
         assertThat(
-                RemoteClusterLicenseChecker.buildErrorMessage("Feature", info, RemoteClusterLicenseChecker::isLicensePlatinumOrTrial),
+                RemoteClusterLicenseChecker.buildErrorMessage("Feature", info, RemoteClusterLicenseChecker::isAllowedByLicense),
                 equalTo("the license mode [BASIC] on cluster [basic-cluster] does not enable [Feature]"));
     }
 
@@ -373,7 +378,7 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         final RemoteClusterLicenseChecker.RemoteClusterLicenseInfo info =
                 new RemoteClusterLicenseChecker.RemoteClusterLicenseInfo("expired-cluster", expiredLicense);
         assertThat(
-                RemoteClusterLicenseChecker.buildErrorMessage("Feature", info, RemoteClusterLicenseChecker::isLicensePlatinumOrTrial),
+                RemoteClusterLicenseChecker.buildErrorMessage("Feature", info, RemoteClusterLicenseChecker::isAllowedByLicense),
                 equalTo("the license on cluster [expired-cluster] is not active"));
     }
 
@@ -388,7 +393,8 @@ public final class RemoteClusterLicenseCheckerTests extends ESTestCase {
         }).when(client).execute(same(XPackInfoAction.INSTANCE), any(), any());
 
         final RemoteClusterLicenseChecker licenseChecker =
-            new RemoteClusterLicenseChecker(client, XPackLicenseState::isPlatinumOrTrialOperationMode);
+            new RemoteClusterLicenseChecker(client, operationMode ->
+                XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true));
         final AtomicReference<Exception> exception = new AtomicReference<>();
 
         licenseChecker.checkRemoteClusterLicenses(

+ 5 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java

@@ -282,6 +282,11 @@ public class TestUtils {
             builder.subscriptionType((type != null) ? type : randomFrom("dev", "gold", "platinum", "silver"));
             builder.feature(randomAlphaOfLength(10));
         }
+        if ("enterprise".equals(licenseType)) {
+            builder.version(License.VERSION_ENTERPRISE)
+                .maxResourceUnits(randomIntBetween(5, 500))
+                .maxNodes(-1);
+        }
         final LicenseSigner signer = new LicenseSigner(getTestPriKeyPath(), getTestPubKeyPath());
         return signer.sign(builder.build());
     }

+ 12 - 12
x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java

@@ -41,7 +41,7 @@ public class XPackLicenseStateTests extends ESTestCase {
      * Checks the ack message going from the  {@code from} license type to {@code to} license type.
      * TODO: check the actual messages, not just the number of them! This was copied from previous license tests...
      */
-    void assertAckMesssages(String feature, OperationMode from, OperationMode to, int expectedMessages) {
+    void assertAckMessages(String feature, OperationMode from, OperationMode to, int expectedMessages) {
         String[] gotMessages = XPackLicenseState.ACKNOWLEDGMENT_MESSAGES.get(feature).apply(from, to);
         assertEquals(expectedMessages, gotMessages.length);
     }
@@ -276,42 +276,42 @@ public class XPackLicenseStateTests extends ESTestCase {
 
     public void testSecurityAckBasicToNotGoldOrStandard() {
         OperationMode toMode = randomFrom(OperationMode.values(), mode -> mode != GOLD && mode != STANDARD);
-        assertAckMesssages(XPackField.SECURITY, BASIC, toMode, 0);
+        assertAckMessages(XPackField.SECURITY, BASIC, toMode, 0);
     }
 
     public void testSecurityAckAnyToTrialOrPlatinum() {
-        assertAckMesssages(XPackField.SECURITY, randomMode(), randomTrialOrPlatinumMode(), 0);
+        assertAckMessages(XPackField.SECURITY, randomMode(), randomTrialOrPlatinumMode(), 0);
     }
 
     public void testSecurityAckTrialGoldOrPlatinumToBasic() {
-        assertAckMesssages(XPackField.SECURITY, randomTrialGoldOrPlatinumMode(), BASIC, 7);
+        assertAckMessages(XPackField.SECURITY, randomTrialGoldOrPlatinumMode(), BASIC, 7);
     }
 
     public void testSecurityAckStandardToBasic() {
-        assertAckMesssages(XPackField.SECURITY, STANDARD, BASIC, 1);
+        assertAckMessages(XPackField.SECURITY, STANDARD, BASIC, 1);
     }
 
     public void testSecurityAckAnyToStandard() {
         OperationMode from = randomFrom(BASIC, GOLD, PLATINUM, TRIAL);
-        assertAckMesssages(XPackField.SECURITY, from, STANDARD, 5);
+        assertAckMessages(XPackField.SECURITY, from, STANDARD, 5);
     }
 
     public void testSecurityAckBasicStandardTrialOrPlatinumToGold() {
         OperationMode from = randomFrom(BASIC, PLATINUM, TRIAL, STANDARD);
-        assertAckMesssages(XPackField.SECURITY, from, GOLD, 3);
+        assertAckMessages(XPackField.SECURITY, from, GOLD, 3);
     }
 
     public void testMonitoringAckBasicToAny() {
-        assertAckMesssages(XPackField.MONITORING, BASIC, randomMode(), 0);
+        assertAckMessages(XPackField.MONITORING, BASIC, randomMode(), 0);
     }
 
     public void testMonitoringAckAnyToTrialGoldOrPlatinum() {
-        assertAckMesssages(XPackField.MONITORING, randomMode(), randomTrialStandardGoldOrPlatinumMode(), 0);
+        assertAckMessages(XPackField.MONITORING, randomMode(), randomTrialStandardGoldOrPlatinumMode(), 0);
     }
 
     public void testMonitoringAckNotBasicToBasic() {
         OperationMode from = randomFrom(STANDARD, GOLD, PLATINUM, TRIAL);
-        assertAckMesssages(XPackField.MONITORING, from, BASIC, 2);
+        assertAckMessages(XPackField.MONITORING, from, BASIC, 2);
     }
 
     public void testMonitoringAllowed() {
@@ -484,11 +484,11 @@ public class XPackLicenseStateTests extends ESTestCase {
     }
 
     public void testSqlAckAnyToTrialOrPlatinum() {
-        assertAckMesssages(XPackField.SQL, randomMode(), randomTrialOrPlatinumMode(), 0);
+        assertAckMessages(XPackField.SQL, randomMode(), randomTrialOrPlatinumMode(), 0);
     }
 
     public void testSqlAckTrialOrPlatinumToNotTrialOrPlatinum() {
-        assertAckMesssages(XPackField.SQL, randomTrialOrPlatinumMode(), randomBasicStandardOrGold(), 1);
+        assertAckMessages(XPackField.SQL, randomTrialOrPlatinumMode(), randomBasicStandardOrGold(), 1);
     }
 
     public void testTransformBasic() throws Exception {

+ 12 - 6
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/common/validation/SourceDestValidatorTests.java

@@ -597,7 +597,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithBasicLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithBasicLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { REMOTE_BASIC + ":" + "SOURCE_1" },
                 "dest",
                 "node_id",
@@ -626,7 +627,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithPlatinumLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithPlatinumLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { REMOTE_PLATINUM + ":" + "SOURCE_1" },
                 "dest",
                 "node_id",
@@ -646,7 +648,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithPlatinumLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithPlatinumLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { REMOTE_PLATINUM + ":" + "SOURCE_1" },
                 "dest",
                 "node_id",
@@ -667,7 +670,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithTrialLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithTrialLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { REMOTE_PLATINUM + ":" + "SOURCE_1" },
                 "dest",
                 "node_id",
@@ -690,7 +694,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithExpiredBasicLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithExpiredBasicLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { REMOTE_BASIC + ":" + "SOURCE_1" },
                 "dest",
                 "node_id",
@@ -716,7 +721,8 @@ public class SourceDestValidatorTests extends ESTestCase {
                 CLUSTER_STATE,
                 new IndexNameExpressionResolver(),
                 remoteClusterService,
-                new RemoteClusterLicenseChecker(clientWithExpiredBasicLicense, XPackLicenseState::isPlatinumOrTrialOperationMode),
+                new RemoteClusterLicenseChecker(clientWithExpiredBasicLicense,
+                    operationMode -> XPackLicenseState.isAllowedByOperationMode(operationMode, License.OperationMode.PLATINUM, true)),
                 new String[] { "non_existing_remote:" + "SOURCE_1" },
                 "dest",
                 "node_id",

+ 18 - 0
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/inference/TrainedModelConfigTests.java

@@ -64,6 +64,7 @@ public class TrainedModelConfigTests extends AbstractSerializingTestCase<Trained
             .setEstimatedHeapMemory(randomNonNegativeLong())
             .setEstimatedOperations(randomNonNegativeLong())
             .setLicenseLevel(randomFrom(License.OperationMode.PLATINUM.description(),
+                License.OperationMode.ENTERPRISE.description(),
                 License.OperationMode.GOLD.description(),
                 License.OperationMode.BASIC.description()))
             .setTags(tags);
@@ -311,28 +312,45 @@ public class TrainedModelConfigTests extends AbstractSerializingTestCase<Trained
         when(licenseState.isActive()).thenReturn(false);
         when(licenseState.getOperationMode()).thenReturn(License.OperationMode.BASIC);
 
+        assertFalse(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
 
+        when(licenseState.isActive()).thenReturn(true);
+        when(licenseState.getOperationMode()).thenReturn(License.OperationMode.ENTERPRISE);
+        assertTrue(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
+        assertTrue(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
+        assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
+        assertTrue(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));
+
+        when(licenseState.isActive()).thenReturn(false);
+        assertFalse(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
+        assertFalse(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
+        assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
+        assertFalse(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));
 
         when(licenseState.isActive()).thenReturn(true);
         when(licenseState.getOperationMode()).thenReturn(License.OperationMode.PLATINUM);
+        assertTrue(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));
 
         when(licenseState.isActive()).thenReturn(false);
+        assertFalse(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));
 
         when(licenseState.isActive()).thenReturn(true);
         when(licenseState.getOperationMode()).thenReturn(License.OperationMode.GOLD);
+        assertFalse(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));
 
         when(licenseState.isActive()).thenReturn(false);
+        assertFalse(builder.setLicenseLevel(License.OperationMode.ENTERPRISE.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.PLATINUM.description()).build().isAvailableWithLicense(licenseState));
         assertTrue(builder.setLicenseLevel(License.OperationMode.BASIC.description()).build().isAvailableWithLicense(licenseState));
         assertFalse(builder.setLicenseLevel(License.OperationMode.GOLD.description()).build().isAvailableWithLicense(licenseState));

+ 2 - 2
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java

@@ -23,7 +23,7 @@ public class TLSLicenseBootstrapCheckTests extends AbstractBootstrapCheckTestCas
     }
 
     public void testBootstrapCheckFailureOnPremiumLicense() throws Exception {
-        final OperationMode mode = randomFrom(OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
+        final OperationMode mode = randomFrom(OperationMode.ENTERPRISE, OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
         final Settings.Builder settings = Settings.builder();
         if (randomBoolean()) {
             // randomise between default-false & explicit-false
@@ -43,7 +43,7 @@ public class TLSLicenseBootstrapCheckTests extends AbstractBootstrapCheckTestCas
     }
 
     public void testBootstrapCheckSucceedsWithTlsEnabledOnPremiumLicense() throws Exception {
-        final OperationMode mode = randomFrom(OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
+        final OperationMode mode = randomFrom(OperationMode.ENTERPRISE, OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
         final Settings.Builder settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true);
         final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(mode, settings);
         assertSuccess(result);

+ 1 - 1
x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/action/TransportStartDatafeedAction.java

@@ -342,7 +342,7 @@ public class TransportStartDatafeedAction extends TransportMasterNodeAction<Star
                 RemoteClusterLicenseChecker.buildErrorMessage(
                         "ml",
                         licenseCheck.remoteClusterLicenseInfo(),
-                        RemoteClusterLicenseChecker::isLicensePlatinumOrTrial));
+                        RemoteClusterLicenseChecker::isAllowedByLicense));
         return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST);
     }
 

+ 1 - 1
x-pack/plugin/ml/src/test/java/org/elasticsearch/license/MachineLearningLicensingTests.java

@@ -689,7 +689,7 @@ public class MachineLearningLicensingTests extends BaseMlIntegTestCase {
     }
 
     private static OperationMode randomValidLicenseType() {
-        return randomFrom(License.OperationMode.TRIAL, License.OperationMode.PLATINUM);
+        return randomFrom(License.OperationMode.TRIAL, License.OperationMode.PLATINUM, OperationMode.ENTERPRISE);
     }
 
     private static OperationMode randomLicenseType() {

+ 1 - 0
x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java

@@ -131,6 +131,7 @@ public class ClusterStatsCollectorTests extends BaseCollectorTestCase {
                 case STANDARD:
                 case GOLD:
                 case PLATINUM:
+                case ENTERPRISE:
                     transportTLSEnabled = true;
                     break;
                 default:

+ 1 - 2
x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java

@@ -267,7 +267,6 @@ import java.util.stream.Collectors;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
-import static org.elasticsearch.license.XPackLicenseState.FIPS_ALLOWED_LICENSE_OPERATION_MODES;
 import static org.elasticsearch.xpack.core.XPackSettings.API_KEY_SERVICE_ENABLED_SETTING;
 import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
 import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
@@ -1045,7 +1044,7 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin,
             if (inFipsMode) {
                 License license = LicenseService.getLicense(state.metaData());
                 if (license != null &&
-                    FIPS_ALLOWED_LICENSE_OPERATION_MODES.contains(license.operationMode()) == false) {
+                    XPackLicenseState.isFipsAllowedForOperationMode(license.operationMode()) == false) {
                     throw new IllegalStateException("FIPS mode cannot be used with a [" + license.operationMode() +
                         "] license. It is only allowed with a Platinum or Trial license.");
 

+ 3 - 2
x-pack/plugin/security/src/test/java/org/elasticsearch/license/LicensingTests.java

@@ -180,7 +180,7 @@ public class LicensingTests extends SecurityIntegTestCase {
 
         // generate a new license with a mode that enables auth
         License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.TRIAL,
-                License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
+                License.OperationMode.PLATINUM, License.OperationMode.STANDARD, License.OperationMode.ENTERPRISE);
         enableLicensing(mode);
         e = expectThrows(ResponseException.class, () -> getRestClient().performRequest(new Request("GET", "/")));
         assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401));
@@ -204,7 +204,8 @@ public class LicensingTests extends SecurityIntegTestCase {
     }
 
     public void testNodeJoinWithoutSecurityExplicitlyEnabled() throws Exception {
-        License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.PLATINUM, License.OperationMode.STANDARD);
+        License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.PLATINUM,
+            License.OperationMode.ENTERPRISE, License.OperationMode.STANDARD);
         enableLicensing(mode);
 
         final List<String> seedHosts = internalCluster().masterClient().admin().cluster().nodesInfo(new NodesInfoRequest()).get()

+ 4 - 3
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java

@@ -65,7 +65,6 @@ import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
-import static org.elasticsearch.license.XPackLicenseState.FIPS_ALLOWED_LICENSE_OPERATION_MODES;
 import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
 import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT;
 import static org.hamcrest.Matchers.containsString;
@@ -245,7 +244,9 @@ public class SecurityTests extends ESTestCase {
             VersionUtils.randomVersionBetween(random(), null, Version.CURRENT));
         MetaData.Builder builder = MetaData.builder();
         License license =
-            TestUtils.generateSignedLicense(randomFrom(FIPS_ALLOWED_LICENSE_OPERATION_MODES).toString(), TimeValue.timeValueHours(24));
+            TestUtils.generateSignedLicense(
+                randomFrom(License.OperationMode.ENTERPRISE, License.OperationMode.PLATINUM, License.OperationMode.TRIAL).toString(),
+                TimeValue.timeValueHours(24));
         TestUtils.putLicense(builder, license);
         ClusterState state = ClusterState.builder(ClusterName.DEFAULT).metaData(builder.build()).build();
         new Security.ValidateLicenseForFIPS(false).accept(node, state);
@@ -260,7 +261,7 @@ public class SecurityTests extends ESTestCase {
         MetaData.Builder builder = MetaData.builder();
         final String forbiddenLicenseType =
             randomFrom(List.of(License.OperationMode.values()).stream()
-                .filter(l -> FIPS_ALLOWED_LICENSE_OPERATION_MODES.contains(l) == false).collect(Collectors.toList())).toString();
+                .filter(l -> XPackLicenseState.isFipsAllowedForOperationMode(l) == false).collect(Collectors.toList())).toString();
         License license = TestUtils.generateSignedLicense(forbiddenLicenseType, TimeValue.timeValueHours(24));
         TestUtils.putLicense(builder, license);
         ClusterState state = ClusterState.builder(ClusterName.DEFAULT).metaData(builder.build()).build();

+ 2 - 2
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java

@@ -758,7 +758,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
             Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache,
             mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
         // these licenses allow custom role providers
-        xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), true, null);
+        xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), true, null);
         roleNames = Sets.newHashSet("roleA");
         future = new PlainActionFuture<>();
         compositeRolesStore.roles(roleNames, future);
@@ -774,7 +774,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
             Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class),
             Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache,
             mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds));
-        xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.TRIAL), false, null);
+        xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), false, null);
         roleNames = Sets.newHashSet("roleA");
         future = new PlainActionFuture<>();
         compositeRolesStore.roles(roleNames, future);

+ 2 - 1
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java

@@ -23,7 +23,8 @@ import static org.hamcrest.Matchers.instanceOf;
 public class SamlBaseRestHandlerTests extends ESTestCase {
 
     public void testSamlAvailableOnTrialAndPlatinum() {
-        final SamlBaseRestHandler handler = buildHandler(randomFrom(License.OperationMode.TRIAL, License.OperationMode.PLATINUM));
+        final SamlBaseRestHandler handler = buildHandler(randomFrom(
+            License.OperationMode.TRIAL, License.OperationMode.PLATINUM, License.OperationMode.ENTERPRISE));
         assertThat(handler.checkFeatureAvailable(new FakeRestRequest()), Matchers.nullValue());
     }