diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/Security.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/Security.java index d70958c2994..0e367bbde25 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -337,7 +337,7 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin { components.add(authzService); components.add(new SecurityLifecycleService(settings, clusterService, threadPool, indexAuditTrail, - nativeUsersStore, nativeRolesStore, client)); + nativeUsersStore, nativeRolesStore, licenseState, client)); ipFilter.set(new IPFilter(settings, auditTrailService, clusterService.getClusterSettings(), licenseState)); components.add(ipFilter.get()); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java index d75243185c3..8309fcff46a 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.component.LifecycleListener; import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AbstractRunnable; +import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.authc.esnative.NativeRealmMigrator; @@ -40,7 +41,7 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust public SecurityLifecycleService(Settings settings, ClusterService clusterService, ThreadPool threadPool, @Nullable IndexAuditTrail indexAuditTrail, NativeUsersStore nativeUserStore, - NativeRolesStore nativeRolesStore, InternalClient client) { + NativeRolesStore nativeRolesStore, XPackLicenseState licenseState, InternalClient client) { super(settings); this.settings = settings; this.threadPool = threadPool; @@ -53,7 +54,8 @@ public class SecurityLifecycleService extends AbstractComponent implements Clust clusterService.addListener(this); clusterService.addListener(nativeUserStore); clusterService.addListener(nativeRolesStore); - clusterService.addListener(new SecurityTemplateService(settings, client, new NativeRealmMigrator(settings, nativeUserStore))); + final NativeRealmMigrator nativeRealmMigrator = new NativeRealmMigrator(settings, nativeUserStore, licenseState); + clusterService.addListener(new SecurityTemplateService(settings, client, nativeRealmMigrator)); clusterService.addLifecycleListener(new LifecycleListener() { @Override diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityTemplateService.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityTemplateService.java index 8e866e40846..3ab973f3ef6 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityTemplateService.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/SecurityTemplateService.java @@ -140,12 +140,13 @@ public class SecurityTemplateService extends AbstractComponent implements Cluste }); return true; } else { - andThen.run(); + if (upgradeDataState.get() == UpgradeState.COMPLETE) { + andThen.run(); + } return false; } } - private void updateSecurityMapping() { // only update the mapping if this is not already in progress if (updateMappingPending.compareAndSet(false, true) ) { diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java index 4b404e50e4a..0c7ee76e68e 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigrator.java @@ -12,6 +12,7 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.user.LogstashSystemUser; @@ -24,10 +25,12 @@ import org.elasticsearch.xpack.security.user.LogstashSystemUser; public class NativeRealmMigrator { private final NativeUsersStore nativeUsersStore; + private final XPackLicenseState licenseState; private final Logger logger; - public NativeRealmMigrator(Settings settings, NativeUsersStore nativeUsersStore) { + public NativeRealmMigrator(Settings settings, NativeUsersStore nativeUsersStore, XPackLicenseState licenseState) { this.nativeUsersStore = nativeUsersStore; + this.licenseState = licenseState; this.logger = Loggers.getLogger(getClass(), settings); } @@ -48,7 +51,10 @@ public class NativeRealmMigrator { if (shouldDisableLogstashUser(previousVersion)) { logger.info("Upgrading security from version [{}] - new reserved user [{}] will default to disabled", previousVersion, LogstashSystemUser.NAME); - nativeUsersStore.ensureReservedUserIsDisabled(LogstashSystemUser.NAME, new ActionListener() { + // Only clear the cache is authentication is allowed by the current license + // otherwise the license management checks will prevent it from completing successfully. + final boolean clearCache = licenseState.isAuthAllowed(); + nativeUsersStore.ensureReservedUserIsDisabled(LogstashSystemUser.NAME, clearCache, new ActionListener() { @Override public void onResponse(Void aVoid) { listener.onResponse(true); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java index af4b16d1dcd..5f6c00d853d 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java @@ -12,7 +12,6 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.DocWriteResponse; -import org.elasticsearch.action.DocWriteResponse.Result; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; @@ -396,7 +395,7 @@ public class NativeUsersStore extends AbstractComponent implements ClusterStateL } if (ReservedRealm.isReserved(username, settings)) { - setReservedUserEnabled(username, enabled, refreshPolicy, listener); + setReservedUserEnabled(username, enabled, refreshPolicy, true, listener); } else { setRegularUserEnabled(username, enabled, refreshPolicy, listener); } @@ -434,10 +433,10 @@ public class NativeUsersStore extends AbstractComponent implements ClusterStateL } } - void ensureReservedUserIsDisabled(final String username, final ActionListener listener) { + void ensureReservedUserIsDisabled(final String username, boolean clearCache, final ActionListener listener) { getReservedUserInfo(username, ActionListener.wrap(userInfo -> { if (userInfo == null || userInfo.enabled) { - setReservedUserEnabled(username, false, RefreshPolicy.IMMEDIATE, listener); + setReservedUserEnabled(username, false, RefreshPolicy.IMMEDIATE, clearCache, listener); } else { listener.onResponse(null); } @@ -445,7 +444,7 @@ public class NativeUsersStore extends AbstractComponent implements ClusterStateL } private void setReservedUserEnabled(final String username, final boolean enabled, final RefreshPolicy refreshPolicy, - final ActionListener listener) { + boolean clearCache, final ActionListener listener) { try { client.prepareUpdate(SecurityTemplateService.SECURITY_INDEX_NAME, RESERVED_USER_DOC_TYPE, username) .setDoc(Requests.INDEX_CONTENT_TYPE, User.Fields.ENABLED.getPreferredName(), enabled) @@ -456,7 +455,11 @@ public class NativeUsersStore extends AbstractComponent implements ClusterStateL .execute(new ActionListener() { @Override public void onResponse(UpdateResponse updateResponse) { - clearRealmCache(username, listener, null); + if (clearCache) { + clearRealmCache(username, listener, null); + } else { + listener.onResponse(null); + } } @Override diff --git a/elasticsearch/src/test/java/org/elasticsearch/license/LicensingTests.java b/elasticsearch/src/test/java/org/elasticsearch/license/LicensingTests.java index 064eccc7a05..2d1710ca0c6 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/license/LicensingTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/license/LicensingTests.java @@ -7,21 +7,43 @@ package org.elasticsearch.license; import org.apache.http.message.BasicHeader; import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.Version; +import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; import org.elasticsearch.action.admin.cluster.stats.ClusterStatsIndices; import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; +import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.client.Client; import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.transport.NoNodeAvailableException; import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.test.SecurityIntegTestCase; @@ -31,18 +53,27 @@ import org.elasticsearch.transport.Transport; import org.elasticsearch.xpack.TestXPackTransportClient; import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.security.Security; +import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.action.user.GetUsersResponse; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.client.SecurityClient; +import org.elasticsearch.xpack.template.TemplateUtils; import org.junit.Before; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; @@ -50,37 +81,37 @@ import static org.hamcrest.Matchers.notNullValue; public class LicensingTests extends SecurityIntegTestCase { public static final String ROLES = - SecuritySettingsSource.DEFAULT_ROLE + ":\n" + - " cluster: [ all ]\n" + - " indices:\n" + - " - names: '*'\n" + - " privileges: [manage]\n" + - " - names: '/.*/'\n" + - " privileges: [write]\n" + - " - names: 'test'\n" + - " privileges: [read]\n" + - " - names: 'test1'\n" + - " privileges: [read]\n" + - "\n" + - "role_a:\n" + - " indices:\n" + - " - names: 'a'\n" + - " privileges: [all]\n" + - "\n" + - "role_b:\n" + - " indices:\n" + - " - names: 'b'\n" + - " privileges: [all]\n"; + SecuritySettingsSource.DEFAULT_ROLE + ":\n" + + " cluster: [ all ]\n" + + " indices:\n" + + " - names: '*'\n" + + " privileges: [manage]\n" + + " - names: '/.*/'\n" + + " privileges: [write]\n" + + " - names: 'test'\n" + + " privileges: [read]\n" + + " - names: 'test1'\n" + + " privileges: [read]\n" + + "\n" + + "role_a:\n" + + " indices:\n" + + " - names: 'a'\n" + + " privileges: [all]\n" + + "\n" + + "role_b:\n" + + " indices:\n" + + " - names: 'b'\n" + + " privileges: [all]\n"; public static final String USERS = - SecuritySettingsSource.CONFIG_STANDARD_USER + - "user_a:{plain}passwd\n" + - "user_b:{plain}passwd\n"; + SecuritySettingsSource.CONFIG_STANDARD_USER + + "user_a:{plain}passwd\n" + + "user_b:{plain}passwd\n"; public static final String USERS_ROLES = - SecuritySettingsSource.CONFIG_STANDARD_USER_ROLES + - "role_a:user_a,user_b\n" + - "role_b:user_b\n"; + SecuritySettingsSource.CONFIG_STANDARD_USER_ROLES + + "role_a:user_a,user_b\n" + + "role_b:user_b\n"; @Override protected String configRoles() { @@ -100,8 +131,8 @@ public class LicensingTests extends SecurityIntegTestCase { @Override public Settings nodeSettings(int nodeOrdinal) { return Settings.builder().put(super.nodeSettings(nodeOrdinal)) - .put(NetworkModule.HTTP_ENABLED.getKey(), true) - .build(); + .put(NetworkModule.HTTP_ENABLED.getKey(), true) + .build(); } @Override @@ -118,16 +149,16 @@ public class LicensingTests extends SecurityIntegTestCase { public void testEnableDisableBehaviour() throws Exception { IndexResponse indexResponse = index("test", "type", jsonBuilder() - .startObject() - .field("name", "value") - .endObject()); + .startObject() + .field("name", "value") + .endObject()); assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult()); indexResponse = index("test1", "type", jsonBuilder() - .startObject() - .field("name", "value1") - .endObject()); + .startObject() + .field("name", "value1") + .endObject()); assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult()); refresh(); @@ -169,7 +200,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); enableLicensing(mode); e = expectThrows(ResponseException.class, () -> getRestClient().performRequest("GET", "/")); assertThat(e.getResponse().getStatusLine().getStatusCode(), is(401)); @@ -211,7 +242,7 @@ public class LicensingTests extends SecurityIntegTestCase { public void testTransportClientAuthenticationByLicenseType() throws Exception { Settings.Builder builder = Settings.builder() - .put(internalCluster().transportClient().settings()); + .put(internalCluster().transportClient().settings()); // remove user info builder.remove(Security.USER_SETTING.getKey()); builder.remove(ThreadContext.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER); @@ -224,7 +255,7 @@ public class LicensingTests extends SecurityIntegTestCase { // enable a license that enables security License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.TRIAL, - License.OperationMode.PLATINUM, License.OperationMode.STANDARD); + License.OperationMode.PLATINUM, License.OperationMode.STANDARD); enableLicensing(mode); try (TransportClient client = new TestXPackTransportClient(builder.build())) { @@ -236,6 +267,55 @@ public class LicensingTests extends SecurityIntegTestCase { } } + public void testNativeRealmMigratorWorksUnderBasicLicense() throws Exception { + final String securityIndex = ".security"; + final String reservedUserType = "reserved-user"; + final String oldVersionThatRequiresMigration = Version.V_5_0_2.toString(); + + final Client client = internalCluster().transportClient(); + final String template = TemplateUtils.loadTemplate("/" + SecurityTemplateService.SECURITY_TEMPLATE_NAME + ".json", + oldVersionThatRequiresMigration, Pattern.quote("${security.template.version}")); + + PutIndexTemplateRequest putTemplateRequest = client.admin().indices() + .preparePutTemplate(SecurityTemplateService.SECURITY_TEMPLATE_NAME) + .setSource(new BytesArray(template.getBytes(StandardCharsets.UTF_8)), XContentType.JSON) + .request(); + final PutIndexTemplateResponse putTemplateResponse = client.admin().indices().putTemplate(putTemplateRequest).actionGet(); + assertThat(putTemplateResponse.isAcknowledged(), equalTo(true)); + + final CreateIndexRequest createIndexRequest = client.admin().indices().prepareCreate(securityIndex).request(); + final CreateIndexResponse createIndexResponse = client.admin().indices().create(createIndexRequest).actionGet(); + assertThat(createIndexResponse.isAcknowledged(), equalTo(true)); + + final Map templateMap = XContentHelper.convertToMap(JsonXContent.jsonXContent, template, false); + final Map mappings = (Map) templateMap.get("mappings"); + final Map reservedUserMapping = (Map) mappings.get(reservedUserType); + + final PutMappingRequest putMappingRequest = client.admin().indices() + .preparePutMapping(securityIndex).setSource(reservedUserMapping).setType(reservedUserType).request(); + + final PutMappingResponse putMappingResponse = client.admin().indices().putMapping(putMappingRequest).actionGet(); + assertThat(putMappingResponse.isAcknowledged(), equalTo(true)); + + final GetMappingsRequest getMappingsRequest = client.admin().indices().prepareGetMappings(securityIndex).request(); + final boolean upgradeOk = awaitBusy(() -> { + final GetMappingsResponse getMappingsResponse = client.admin().indices().getMappings(getMappingsRequest).actionGet(); + final MappingMetaData metaData = getMappingsResponse.mappings().get(securityIndex).get(reservedUserType); + try { + Map meta = (Map) metaData.sourceAsMap().get("_meta"); + return meta != null && Version.CURRENT.toString().equals(meta.get("security-version")); + } catch (IOException e) { + return false; + } + }, 1, TimeUnit.SECONDS); + assertThat(upgradeOk, equalTo(true)); + + final GetRequest getRequest = client.prepareGet(securityIndex, reservedUserType, "logstash_system").setRefresh(true).request(); + final GetResponse getResponse = client.get(getRequest).actionGet(); + assertThat(getResponse.isExists(), equalTo(true)); + assertThat(getResponse.getFields(), equalTo(Collections.emptyMap())); + } + private static void assertElasticsearchSecurityException(ThrowingRunnable runnable) { ElasticsearchSecurityException ee = expectThrows(ElasticsearchSecurityException.class, runnable); assertThat(ee.getMetadata(LicenseUtils.EXPIRED_FEATURE_METADATA), hasItem(XPackPlugin.SECURITY)); diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/SecurityTemplateServiceTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/SecurityTemplateServiceTests.java index a6b0e67c374..b4a34dfc7ca 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/SecurityTemplateServiceTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/SecurityTemplateServiceTests.java @@ -217,8 +217,8 @@ public class SecurityTemplateServiceTests extends ESTestCase { assertThat(securityTemplateService.upgradeDataState.get(), equalTo(UpgradeState.NOT_STARTED)); - securityTemplateService.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build() - , EMPTY_CLUSTER_STATE)); + securityTemplateService.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), + EMPTY_CLUSTER_STATE)); assertThat(migratorVersionRef.get(), equalTo(expectedOldVersion)); assertThat(migratorListenerRef.get(), notNullValue()); @@ -241,7 +241,7 @@ public class SecurityTemplateServiceTests extends ESTestCase { assertTrue(securityTemplateService.updateMappingPending.get()); // if we now simulate an error... - listener.onFailure(new Exception()); + listener.onFailure(new Exception("Testing failure handling")); assertFalse(securityTemplateService.updateMappingPending.get()); // ... we should be able to send a new update diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java index 8de4c204a89..9255d1615c6 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmMigratorTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.security.user.LogstashSystemUser; import org.junit.Before; @@ -19,28 +20,38 @@ import org.mockito.Mockito; import static org.hamcrest.Matchers.is; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; public class NativeRealmMigratorTests extends ESTestCase { private Consumer> ensureDisabledHandler; private NativeUsersStore nativeUsersStore; private NativeRealmMigrator migrator; + private XPackLicenseState licenseState; @Before public void setupMocks() { + final boolean allowClearCache = randomBoolean(); + ensureDisabledHandler = listener -> listener.onResponse(null); nativeUsersStore = Mockito.mock(NativeUsersStore.class); Mockito.doAnswer(invocation -> { - ActionListener listener = (ActionListener) invocation.getArguments()[1]; + ActionListener listener = (ActionListener) invocation.getArguments()[2]; ensureDisabledHandler.accept(listener); return null; - }).when(nativeUsersStore).ensureReservedUserIsDisabled(any(), any()); + }).when(nativeUsersStore).ensureReservedUserIsDisabled(any(), eq(allowClearCache), any()); final Settings settings = Settings.EMPTY; - migrator = new NativeRealmMigrator(settings, nativeUsersStore); + + licenseState = mock(XPackLicenseState.class); + when(licenseState.isAuthAllowed()).thenReturn(allowClearCache); + + migrator = new NativeRealmMigrator(settings, nativeUsersStore, licenseState); } public void testNoChangeOnFreshInstall() throws Exception { @@ -71,7 +82,8 @@ public class NativeRealmMigratorTests extends ESTestCase { private void verifyUpgradeDisablesLogstashSystemUser(Version fromVersion) throws ExecutionException, InterruptedException { final PlainActionFuture future = doUpgrade(fromVersion); - verify(nativeUsersStore).ensureReservedUserIsDisabled(eq(LogstashSystemUser.NAME), any()); + final boolean clearCache = licenseState.isAuthAllowed(); + verify(nativeUsersStore).ensureReservedUserIsDisabled(eq(LogstashSystemUser.NAME), eq(clearCache), any()); verifyNoMoreInteractions(nativeUsersStore); assertThat(future.get(), is(Boolean.TRUE)); }