From 0e48f1d7a3f7ed24e24fba77c110c949c44ceb41 Mon Sep 17 00:00:00 2001 From: Jake Landis Date: Mon, 2 Oct 2023 15:17:23 -0500 Subject: [PATCH] adjust for split --- .../xpack/security/authc/ApiKeyService.java | 22 +-- .../security/authc/ExpiredTokenRemover.java | 5 +- .../xpack/security/authc/TokenService.java | 28 +-- .../authc/esnative/NativeUsersStore.java | 36 ++-- .../IndexServiceAccountTokenStore.java | 14 +- .../mapper/NativeRoleMappingStore.java | 29 ++-- .../authz/store/NativePrivilegeStore.java | 14 +- .../authz/store/NativeRolesStore.java | 22 +-- .../security/profile/ProfileService.java | 23 ++- .../support/SecurityIndexManager.java | 163 +++++++++--------- ...ansportOpenIdConnectLogoutActionTests.java | 5 +- ...sportSamlInvalidateSessionActionTests.java | 5 +- .../saml/TransportSamlLogoutActionTests.java | 5 +- .../TransportInvalidateTokenActionTests.java | 14 +- .../user/TransportGetUsersActionTests.java | 12 +- .../security/authc/ApiKeyServiceTests.java | 2 +- .../authc/AuthenticationServiceTests.java | 10 +- .../security/authc/TokenServiceTests.java | 16 +- .../authc/esnative/NativeUsersStoreTests.java | 5 +- .../authc/ldap/ActiveDirectoryRealmTests.java | 3 +- .../security/authc/ldap/LdapRealmTests.java | 3 +- .../IndexServiceAccountTokenStoreTests.java | 13 +- .../mapper/NativeRoleMappingStoreTests.java | 3 +- .../store/NativePrivilegeStoreTests.java | 5 +- .../security/profile/ProfileServiceTests.java | 4 +- .../support/SecurityIndexManagerTests.java | 40 ++--- .../xpack/security/test/SecurityMocks.java | 5 +- 27 files changed, 268 insertions(+), 238 deletions(-) diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java index f01db0609ead8..ce622ddf6fa69 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ApiKeyService.java @@ -149,6 +149,8 @@ import static org.elasticsearch.xpack.core.security.action.apikey.CrossClusterApiKeyRoleDescriptorBuilder.CCS_CLUSTER_PRIVILEGE_NAMES; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.WORKFLOWS_RESTRICTION_VERSION; import static org.elasticsearch.xpack.security.Security.SECURITY_CRYPTO_THREAD_POOL_NAME; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; public class ApiKeyService { @@ -1309,12 +1311,12 @@ public void crossClusterApiKeyUsageStats(ActionListener> lis listener.onResponse(Map.of()); return; } - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { logger.debug("security index does not exist"); listener.onResponse(Map.of("total", 0, "ccs", 0, "ccr", 0, "ccs_ccr", 0)); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() .filter(QueryBuilders.termQuery("doc_type", "api_key")) @@ -1638,11 +1640,11 @@ private void findApiKeysForUserRealmApiKeyIdAndNameCombination( Function hitParser, ActionListener> listener ) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(Collections.emptyList()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { final BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("doc_type", "api_key")); QueryBuilder realmsQuery = filterForRealmNames(realmNames); @@ -1879,7 +1881,7 @@ long lastTimeWhenApiKeysRemoverWasTriggered() { } private void maybeStartApiKeyRemover() { - if (securityIndex.isAvailableForSearch()) { + if (securityIndex.isAvailable(PRIMARY_SHARDS)) { if (client.threadPool().relativeTimeInMillis() - lastExpirationRunMs > deleteInterval.getMillis()) { inactiveApiKeysRemover.submit(client.threadPool()); lastExpirationRunMs = client.threadPool().relativeTimeInMillis(); @@ -1935,12 +1937,12 @@ public void getApiKeys( public void queryApiKeys(SearchRequest searchRequest, boolean withLimitedBy, ActionListener listener) { ensureEnabled(); - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { logger.debug("security index does not exist"); listener.onResponse(QueryApiKeyResponse.emptyResponse()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute( listener::onFailure, diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ExpiredTokenRemover.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ExpiredTokenRemover.java index a42ff69c0cd82..bec9e90c9f190 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ExpiredTokenRemover.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ExpiredTokenRemover.java @@ -34,6 +34,7 @@ import static org.elasticsearch.core.Strings.format; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; /** * Responsible for cleaning the invalidated and expired tokens from the security indices (`main` and `tokens`). @@ -68,10 +69,10 @@ final class ExpiredTokenRemover extends AbstractRunnable { @Override public void doRun() { final List indicesWithTokens = new ArrayList<>(); - if (securityTokensIndex.isAvailableForSearch()) { + if (securityTokensIndex.isAvailable(PRIMARY_SHARDS)) { indicesWithTokens.add(securityTokensIndex.aliasName()); } - if (securityMainIndex.isAvailableForSearch() && checkMainIndexForExpiredTokens) { + if (securityMainIndex.isAvailable(PRIMARY_SHARDS) && checkMainIndexForExpiredTokens) { indicesWithTokens.add(securityMainIndex.aliasName()); } if (indicesWithTokens.isEmpty()) { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java index 238084bb88406..0b05715940e6c 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java @@ -147,6 +147,8 @@ import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; /** * Service responsible for the creation, validation, and other management of {@link UserToken} @@ -552,10 +554,10 @@ private void getTokenDocById( ActionListener listener ) { final SecurityIndexManager tokensIndex = getTokensIndexForVersion(tokenVersion); - final SecurityIndexManager frozenTokensIndex = tokensIndex.freeze(); - if (frozenTokensIndex.isAvailableForSearch() == false) { + final SecurityIndexManager frozenTokensIndex = tokensIndex.defensiveCopy(); + if (frozenTokensIndex.isAvailable(PRIMARY_SHARDS) == false) { logger.warn("failed to get access token [{}] because index [{}] is not available", tokenId, tokensIndex.aliasName()); - listener.onFailure(frozenTokensIndex.getUnavailableReason()); + listener.onFailure(frozenTokensIndex.getUnavailableReason(PRIMARY_SHARDS)); return; } final GetRequest getRequest = client.prepareGet(tokensIndex.aliasName(), getTokenDocumentId(tokenId)).request(); @@ -1168,13 +1170,13 @@ private void findTokenFromRefreshToken( onFailure.accept(ex); } }; - final SecurityIndexManager frozenTokensIndex = tokensIndexManager.freeze(); + final SecurityIndexManager frozenTokensIndex = tokensIndexManager.defensiveCopy(); if (frozenTokensIndex.indexExists() == false) { logger.warn("index [{}] does not exist so we can't find token from refresh token", frozenTokensIndex.aliasName()); - listener.onFailure(frozenTokensIndex.getUnavailableReason()); - } else if (frozenTokensIndex.isAvailableForSearch() == false) { + listener.onFailure(new IndexNotFoundException(frozenTokensIndex.aliasName())); + } else if (frozenTokensIndex.isAvailable(SEARCH_SHARDS) == false) { logger.debug("index [{}] is not available to find token from refresh token, retrying", frozenTokensIndex.aliasName()); - maybeRetryOnFailure.accept(frozenTokensIndex.getUnavailableReason()); + maybeRetryOnFailure.accept(frozenTokensIndex.getUnavailableReason(SEARCH_SHARDS)); } else { final SearchRequest request = client.prepareSearch(tokensIndexManager.aliasName()) .setQuery( @@ -1786,11 +1788,11 @@ private void searchActiveTokens( */ private void sourceIndicesWithTokensAndRun(ActionListener> listener) { final List indicesWithTokens = new ArrayList<>(2); - final SecurityIndexManager frozenTokensIndex = securityTokensIndex.freeze(); + final SecurityIndexManager frozenTokensIndex = securityTokensIndex.defensiveCopy(); if (frozenTokensIndex.indexExists()) { // an existing tokens index always contains tokens (if available and version allows) - if (false == frozenTokensIndex.isAvailableForSearch()) { - listener.onFailure(frozenTokensIndex.getUnavailableReason()); + if (false == frozenTokensIndex.isAvailable(PRIMARY_SHARDS)) { + listener.onFailure(frozenTokensIndex.getUnavailableReason(PRIMARY_SHARDS)); return; } if (false == frozenTokensIndex.isIndexUpToDate()) { @@ -1806,14 +1808,14 @@ private void sourceIndicesWithTokensAndRun(ActionListener> listener } indicesWithTokens.add(frozenTokensIndex.aliasName()); } - final SecurityIndexManager frozenMainIndex = securityMainIndex.freeze(); + final SecurityIndexManager frozenMainIndex = securityMainIndex.defensiveCopy(); if (frozenMainIndex.indexExists()) { // main security index _might_ contain tokens if the tokens index has been created recently if (false == frozenTokensIndex.indexExists() || frozenTokensIndex.getCreationTime() .isAfter(clock.instant().minus(ExpiredTokenRemover.MAXIMUM_TOKEN_LIFETIME_HOURS, ChronoUnit.HOURS))) { - if (false == frozenMainIndex.isAvailableForSearch()) { - listener.onFailure(frozenMainIndex.getUnavailableReason()); + if (false == frozenMainIndex.isAvailable(PRIMARY_SHARDS)) { + listener.onFailure(frozenMainIndex.getUnavailableReason(PRIMARY_SHARDS)); return; } if (false == frozenMainIndex.isIndexUpToDate()) { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java index 6648b2ac1d648..fd94a45b6fd16 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStore.java @@ -65,6 +65,8 @@ import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; /** @@ -119,11 +121,11 @@ public void getUsers(String[] userNames, final ActionListener> listener.onFailure(t); }; - final SecurityIndexManager frozenSecurityIndex = this.securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = this.securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(Collections.emptyList()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else if (userNames.length == 1) { // optimization for single user lookup final String username = userNames[0]; getUserAndPassword( @@ -161,11 +163,11 @@ public void getUsers(String[] userNames, final ActionListener> } void getUserCount(final ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = this.securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = this.securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(0L); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute( listener::onFailure, @@ -188,8 +190,8 @@ void getUserCount(final ActionListener listener) { * Async method to retrieve a user and their password */ private void getUserAndPassword(final String user, final ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); - if (frozenSecurityIndex.isAvailableForSearch() == false) { + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); + if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { if (frozenSecurityIndex.indexExists() == false) { logger.trace("could not retrieve user [{}] because security index does not exist", user); } else { @@ -538,11 +540,11 @@ private void setReservedUserEnabled( } public void deleteUser(final DeleteUserRequest deleteUserRequest, final ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(false); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { DeleteRequest request = client.prepareDelete(SECURITY_MAIN_ALIAS, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username())) @@ -596,11 +598,11 @@ void verifyPassword(String username, final SecureString password, ActionListener } void getReservedUserInfo(String username, ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(null); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute( listener::onFailure, @@ -649,11 +651,11 @@ public void onFailure(Exception e) { } void getAllReservedUserInfo(ActionListener> listener) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(Collections.emptyMap()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute( listener::onFailure, diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStore.java index 8acc2ced825a2..a16eeb7cf4e0f 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStore.java @@ -65,6 +65,8 @@ import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; public class IndexServiceAccountTokenStore extends CachingServiceAccountTokenStore { @@ -168,11 +170,11 @@ void createToken( } void findTokensFor(ServiceAccountId accountId, ActionListener> listener) { - final SecurityIndexManager frozenSecurityIndex = this.securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = this.securityIndex.defensiveCopy(); if (false == frozenSecurityIndex.indexExists()) { listener.onResponse(List.of()); - } else if (false == frozenSecurityIndex.isAvailableForSearch()) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (false == frozenSecurityIndex.isAvailable(SEARCH_SHARDS)) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { final Supplier contextSupplier = client.threadPool() @@ -204,11 +206,11 @@ void findTokensFor(ServiceAccountId accountId, ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = this.securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = this.securityIndex.defensiveCopy(); if (false == frozenSecurityIndex.indexExists()) { listener.onResponse(false); - } else if (false == frozenSecurityIndex.isAvailableForSearch()) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (false == frozenSecurityIndex.isAvailable(PRIMARY_SHARDS)) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { final ServiceAccountId accountId = new ServiceAccountId(request.getNamespace(), request.getServiceName()); if (false == ServiceAccountService.isServiceAccountPrincipal(accountId.asPrincipal())) { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java index 4acd11ac4c661..91e8d459a2dc7 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStore.java @@ -62,6 +62,8 @@ import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; @@ -245,11 +247,11 @@ public void onFailure(Exception e) { } private void innerDeleteMapping(DeleteRoleMappingRequest request, ActionListener listener) { - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(false); - } else if (securityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (securityIndex.isAvailable(PRIMARY_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin( @@ -293,18 +295,15 @@ public void getRoleMappings(Set names, ActionListener> listener) { - if (securityIndex.isAvailableForSearch()) { - loadMappings(listener); - } else { - if (logger.isDebugEnabled()) { - logger.debug( - "The security index is not yet available - no role mappings can be loaded. index [{}] [exists: {}] [available: {}]", - SECURITY_MAIN_ALIAS, - securityIndex.indexExists(), - securityIndex.isAvailableForSearch() - ); - } + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); + if (frozenSecurityIndex.indexExists() == false) { + logger.debug("The security index exists - no role mappings can be loaded"); listener.onResponse(Collections.emptyList()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + logger.debug("The security index exists but is not available - no role mappings can be loaded"); + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); + } else { + loadMappings(listener); } } @@ -318,7 +317,7 @@ private void getMappings(ActionListener> listener) { * */ public void usageStats(ActionListener> listener) { - if (securityIndex.isAvailableForSearch() == false) { + if (securityIndex.isAvailable(SEARCH_SHARDS) == false) { reportStats(listener, Collections.emptyList()); } else { getMappings(ActionListener.wrap(mappings -> reportStats(listener, mappings), listener::onFailure)); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStore.java index 060535d97fc9b..02226cd3f1880 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStore.java @@ -75,6 +75,8 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.Fields.APPLICATION; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; /** @@ -190,11 +192,11 @@ public void getPrivileges( private void innerGetPrivileges(Collection applications, ActionListener> listener) { assert applications != null && applications.size() > 0 : "Application names are required (found " + applications + ")"; - final SecurityIndexManager frozenSecurityIndex = securityIndexManager.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndexManager.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(Collections.emptyList()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(SEARCH_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(SEARCH_SHARDS)); } else { securityIndexManager.checkIndexVersionThenExecute(listener::onFailure, () -> { @@ -420,11 +422,11 @@ public void deletePrivileges( WriteRequest.RefreshPolicy refreshPolicy, ActionListener>> listener ) { - final SecurityIndexManager frozenSecurityIndex = securityIndexManager.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndexManager.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(Collections.emptyMap()); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { securityIndexManager.checkIndexVersionThenExecute(listener::onFailure, () -> { ActionListener groupListener = new GroupedActionListener<>(names.size(), ActionListener.wrap(responses -> { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStore.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStore.java index 578f4cea8e46c..26e6b639950ca 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStore.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStore.java @@ -70,6 +70,8 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.security.SecurityField.DOCUMENT_LEVEL_SECURITY_FEATURE; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ROLE_TYPE; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_MAIN_ALIAS; /** @@ -134,12 +136,12 @@ public void getRoleDescriptors(Set names, final ActionListener { QueryBuilder query = QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE); @@ -209,11 +211,11 @@ public void deleteRole(final DeleteRoleRequest deleteRoleRequest, final ActionLi return; } - final SecurityIndexManager frozenSecurityIndex = securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { listener.onResponse(false); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - listener.onFailure(frozenSecurityIndex.getUnavailableReason()); + } else if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { + listener.onFailure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS)); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { DeleteRequest request = client.prepareDelete(SECURITY_MAIN_ALIAS, getIdForRole(deleteRoleRequest.name())).request(); @@ -310,7 +312,7 @@ public void onFailure(Exception e) { public void usageStats(ActionListener> listener) { Map usageStats = Maps.newMapWithExpectedSize(3); - if (securityIndex.isAvailableForSearch() == false) { + if (securityIndex.isAvailable(SEARCH_SHARDS) == false) { usageStats.put("size", 0L); usageStats.put("fls", false); usageStats.put("dls", false); @@ -407,12 +409,12 @@ public String toString() { } private void getRoleDescriptor(final String roleId, ActionListener resultListener) { - final SecurityIndexManager frozenSecurityIndex = this.securityIndex.freeze(); + final SecurityIndexManager frozenSecurityIndex = this.securityIndex.defensiveCopy(); if (frozenSecurityIndex.indexExists() == false) { // TODO remove this short circuiting and fix tests that fail without this! resultListener.onResponse(RoleRetrievalResult.success(Collections.emptySet())); - } else if (frozenSecurityIndex.isAvailableForSearch() == false) { - resultListener.onResponse(RoleRetrievalResult.failure(frozenSecurityIndex.getUnavailableReason())); + } else if (frozenSecurityIndex.isAvailable(PRIMARY_SHARDS) == false) { + resultListener.onResponse(RoleRetrievalResult.failure(frozenSecurityIndex.getUnavailableReason(PRIMARY_SHARDS))); } else { securityIndex.checkIndexVersionThenExecute( e -> resultListener.onResponse(RoleRetrievalResult.failure(e)), diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java index bc55a0e022ff7..054583d94cbb1 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/profile/ProfileService.java @@ -99,6 +99,8 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_PROFILE_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.security.authc.Authentication.isFileOrNativeRealm; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.PRIMARY_SHARDS; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.Availability.SEARCH_SHARDS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.SECURITY_PROFILE_ALIAS; import static org.elasticsearch.xpack.security.support.SecuritySystemIndices.VERSION_SECURITY_PROFILE_ORIGIN; @@ -261,7 +263,7 @@ public void suggestProfile(SuggestProfilesRequest request, TaskId parentTaskId, 0, new TotalHits(0, TotalHits.Relation.EQUAL_TO) ); - })).ifPresent(frozenProfileIndex -> { + }), SEARCH_SHARDS).ifPresent(frozenProfileIndex -> { final SearchRequest searchRequest = buildSearchRequestForSuggest(request, parentTaskId); frozenProfileIndex.checkIndexVersionThenExecute( @@ -334,7 +336,7 @@ public void usageStats(ActionListener> listener) { tryFreezeAndCheckIndex(listener.map(response -> { // index does not exist assert response == null : "only null response can reach here"; return Map.of("total", 0L, "enabled", 0L, "recent", 0L); - })).ifPresent(frozenProfileIndex -> { + }), SEARCH_SHARDS).ifPresent(frozenProfileIndex -> { final MultiSearchRequest multiSearchRequest = client.prepareMultiSearch() .add( client.prepareSearch(SECURITY_PROFILE_ALIAS) @@ -445,7 +447,7 @@ SearchRequest buildSearchRequestForSuggest(SuggestProfilesRequest request, TaskI } private void getVersionedDocument(String uid, ActionListener listener) { - tryFreezeAndCheckIndex(listener).ifPresent(frozenProfileIndex -> { + tryFreezeAndCheckIndex(listener, PRIMARY_SHARDS).ifPresent(frozenProfileIndex -> { final GetRequest getRequest = new GetRequest(SECURITY_PROFILE_ALIAS, uidToDocId(uid)); frozenProfileIndex.checkIndexVersionThenExecute( listener::onFailure, @@ -472,7 +474,7 @@ private void getVersionedDocuments(Collection uids, ActionListener { + tryFreezeAndCheckIndex(listener, PRIMARY_SHARDS).ifPresent(frozenProfileIndex -> { frozenProfileIndex.checkIndexVersionThenExecute( listener::onFailure, () -> new OriginSettingClient(client, getActionOrigin()).prepareMultiGet() @@ -544,7 +546,7 @@ private void searchVersionedDocumentsForSubjects( listener.onResponse(new SubjectSearchResultsAndErrors<>(List.of(), Map.of())); return; } - tryFreezeAndCheckIndex(listener).ifPresent(frozenProfileIndex -> { + tryFreezeAndCheckIndex(listener, SEARCH_SHARDS).ifPresent(frozenProfileIndex -> { frozenProfileIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { final MultiSearchRequest multiSearchRequest = new MultiSearchRequest(); subjects.forEach(subject -> multiSearchRequest.add(buildSearchRequestForSubject(subject))); @@ -1006,14 +1008,17 @@ private static XContentBuilder wrapProfileDocumentWithoutApplicationData(Profile * Freeze the profile index check its availability and return it if everything is ok. * Otherwise it calls the listener with null and returns an empty Optional. */ - private Optional tryFreezeAndCheckIndex(ActionListener listener) { - final SecurityIndexManager frozenProfileIndex = profileIndex.freeze(); + private Optional tryFreezeAndCheckIndex( + ActionListener listener, + SecurityIndexManager.Availability availability + ) { + final SecurityIndexManager frozenProfileIndex = profileIndex.defensiveCopy(); if (false == frozenProfileIndex.indexExists()) { logger.debug("profile index does not exist"); listener.onResponse(null); return Optional.empty(); - } else if (false == frozenProfileIndex.isAvailableForSearch()) { - listener.onFailure(frozenProfileIndex.getUnavailableReason()); + } else if (false == frozenProfileIndex.isAvailable(availability)) { + listener.onFailure(frozenProfileIndex.getUnavailableReason(availability)); return Optional.empty(); } return Optional.of(frozenProfileIndex); diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java index 0bdf9cffb69ac..adf9be0d58b84 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/support/SecurityIndexManager.java @@ -34,6 +34,7 @@ import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.core.Tuple; import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; @@ -67,31 +68,45 @@ public class SecurityIndexManager implements ClusterStateListener { private static final Logger logger = LogManager.getLogger(SecurityIndexManager.class); + /** + * When checking availability, check for availability of search or availability of all primaries + **/ + public enum Availability { + SEARCH_SHARDS, + PRIMARY_SHARDS + } + private final Client client; private final SystemIndexDescriptor systemIndexDescriptor; private final List> stateChangeListeners = new CopyOnWriteArrayList<>(); private volatile State state; + private final boolean defensiveCopy; public static SecurityIndexManager buildSecurityIndexManager( Client client, ClusterService clusterService, SystemIndexDescriptor descriptor ) { - final SecurityIndexManager securityIndexManager = new SecurityIndexManager(client, descriptor, State.UNRECOVERED_STATE); + final SecurityIndexManager securityIndexManager = new SecurityIndexManager(client, descriptor, State.UNRECOVERED_STATE, false); clusterService.addListener(securityIndexManager); return securityIndexManager; } - private SecurityIndexManager(Client client, SystemIndexDescriptor descriptor, State state) { + private SecurityIndexManager(Client client, SystemIndexDescriptor descriptor, State state, boolean defensiveCopy) { this.client = client; this.state = state; this.systemIndexDescriptor = descriptor; + this.defensiveCopy = defensiveCopy; } - public SecurityIndexManager freeze() { - return new SecurityIndexManager(null, systemIndexDescriptor, state); + /** + * Creates a defensive to protect against the underlying state changes. Should be called prior to making decisions and that same copy + * should be reused for multiple checks in the same workflow. + */ + public SecurityIndexManager defensiveCopy() { + return new SecurityIndexManager(null, systemIndexDescriptor, state, true); } public String aliasName() { @@ -115,26 +130,26 @@ public boolean isIndexUpToDate() { } /** - * @return true if all searchable shards for the security index are available - */ - public boolean isAvailableForSearch() { - return this.state.indexAvailableForSearch; - } - - /** - * @return true if all primary shards for the security index are available - */ - public boolean isAvailableForWrite() { - return this.state.indexAvailableForWrite; - } - - /** - * @return true if all primary shards OR all searchable shards for the security index are available. Since real time - * get can read from either the write shards (via translog) or from the search shards we check if either available. If neither are - * available the real time get is guaranteed to fail. If one of the two are unavailable the real time get may or may not fail. + * Optimization to avoid making unnecessary calls when we know the underlying shard state. This call will check that the index exists, + * is discoverable from the alias, is not closed, and determine the type of {@link Availability}. + * @param availability Check availability for search or write/update/real time get workflows. Write/update/realtime get workflows + * should check for availability of primary shards. Search workflows should check availability of search shards + * (which may or may not also be the primary shards). + * @return + * when checking for search: true if all searchable shards for the security index are available + * when checking for all primary: true if all primary shards for the security index are available */ - public boolean isAvailableForRealTimeGet() { - return this.state.indexAvailableForWrite || this.state.indexAvailableForSearch; + public boolean isAvailable(Availability availability) { + switch (availability) { + case SEARCH_SHARDS -> { + return this.state.indexAvailableForSearch; + } + case PRIMARY_SHARDS -> { + return this.state.indexAvailableForWrite; + } + } + // can never happen + throw new IllegalStateException("Unexpected availability enumeration. This is bug, please contact support."); } public boolean isMappingUpToDate() { @@ -145,27 +160,30 @@ public boolean isStateRecovered() { return this.state != State.UNRECOVERED_STATE; } - public ElasticsearchException getUnavailableReason() { - final State state = this.state; // use a local copy so all checks execute against the same state! - if (state.indexAvailableForSearch) { - throw new IllegalStateException("caller must make sure to use a frozen state and check indexAvailable"); + public ElasticsearchException getUnavailableReason(Availability availability) { + // ensure usage of a local copy so all checks execute against the same state! + if (defensiveCopy == false) { + throw new IllegalStateException("caller must make sure to use a defensive copy"); } - + final State state = this.state; if (state.indexState == IndexMetadata.State.CLOSE) { return new IndexClosedException(new Index(state.concreteIndexName, ClusterState.UNKNOWN_UUID)); } else if (state.indexExists()) { - return new UnavailableShardsException( - null, - "index [" - + state.concreteIndexName - + "] exists but at least one shard is unavailable. " - + "Is available for search [" - + state.indexAvailableForSearch - + "]" - + "Is available for write [" - + state.indexAvailableForWrite - + "]" - ); + assert state.indexAvailableForSearch == false || state.indexAvailableForWrite == false; + if (Availability.PRIMARY_SHARDS.equals(availability) && state.indexAvailableForWrite == false) { + return new UnavailableShardsException( + null, + "at least one primary shard for the index [" + state.concreteIndexName + "] is unavailable" + ); + } else if (Availability.SEARCH_SHARDS.equals(availability) && state.indexAvailableForSearch == false) { + return new UnavailableShardsException( + null, + "at least one search shard for the index [" + state.concreteIndexName + "] is unavailable" + ); + } else { + // should never happen + throw new IllegalStateException("caller must ensure original availability matches the current availability"); + } } else { return new IndexNotFoundException(state.concreteIndexName); } @@ -201,8 +219,9 @@ public void clusterChanged(ClusterChangedEvent event) { final Instant creationTime = indexMetadata != null ? Instant.ofEpochMilli(indexMetadata.getCreationDate()) : null; final boolean isIndexUpToDate = indexMetadata == null || INDEX_FORMAT_SETTING.get(indexMetadata.getSettings()) == systemIndexDescriptor.getIndexFormat(); - final boolean indexAvailableForSearch = checkIndexAvailableForSearch(event.state()); - final boolean indexAvailableForWrite = checkIndexAvailableForWrite(event.state()); + Tuple available = checkIndexAvailable(event.state()); + final boolean indexAvailableForWrite = available.v1(); + final boolean indexAvailableForSearch = available.v2(); final boolean mappingIsUpToDate = indexMetadata == null || checkIndexMappingUpToDate(event.state()); final Version mappingVersion = oldestIndexMappingVersion(event.state()); final String concreteIndexName = indexMetadata == null @@ -259,53 +278,35 @@ public void onStateRecovered(Consumer recoveredStateConsumer) { stateChangeListeners.add(stateChangeListener); } - /** - * @return true if all shards that needed to service a search request are available - */ - private boolean checkIndexAvailableForSearch(ClusterState state) { + private Tuple checkIndexAvailable(ClusterState state) { final String aliasName = systemIndexDescriptor.getAliasName(); - IndexMetadata metadata = getOpenIndexMetadata(aliasName, state); - if (metadata == null) { - return false; - } - final IndexRoutingTable routingTable = state.routingTable().index(metadata.getIndex()); - if (routingTable == null || routingTable.readyForSearch(state) == false) { - logger.debug("Index [{}] is not yet active", aliasName); - return false; - } else { - return true; - } - } - - /** - * @return true if all primary shards are available. - */ - private boolean checkIndexAvailableForWrite(ClusterState state) { - final String aliasName = systemIndexDescriptor.getAliasName(); - IndexMetadata metadata = getOpenIndexMetadata(aliasName, state); - if (metadata == null) { - return false; - } - final IndexRoutingTable routingTable = state.routingTable().index(metadata.getIndex()); - if (routingTable == null || routingTable.allPrimaryShardsActive() == false) { - logger.debug("Index [{}] is not yet active", aliasName); - return false; - } else { - return true; - } - } - - private IndexMetadata getOpenIndexMetadata(String aliasName, ClusterState state) { IndexMetadata metadata = resolveConcreteIndex(aliasName, state.metadata()); if (metadata == null) { logger.debug("Index [{}] is not available - no metadata", aliasName); - return null; + return new Tuple<>(false, false); } if (metadata.getState() == IndexMetadata.State.CLOSE) { logger.warn("Index [{}] is closed", aliasName); - return null; + return new Tuple<>(false, false); + } + boolean allPrimaryShards = false; + boolean searchShards = false; + final IndexRoutingTable routingTable = state.routingTable().index(metadata.getIndex()); + if (routingTable != null && routingTable.allPrimaryShardsActive()) { + allPrimaryShards = true; + } + if (routingTable != null && routingTable.readyForSearch(state)) { + searchShards = true; + } + if (allPrimaryShards == false || searchShards == false) { + logger.debug( + "Index [{}] is not fully available." + "all primary shards available [{}], search shards available, [{}]", + aliasName, + allPrimaryShards, + searchShards + ); } - return metadata; + return new Tuple<>(allPrimaryShards, searchShards); } private boolean checkIndexMappingUpToDate(ClusterState clusterState) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/oidc/TransportOpenIdConnectLogoutActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/oidc/TransportOpenIdConnectLogoutActionTests.java index 704684bc87a12..2a6fad9c81f53 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/oidc/TransportOpenIdConnectLogoutActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/oidc/TransportOpenIdConnectLogoutActionTests.java @@ -173,8 +173,9 @@ public void setup() throws Exception { ((Runnable) inv.getArguments()[1]).run(); return null; }).when(securityIndex).checkIndexVersionThenExecute(anyConsumer(), any(Runnable.class)); - when(securityIndex.isAvailableForSearch()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlInvalidateSessionActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlInvalidateSessionActionTests.java index ec7f2f5c0bcb1..a748de0c89413 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlInvalidateSessionActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlInvalidateSessionActionTests.java @@ -263,12 +263,13 @@ protected void ((Runnable) inv.getArguments()[1]).run(); return null; }).when(securityIndex).checkIndexVersionThenExecute(anyConsumer(), any(Runnable.class)); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true); when(securityIndex.isIndexUpToDate()).thenReturn(true); when(securityIndex.getCreationTime()).thenReturn(Clock.systemUTC().instant()); when(securityIndex.aliasName()).thenReturn(".security"); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); final MockLicenseState licenseState = mock(MockLicenseState.class); when(licenseState.isAllowed(Security.TOKEN_SERVICE_FEATURE)).thenReturn(true); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlLogoutActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlLogoutActionTests.java index de70205a59528..e3631a785b9f3 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlLogoutActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/saml/TransportSamlLogoutActionTests.java @@ -204,8 +204,9 @@ public void setup() throws Exception { ((Runnable) inv.getArguments()[1]).run(); return null; }).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class)); - when(securityIndex.isAvailableForSearch()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); final MockLicenseState licenseState = mock(MockLicenseState.class); when(licenseState.isAllowed(Security.TOKEN_SERVICE_FEATURE)).thenReturn(true); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/token/TransportInvalidateTokenActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/token/TransportInvalidateTokenActionTests.java index b76c4f2be0c78..6b9594c1c68ea 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/token/TransportInvalidateTokenActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/token/TransportInvalidateTokenActionTests.java @@ -78,10 +78,12 @@ public void setup() { } public void testInvalidateTokensWhenIndexUnavailable() throws Exception { - when(securityIndex.isAvailableForSearch()).thenReturn(false); + + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(false); when(securityIndex.indexExists()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); - when(securityIndex.getUnavailableReason()).thenReturn(new ElasticsearchException("simulated")); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); + when(securityIndex.getUnavailableReason(SecurityIndexManager.Availability.PRIMARY_SHARDS)) + .thenReturn(new ElasticsearchException("simulated")); final TokenService tokenService = new TokenService( SETTINGS, Clock.systemUTC(), @@ -122,10 +124,10 @@ public void testInvalidateTokensWhenIndexUnavailable() throws Exception { } public void testInvalidateTokensWhenIndexClosed() throws Exception { - when(securityIndex.isAvailableForSearch()).thenReturn(false); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(false); when(securityIndex.indexExists()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); - when(securityIndex.getUnavailableReason()).thenReturn( + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); + when(securityIndex.getUnavailableReason(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn( new IndexClosedException(new Index(INTERNAL_SECURITY_TOKENS_INDEX_7, ClusterState.UNKNOWN_UUID)) ); final TokenService tokenService = new TokenService( diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportGetUsersActionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportGetUsersActionTests.java index 56b8fdcd5c49e..b6a1523b09784 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportGetUsersActionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/action/user/TransportGetUsersActionTests.java @@ -110,7 +110,8 @@ public void terminateThreadPool() throws InterruptedException { public void testAnonymousUser() { NativeUsersStore usersStore = mock(NativeUsersStore.class); SecurityIndexManager securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); AnonymousUser anonymousUser = new AnonymousUser(settings); ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), settings, usersStore, anonymousUser, threadPool); reservedRealm.initRealmRef( @@ -183,7 +184,8 @@ public void onFailure(Exception e) { public void testReservedUsersOnly() { NativeUsersStore usersStore = mock(NativeUsersStore.class); SecurityIndexManager securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap()); ReservedRealm reservedRealm = new ReservedRealm( @@ -272,7 +274,8 @@ public void testGetAllUsers() { ); NativeUsersStore usersStore = mock(NativeUsersStore.class); SecurityIndexManager securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap()); ReservedRealm reservedRealm = new ReservedRealm( mock(Environment.class), @@ -377,7 +380,8 @@ public void testGetUsersWithProfileUidException() { ); NativeUsersStore usersStore = mock(NativeUsersStore.class); SecurityIndexManager securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); ReservedRealmTests.mockGetAllReservedUserInfo(usersStore, Collections.emptyMap()); ReservedRealm reservedRealm = new ReservedRealm( mock(Environment.class), diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java index 117d1f1fe14bb..a0a1b622cf36e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java @@ -877,7 +877,7 @@ public void testCrossClusterApiKeyUsageStatsAreZerosWhenIndexDoesNotExist() { public void testCrossClusterApiKeyUsageFailsWhenIndexNotAvailable() { securityIndex = SecurityMocks.mockSecurityIndexManager(".security", true, false); final ElasticsearchException expectedException = new ElasticsearchException("not available"); - when(securityIndex.getUnavailableReason()).thenReturn(expectedException); + when(securityIndex.getUnavailableReason(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(expectedException); final ApiKeyService apiKeyService = createApiKeyService(); final PlainActionFuture> future = new PlainActionFuture<>(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java index d6142b3945a9e..cf343f790d85c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java @@ -1909,8 +1909,9 @@ public void testAuthenticateWithToken() throws Exception { String token = tokenFuture.get().getAccessToken(); when(client.prepareMultiGet()).thenReturn(new MultiGetRequestBuilder(client, MultiGetAction.INSTANCE)); mockGetTokenFromAccessTokenBytes(tokenService, newTokenBytes.v1(), expected, Map.of(), false, null, client); - when(securityIndex.freeze()).thenReturn(securityIndex); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true); try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { threadContext.putHeader("Authorization", "Bearer " + token); @@ -2014,8 +2015,9 @@ public void testInvalidToken() throws Exception { } public void testExpiredToken() throws Exception { - when(securityIndex.freeze()).thenReturn(securityIndex); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true); User user = new User("_username", "r1"); final Authentication expected = AuthenticationTestHelper.builder() diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java index 3f11297950127..02f4e9b0f51fc 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenServiceTests.java @@ -922,14 +922,14 @@ public void testIndexNotAvailable() throws Exception { final SecurityIndexManager tokensIndex; if (pre72OldNode != null) { tokensIndex = securityMainIndex; - when(securityTokensIndex.isAvailableForSearch()).thenReturn(false); + when(securityTokensIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(false); when(securityTokensIndex.indexExists()).thenReturn(false); - when(securityTokensIndex.freeze()).thenReturn(securityTokensIndex); + when(securityTokensIndex.defensiveCopy()).thenReturn(securityTokensIndex); } else { tokensIndex = securityTokensIndex; - when(securityMainIndex.isAvailableForSearch()).thenReturn(false); + when(securityTokensIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(false); when(securityMainIndex.indexExists()).thenReturn(false); - when(securityMainIndex.freeze()).thenReturn(securityMainIndex); + when(securityMainIndex.defensiveCopy()).thenReturn(securityMainIndex); } try (ThreadContext.StoredContext ignore = requestContext.newStoredContextPreservingResponseHeaders()) { PlainActionFuture future = new PlainActionFuture<>(); @@ -937,8 +937,10 @@ public void testIndexNotAvailable() throws Exception { tokenService.tryAuthenticateToken(bearerToken3, future); assertNull(future.get()); - when(tokensIndex.isAvailableForSearch()).thenReturn(false); - when(tokensIndex.getUnavailableReason()).thenReturn(new UnavailableShardsException(null, "unavailable")); + when(securityTokensIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(false); + when(tokensIndex.getUnavailableReason(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn( + new UnavailableShardsException(null, "unavailable") + ); when(tokensIndex.indexExists()).thenReturn(true); future = new PlainActionFuture<>(); final SecureString bearerToken2 = Authenticator.extractBearerTokenFromHeader(requestContext); @@ -951,7 +953,7 @@ public void testIndexNotAvailable() throws Exception { tokenService.tryAuthenticateToken(bearerToken1, future); assertNull(future.get()); - when(tokensIndex.isAvailableForSearch()).thenReturn(true); + when(securityTokensIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); when(tokensIndex.indexExists()).thenReturn(true); mockGetTokenFromAccessTokenBytes(tokenService, newTokenBytes.v1(), authentication, false, null); future = new PlainActionFuture<>(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java index 3d0c2d4419a14..4e364518bb7f3 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeUsersStoreTests.java @@ -317,10 +317,11 @@ private void respondToGetUserRequest(String username, SecureString password, Str @SuppressWarnings("unchecked") private NativeUsersStore startNativeUsersStore() { SecurityIndexManager securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true); when(securityIndex.isIndexUpToDate()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); doAnswer((i) -> { Runnable action = (Runnable) i.getArguments()[1]; action.run(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java index c5942aae939c3..8b61b7912ef42 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java @@ -423,7 +423,8 @@ public void testRealmWithTemplatedRoleMapping() throws Exception { ActiveDirectorySessionFactory sessionFactory = new ActiveDirectorySessionFactory(config, sslService, threadPool); SecurityIndexManager mockSecurityIndex = mock(SecurityIndexManager.class); - when(mockSecurityIndex.isAvailableForSearch()).thenReturn(true); + when(mockSecurityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(mockSecurityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(mockSecurityIndex.isIndexUpToDate()).thenReturn(true); Client mockClient = mock(Client.class); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java index 9db0f7fbf498e..663c4779504a8 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java @@ -490,7 +490,8 @@ public void testLdapRealmWithTemplatedRoleMapping() throws Exception { RealmConfig config = getRealmConfig(REALM_IDENTIFIER, settings); SecurityIndexManager mockSecurityIndex = mock(SecurityIndexManager.class); - when(mockSecurityIndex.isAvailableForSearch()).thenReturn(true); + when(mockSecurityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(mockSecurityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(mockSecurityIndex.isIndexUpToDate()).thenReturn(true); Client mockClient = mock(Client.class); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStoreTests.java index 84c0da6825900..f66e58e7645bb 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/service/IndexServiceAccountTokenStoreTests.java @@ -132,10 +132,11 @@ protected void cacheInvalidatorRegistry = mock(CacheInvalidatorRegistry.class); securityIndex = mock(SecurityIndexManager.class); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true); when(securityIndex.isIndexUpToDate()).thenReturn(true); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); doAnswer((i) -> { Runnable action = (Runnable) i.getArguments()[1]; action.run(); @@ -375,7 +376,7 @@ public void testDeleteToken() { public void testIndexStateIssues() { // Index not exists Mockito.reset(securityIndex); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); when(securityIndex.indexExists()).thenReturn(false); final ServiceAccountId accountId = new ServiceAccountId(randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8)); @@ -394,11 +395,11 @@ public void testIndexStateIssues() { // Index exists but not available Mockito.reset(securityIndex); - when(securityIndex.freeze()).thenReturn(securityIndex); + when(securityIndex.defensiveCopy()).thenReturn(securityIndex); when(securityIndex.indexExists()).thenReturn(true); - when(securityIndex.isAvailableForSearch()).thenReturn(false); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(false); final ElasticsearchException e = new ElasticsearchException("fail"); - when(securityIndex.getUnavailableReason()).thenReturn(e); + when(securityIndex.getUnavailableReason(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(e); final PlainActionFuture> future3 = new PlainActionFuture<>(); store.findTokensFor(accountId, future3); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStoreTests.java index e3daf3ce9d603..925ad547c9863 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/mapper/NativeRoleMappingStoreTests.java @@ -125,7 +125,8 @@ public void testResolveRoles() throws Exception { ScriptModule.CORE_CONTEXTS, () -> 1L ); - when(securityIndex.isAvailableForSearch()).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(true); + when(securityIndex.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(true); final NativeRoleMappingStore store = new NativeRoleMappingStore(Settings.EMPTY, client, securityIndex, scriptService) { @Override diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java index bf7ec63dcd4a1..01d3ca6db354e 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativePrivilegeStoreTests.java @@ -126,9 +126,10 @@ public void searchScroll(SearchScrollRequest request, ActionListener { assertThat(invocationOnMock.getArguments().length, equalTo(2)); assertThat(invocationOnMock.getArguments()[1], instanceOf(Runnable.class)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/profile/ProfileServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/profile/ProfileServiceTests.java index 47c74179c61b4..35efb12b278f2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/profile/ProfileServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/profile/ProfileServiceTests.java @@ -297,8 +297,8 @@ public void testGetProfileSubjectsNoIndex() throws Exception { assertThat(resultsAndErrors.errors().size(), is(0)); when(profileIndex.indexExists()).thenReturn(true); ElasticsearchException unavailableException = new ElasticsearchException("mock profile index unavailable"); - when(profileIndex.isAvailableForSearch()).thenReturn(false); - when(profileIndex.getUnavailableReason()).thenReturn(unavailableException); + when(profileIndex.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(false); + when(profileIndex.getUnavailableReason(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(unavailableException); PlainActionFuture>> future2 = new PlainActionFuture<>(); profileService.getProfileSubjects(randomList(1, 5, () -> randomAlphaOfLength(20)), future2); ExecutionException e = expectThrows(ExecutionException.class, () -> future2.get()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/support/SecurityIndexManagerTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/support/SecurityIndexManagerTests.java index f256b8c7d9412..c8f86957f84a3 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/support/SecurityIndexManagerTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/support/SecurityIndexManagerTests.java @@ -123,9 +123,8 @@ public void testIndexWithUpToDateMappingAndTemplate() { manager.clusterChanged(event(markShardsAvailable(clusterStateBuilder))); assertThat(manager.indexExists(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(true)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(true)); } @@ -208,9 +207,8 @@ public void testIndexAvailability() { ClusterState clusterState = clusterStateBuilder.build(); manager.clusterChanged(event(clusterState)); assertThat(manager.indexExists(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(false)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(true)); assertThat(manager.isStateRecovered(), Matchers.equalTo(true)); @@ -230,9 +228,8 @@ public void testIndexAvailability() { clusterState = clusterStateBuilder.build(); manager.clusterChanged(event(clusterState)); assertThat(manager.indexExists(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(true)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(true)); assertThat(manager.isStateRecovered(), Matchers.equalTo(true)); @@ -249,9 +246,8 @@ public void testIndexAvailability() { clusterState = clusterStateBuilder.build(); manager.clusterChanged(event(clusterState)); assertThat(manager.indexExists(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(true)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(true)); assertThat(manager.isStateRecovered(), Matchers.equalTo(true)); @@ -514,9 +510,8 @@ public void testProcessClosedIndexState() { ); manager.clusterChanged(event(markShardsAvailable(indexAvailable))); assertThat(manager.indexExists(), is(true)); - assertThat(manager.isAvailableForSearch(), is(true)); - assertThat(manager.isAvailableForWrite(), is(true)); - assertThat(manager.isAvailableForRealTimeGet(), is(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), is(true)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), is(true)); // Now close it ClusterState.Builder indexClosed = createClusterState( @@ -533,25 +528,22 @@ public void testProcessClosedIndexState() { manager.clusterChanged(event(indexClosed.build())); assertThat(manager.indexExists(), is(true)); - assertThat(manager.isAvailableForSearch(), is(false)); - assertThat(manager.isAvailableForWrite(), is(false)); - assertThat(manager.isAvailableForRealTimeGet(), is(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), is(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), is(false)); } private void assertInitialState() { assertThat(manager.indexExists(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(false)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(false)); assertThat(manager.isStateRecovered(), Matchers.equalTo(false)); } private void assertIndexUpToDateButNotAvailable() { assertThat(manager.indexExists(), Matchers.equalTo(true)); - assertThat(manager.isAvailableForSearch(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForWrite(), Matchers.equalTo(false)); - assertThat(manager.isAvailableForRealTimeGet(), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS), Matchers.equalTo(false)); + assertThat(manager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS), Matchers.equalTo(false)); assertThat(manager.isMappingUpToDate(), Matchers.equalTo(true)); assertThat(manager.isStateRecovered(), Matchers.equalTo(true)); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityMocks.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityMocks.java index 83ccb44ebed52..a15d8409fe2b4 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityMocks.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityMocks.java @@ -86,9 +86,10 @@ public static SecurityIndexManager mockSecurityIndexManager(String alias, boolea return null; }).when(securityIndexManager).checkIndexVersionThenExecute(anyConsumer(), any(Runnable.class)); when(securityIndexManager.indexExists()).thenReturn(exists); - when(securityIndexManager.isAvailableForSearch()).thenReturn(available); + when(securityIndexManager.isAvailable(SecurityIndexManager.Availability.PRIMARY_SHARDS)).thenReturn(available); + when(securityIndexManager.isAvailable(SecurityIndexManager.Availability.SEARCH_SHARDS)).thenReturn(available); when(securityIndexManager.aliasName()).thenReturn(alias); - when(securityIndexManager.freeze()).thenReturn(securityIndexManager); + when(securityIndexManager.defensiveCopy()).thenReturn(securityIndexManager); return securityIndexManager; }