diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java index 7f8fd2ebfe52f..72f93814a94fa 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java @@ -19,7 +19,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -35,31 +34,6 @@ */ public class XPackLicenseState { - /** - * A licensed feature. - * - * Each value defines the licensed state necessary for the feature to be allowed. - */ - public enum Feature { - - OPERATOR_PRIVILEGES(OperationMode.ENTERPRISE, true); - - // NOTE: this is temporary. The Feature enum will go away in favor of LicensedFeature. - // Embedding the feature instance here is a stopgap to allow smaller initial PR, - // followed by PRs to convert the current consumers of the license state. - final LicensedFeature.Momentary feature; - - Feature(OperationMode minimumOperationMode, boolean needsActive) { - assert minimumOperationMode.compareTo(OperationMode.BASIC) > 0: minimumOperationMode.toString(); - String name = name().toLowerCase(Locale.ROOT); - if (needsActive) { - this.feature = LicensedFeature.momentary(name, name, minimumOperationMode); - } else { - this.feature = LicensedFeature.momentaryLenient(name, name, minimumOperationMode); - } - } - } - /** Messages for each feature which are printed when the license expires. */ static final Map EXPIRATION_MESSAGES; static { @@ -428,11 +402,6 @@ public String statusDescription() { return executeAgainstStatus(status -> (status.active ? "active" : "expired") + ' ' + status.mode.description() + " license"); } - @Deprecated - public boolean checkFeature(Feature feature) { - return feature.feature.check(this); - } - void featureUsed(LicensedFeature feature) { checkExpiry(); usage.put(new FeatureUsage(feature, null), epochMillisProvider.getAsLong()); @@ -460,16 +429,6 @@ void cleanupUsageTracking() { }); } - /** - * Checks whether the given feature is allowed by the current license. - *

- * This method should only be used when serializing whether a feature is allowed for telemetry. - */ - @Deprecated - public boolean isAllowed(Feature feature) { - return isAllowed(feature.feature); - } - // Package protected: Only allowed to be called by LicensedFeature boolean isAllowed(LicensedFeature feature) { return isAllowedByLicense(feature.getMinimumOperationMode(), feature.isNeedsActive()); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java index 88f4e8b921d32..f39a2e609926b 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java @@ -14,14 +14,14 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.time.DateMathParser; -import org.elasticsearch.xcontent.ToXContent; -import org.elasticsearch.xcontent.XContentBuilder; -import org.elasticsearch.xcontent.XContentFactory; -import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.core.TimeValue; import org.elasticsearch.license.licensor.LicenseSigner; import org.elasticsearch.protocol.xpack.license.LicensesStatus; import org.elasticsearch.protocol.xpack.license.PutLicenseResponse; +import org.elasticsearch.xcontent.ToXContent; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentFactory; +import org.elasticsearch.xcontent.XContentType; import org.hamcrest.MatcherAssert; import org.junit.Assert; @@ -40,15 +40,13 @@ import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean; import static com.carrotsearch.randomizedtesting.RandomizedTest.randomInt; import static org.apache.lucene.util.LuceneTestCase.createTempFile; -import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength; import static org.elasticsearch.test.ESTestCase.randomFrom; import static org.elasticsearch.test.ESTestCase.randomIntBetween; +import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class TestUtils { @@ -405,12 +403,6 @@ public static void putLicense(Metadata.Builder builder, License license) { } public static MockLicenseState newMockLicenceState() { - MockLicenseState mock = mock(MockLicenseState.class); - // These are deprecated methods, but we haven't replaced all usage of them yet - // By calling the real methods, we force everything through a small number of mockable methods like - // XPackLicenseState.isAllowed(LicensedFeature) - when(mock.isAllowed(any(XPackLicenseState.Feature.class))).thenCallRealMethod(); - when(mock.checkFeature(any(XPackLicenseState.Feature.class))).thenCallRealMethod(); - return mock; + return mock(MockLicenseState.class); } } diff --git a/x-pack/plugin/repository-encrypted/src/internalClusterTest/java/org/elasticsearch/repositories/encrypted/EncryptedRepositorySecretIntegTests.java b/x-pack/plugin/repository-encrypted/src/internalClusterTest/java/org/elasticsearch/repositories/encrypted/EncryptedRepositorySecretIntegTests.java index 9d92c6b3967c7..725a5240565ba 100644 --- a/x-pack/plugin/repository-encrypted/src/internalClusterTest/java/org/elasticsearch/repositories/encrypted/EncryptedRepositorySecretIntegTests.java +++ b/x-pack/plugin/repository-encrypted/src/internalClusterTest/java/org/elasticsearch/repositories/encrypted/EncryptedRepositorySecretIntegTests.java @@ -20,7 +20,7 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.license.License; import org.elasticsearch.license.LicenseService; -import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.license.MockLicenseState; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.repositories.RepositoriesService; import org.elasticsearch.repositories.RepositoryData; @@ -316,7 +316,7 @@ public void testLicenseComplianceSnapshotAndRestore() throws Exception { RepositoriesService.class ).repository(repositoryName); encryptedRepository.licenseStateSupplier = () -> { - XPackLicenseState mockLicenseState = mock(XPackLicenseState.class); + MockLicenseState mockLicenseState = mock(MockLicenseState.class); when(mockLicenseState.isAllowed(anyObject())).thenReturn(false); return mockLicenseState; }; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java index e7d0189d48a5c..9ef6eeceefd94 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -389,6 +389,9 @@ public class Security extends Plugin implements SystemIndexPlugin, IngestPlugin, public static final LicensedFeature.Persistent CUSTOM_ROLE_PROVIDERS_FEATURE = LicensedFeature.persistent(null, "security-roles-provider", License.OperationMode.PLATINUM); + public static final LicensedFeature.Momentary OPERATOR_PRIVILEGES_FEATURE = + LicensedFeature.momentary(null, "operator-privileges", License.OperationMode.ENTERPRISE); + private static final Logger logger = LogManager.getLogger(Security.class); public static final SystemIndexDescriptor SECURITY_MAIN_INDEX_DESCRIPTOR = getSecurityMainIndexDescriptor(); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/SecurityUsageTransportAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/SecurityUsageTransportAction.java index 0870bb8f662fb..94d6a3ec0b332 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/SecurityUsageTransportAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/SecurityUsageTransportAction.java @@ -80,7 +80,7 @@ protected void masterOperation(Task task, XPackUsageRequest request, ClusterStat Map anonymousUsage = singletonMap("enabled", AnonymousUser.isAnonymousEnabled(settings)); Map fips140Usage = fips140Usage(settings); Map operatorPrivilegesUsage = Map.of( - "available", licenseState.isAllowed(XPackLicenseState.Feature.OPERATOR_PRIVILEGES), + "available", Security.OPERATOR_PRIVILEGES_FEATURE.checkWithoutTracking(licenseState), "enabled", OperatorPrivileges.OPERATOR_PRIVILEGES_ENABLED.get(settings) ); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/OperatorPrivileges.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/OperatorPrivileges.java index 203e94b8d0f56..263c55a73ea96 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/OperatorPrivileges.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/operator/OperatorPrivileges.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.AuthenticationField; import org.elasticsearch.xpack.core.security.user.User; +import org.elasticsearch.xpack.security.Security; public class OperatorPrivileges { @@ -110,7 +111,7 @@ public void maybeInterceptRequest(ThreadContext threadContext, TransportRequest } private boolean shouldProcess() { - return licenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES); + return Security.OPERATOR_PRIVILEGES_FEATURE.check(licenseState); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityInfoTransportActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityInfoTransportActionTests.java index be6f93292c8dc..65f6841bf4d04 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityInfoTransportActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityInfoTransportActionTests.java @@ -12,12 +12,12 @@ import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.MockLicenseState; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.transport.TransportService; import org.elasticsearch.xcontent.ToXContent; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentFactory; -import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.core.XPackFeatureSet; import org.elasticsearch.xpack.core.XPackField; import org.elasticsearch.xpack.core.XPackSettings; @@ -51,7 +51,7 @@ public class SecurityInfoTransportActionTests extends ESTestCase { private Settings settings; - private XPackLicenseState licenseState; + private MockLicenseState licenseState; private Realms realms; private IPFilter ipFilter; private CompositeRolesStore rolesStore; @@ -61,7 +61,7 @@ public class SecurityInfoTransportActionTests extends ESTestCase { @Before public void init() throws Exception { settings = Settings.builder().put("path.home", createTempDir()).build(); - licenseState = mock(XPackLicenseState.class); + licenseState = mock(MockLicenseState.class); realms = mock(Realms.class); ipFilter = mock(IPFilter.class); rolesStore = mock(CompositeRolesStore.class); @@ -91,7 +91,7 @@ public void testUsage() throws Exception { final boolean explicitlyDisabled = randomBoolean(); final boolean enabled = explicitlyDisabled == false; final boolean operatorPrivilegesAvailable = randomBoolean(); - when(licenseState.isAllowed(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(operatorPrivilegesAvailable); + when(licenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(operatorPrivilegesAvailable); Settings.Builder settings = Settings.builder().put(this.settings); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/operator/OperatorPrivilegesTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/operator/OperatorPrivilegesTests.java index 32eafc7a52a83..3f15bd5ef180c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/operator/OperatorPrivilegesTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/operator/OperatorPrivilegesTests.java @@ -15,7 +15,7 @@ import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.license.MockLicenseState; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.MockLogAppender; import org.elasticsearch.transport.TransportRequest; @@ -26,6 +26,7 @@ import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; import org.elasticsearch.xpack.core.security.user.XPackUser; +import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.operator.OperatorPrivileges.DefaultOperatorPrivilegesService; import org.elasticsearch.xpack.security.operator.OperatorPrivileges.OperatorPrivilegesService; import org.junit.Before; @@ -44,14 +45,14 @@ public class OperatorPrivilegesTests extends ESTestCase { - private XPackLicenseState xPackLicenseState; + private MockLicenseState xPackLicenseState; private FileOperatorUsersStore fileOperatorUsersStore; private OperatorOnlyRegistry operatorOnlyRegistry; private OperatorPrivilegesService operatorPrivilegesService; @Before public void init() { - xPackLicenseState = mock(XPackLicenseState.class); + xPackLicenseState = mock(MockLicenseState.class); fileOperatorUsersStore = mock(FileOperatorUsersStore.class); operatorOnlyRegistry = mock(OperatorOnlyRegistry.class); operatorPrivilegesService = new DefaultOperatorPrivilegesService(xPackLicenseState, fileOperatorUsersStore, operatorOnlyRegistry); @@ -61,7 +62,7 @@ public void testWillNotProcessWhenFeatureIsDisabledOrLicenseDoesNotSupport() { final Settings settings = Settings.builder() .put("xpack.security.operator_privileges.enabled", randomBoolean()) .build(); - when(xPackLicenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(false); + when(xPackLicenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(false); final ThreadContext threadContext = new ThreadContext(settings); operatorPrivilegesService.maybeMarkOperatorUser(mock(Authentication.class), threadContext); @@ -77,7 +78,7 @@ public void testMarkOperatorUser() throws IllegalAccessException { final Settings settings = Settings.builder() .put("xpack.security.operator_privileges.enabled", true) .build(); - when(xPackLicenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(true); + when(xPackLicenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(true); final Authentication operatorAuth = mock(Authentication.class); final Authentication nonOperatorAuth = mock(Authentication.class); final User operatorUser = new User("operator_user"); @@ -142,7 +143,7 @@ public void testCheck() { final Settings settings = Settings.builder() .put("xpack.security.operator_privileges.enabled", true) .build(); - when(xPackLicenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(true); + when(xPackLicenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(true); final String operatorAction = "cluster:operator_only/action"; final String nonOperatorAction = "cluster:non_operator/action"; @@ -167,7 +168,7 @@ public void testCheck() { } public void testCheckWillPassForInternalUsers() { - when(xPackLicenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(true); + when(xPackLicenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(true); final Authentication internalAuth = mock(Authentication.class); when(internalAuth.getUser()).thenReturn( randomFrom(SystemUser.INSTANCE, XPackUser.INSTANCE, XPackSecurityUser.INSTANCE, AsyncSearchUser.INSTANCE)); @@ -178,7 +179,7 @@ public void testCheckWillPassForInternalUsers() { public void testMaybeInterceptRequest() throws IllegalAccessException { final boolean licensed = randomBoolean(); - when(xPackLicenseState.checkFeature(XPackLicenseState.Feature.OPERATOR_PRIVILEGES)).thenReturn(licensed); + when(xPackLicenseState.isAllowed(Security.OPERATOR_PRIVILEGES_FEATURE)).thenReturn(licensed); final Logger logger = LogManager.getLogger(OperatorPrivileges.class); final MockLogAppender appender = new MockLogAppender();