From fa07a97b347595d5b7dee350d1a63d667452dfed Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 10:51:53 +0200 Subject: [PATCH 01/20] Names --- .../security/index/IndexAuditTrailField.java | 12 ---- .../security/index/SystemIndicesNames.java | 33 +++++++++ .../xpack/core/security/user/XPackUser.java | 4 +- .../xpack/security/Security.java | 25 ++++--- .../security/audit/index/IndexAuditTrail.java | 8 +-- .../security/authc/ExpiredTokenRemover.java | 4 +- .../xpack/security/authc/TokenService.java | 23 ++++--- .../authc/esnative/NativeUsersStore.java | 26 +++---- .../mapper/NativeRoleMappingStore.java | 14 ++-- .../security/authz/AuthorizationService.java | 6 +- .../security/authz/AuthorizedIndices.java | 4 +- .../authz/store/NativePrivilegeStore.java | 10 +-- .../authz/store/NativeRolesStore.java | 18 ++--- .../support/SecurityIndexManager.java | 18 ++--- .../integration/ClearRolesCacheTests.java | 4 +- .../test/SecurityIntegTestCase.java | 8 +-- .../xpack/security/SecuritySettingsTests.java | 5 +- .../xpack/security/SecurityTests.java | 8 +-- .../security/audit/index/AuditTrailTests.java | 4 +- .../audit/index/IndexAuditTrailTests.java | 4 +- .../security/authc/TokenAuthIntegTests.java | 10 +-- .../esnative/ESNativeMigrateToolTests.java | 6 +- .../authc/esnative/NativeRealmIntegTests.java | 25 ++++--- .../authc/esnative/NativeUsersStoreTests.java | 7 +- .../authz/AuthorizationServiceTests.java | 68 +++++++++---------- .../authz/AuthorizedIndicesTests.java | 8 +-- .../authz/IndicesAndAliasesResolverTests.java | 17 +++-- .../store/NativePrivilegeStoreTests.java | 17 ++--- .../authz/store/NativeRolesStoreTests.java | 6 +- .../support/SecurityIndexManagerTests.java | 10 +-- .../security/test/SecurityTestUtils.java | 4 +- .../xpack/security/user/XPackUserTests.java | 9 ++- 32 files changed, 218 insertions(+), 207 deletions(-) delete mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/IndexAuditTrailField.java create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/IndexAuditTrailField.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/IndexAuditTrailField.java deleted file mode 100644 index 340dad82844a0..0000000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/IndexAuditTrailField.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.core.security.index; - -public final class IndexAuditTrailField { - public static final String INDEX_NAME_PREFIX = ".security_audit_log"; - - private IndexAuditTrailField() {} -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java new file mode 100644 index 0000000000000..fa8b51e2681ab --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.core.security.index; + +import org.elasticsearch.xpack.core.upgrade.IndexUpgradeCheckVersion; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public final class SystemIndicesNames { + + public static final String AUDIT_INDEX_NAME_PREFIX = ".security_audit_log"; + public static final String INTERNAL_SECURITY_INDEX = ".security-" + IndexUpgradeCheckVersion.UPRADE_VERSION; + public static final String SECURITY_INDEX_NAME = ".security"; + private static final List index_names; + + static { + index_names = Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)); + } + + private SystemIndicesNames() { + } + + public static List indexNames() { + return index_names; + } + +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/XPackUser.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/XPackUser.java index 38c9fe84aa934..e3fd257f64750 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/XPackUser.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/XPackUser.java @@ -7,7 +7,7 @@ import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.permission.Role; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.MetadataUtils; /** @@ -20,7 +20,7 @@ public class XPackUser extends User { public static final Role ROLE = Role.builder(new RoleDescriptor(ROLE_NAME, new String[] { "all" }, new RoleDescriptor.IndicesPrivileges[] { RoleDescriptor.IndicesPrivileges.builder().indices("/@&~(\\.security.*)/").privileges("all").build(), - RoleDescriptor.IndicesPrivileges.builder().indices(IndexAuditTrailField.INDEX_NAME_PREFIX + "-*") + RoleDescriptor.IndicesPrivileges.builder().indices(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX + "-*") .privileges("read").build() }, new String[] { "*" }, diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java index 6b41ab02071e0..ce3b119d685c9 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java @@ -123,7 +123,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.ssl.SSLConfiguration; @@ -250,7 +250,6 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin, @@ -419,7 +418,7 @@ Collection createComponents(Client client, ThreadPool threadPool, Cluste components.add(auditTrailService); this.auditTrailService.set(auditTrailService); - securityIndex.set(new SecurityIndexManager(client, SecurityIndexManager.SECURITY_INDEX_NAME, clusterService)); + securityIndex.set(new SecurityIndexManager(client, SystemIndicesNames.SECURITY_INDEX_NAME, clusterService)); final TokenService tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex.get(), clusterService); this.tokenService.set(tokenService); @@ -799,7 +798,7 @@ static void validateAutoCreateIndex(Settings settings) { final boolean indexAuditingEnabled = Security.indexAuditLoggingEnabled(settings); if (indexAuditingEnabled) { - String auditIndex = IndexAuditTrailField.INDEX_NAME_PREFIX + "*"; + String auditIndex = SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX + "*"; String errorMessage = LoggerMessageFormat.format( "the [action.auto_create_index] setting value [{}] is too" + " restrictive. disable [action.auto_create_index] or set it to include " + @@ -817,20 +816,20 @@ static void validateAutoCreateIndex(Settings settings) { DateTime now = new DateTime(DateTimeZone.UTC); // just use daily rollover - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusDays(1), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY)); + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusDays(1), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(1), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(1), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(2), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(2), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(3), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(3), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(4), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(4), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(5), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(5), IndexNameResolver.Rollover.DAILY)); - indices.add(IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now.plusMonths(6), + indices.add(IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now.plusMonths(6), IndexNameResolver.Rollover.DAILY)); for (String index : indices) { @@ -1030,7 +1029,7 @@ static final class ValidateUpgradedSecurityIndex implements BiConsumer listener) throws IOExce securityIndex.checkIndexVersionThenExecute( ex -> listener.onFailure(traceLog("prepare security index", tokenId, ex)), () -> { - final GetRequest getRequest = client.prepareGet(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, + final GetRequest getRequest = client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, getTokenDocumentId(tokenId)).request(); Consumer onFailure = ex -> listener.onFailure(traceLog("decode token", tokenId, ex)); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest, @@ -542,7 +543,7 @@ private void indexBwcInvalidation(UserToken userToken, ActionListener l listener.onFailure(invalidGrantException("failed to invalidate token")); } else { final String invalidatedTokenId = getInvalidatedTokenDocumentId(userToken); - IndexRequest indexRequest = client.prepareIndex(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, invalidatedTokenId) + IndexRequest indexRequest = client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, invalidatedTokenId) .setOpType(OpType.CREATE) .setSource("doc_type", INVALIDATED_TOKEN_DOC_TYPE, "expiration_time", expirationEpochMilli) .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL) @@ -588,7 +589,7 @@ private void indexInvalidation(String tokenDocId, Version version, ActionListene logger.warn("Failed to invalidate token [{}] after [{}] attempts", tokenDocId, attemptCount.get()); listener.onFailure(invalidGrantException("failed to invalidate token")); } else { - UpdateRequest request = client.prepareUpdate(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, tokenDocId) + UpdateRequest request = client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, tokenDocId) .setDoc(srcPrefix, Collections.singletonMap("invalidated", true)) .setVersion(documentVersion) .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL) @@ -622,7 +623,7 @@ private void indexInvalidation(String tokenDocId, Version version, ActionListene || isShardNotAvailableException(cause)) { attemptCount.incrementAndGet(); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, tokenDocId).request(), + client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, tokenDocId).request(), ActionListener.wrap(getResult -> { if (getResult.isExists()) { Map source = getResult.getSource(); @@ -690,7 +691,7 @@ private void findTokenFromRefreshToken(String refreshToken, ActionListener onFailure = ex -> listener.onFailure(traceLog("refresh token", tokenDocId, ex)); - GetRequest getRequest = client.prepareGet(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, tokenDocId).request(); + GetRequest getRequest = client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, tokenDocId).request(); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest, ActionListener.wrap(response -> { if (response.isExists()) { @@ -768,7 +769,7 @@ private void innerRefresh(String tokenDocId, Authentication userAuth, ActionList in.setVersion(authVersion); Authentication authentication = new Authentication(in); UpdateRequest updateRequest = - client.prepareUpdate(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, tokenDocId) + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, tokenDocId) .setVersion(response.getVersion()) .setDoc("refresh_token", Collections.singletonMap("refreshed", true)) .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL) @@ -886,7 +887,7 @@ public void findActiveTokensForRealm(String realmName, ActionListener { MultiGetRequest mGetRequest = client.prepareMultiGet() - .add(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, getInvalidatedTokenDocumentId(userToken)) - .add(SecurityIndexManager.SECURITY_INDEX_NAME, TYPE, getTokenDocumentId(userToken)) + .add(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, getInvalidatedTokenDocumentId(userToken)) + .add(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, getTokenDocumentId(userToken)) .request(); Consumer onFailure = ex -> listener.onFailure(traceLog("check token state", userToken.getId(), ex)); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, 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 47c32489ae1f4..aeca14173fa9a 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 @@ -47,6 +47,7 @@ import org.elasticsearch.xpack.core.security.authc.esnative.ClientReservedRealm; import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User.Fields; @@ -66,7 +67,6 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; /** * NativeUsersStore is a store for users that reads from an Elasticsearch index. This store is responsible for fetching the full @@ -147,7 +147,7 @@ public void getUsers(String[] userNames, final ActionListener> } final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -172,7 +172,7 @@ void getUserCount(final ActionListener listener) { } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareSearch(SECURITY_INDEX_NAME) + client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), USER_DOC_TYPE)) .setSize(0) .request(), @@ -205,7 +205,7 @@ private void getUserAndPassword(final String user, final ActionListener executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SECURITY_INDEX_NAME, + client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, user)).request(), new ActionListener() { @Override @@ -246,7 +246,7 @@ public void changePassword(final ChangePasswordRequest request, final ActionList securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(docType, username)) + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(docType, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.PASSWORD.getPreferredName(), String.valueOf(request.passwordHash())) .setRefreshPolicy(request.getRefreshPolicy()).request(), @@ -284,7 +284,7 @@ public void onFailure(Exception e) { private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)) .setSource(Fields.PASSWORD.getPreferredName(), String.valueOf(passwordHash), Fields.ENABLED.getPreferredName(), true, @@ -326,7 +326,7 @@ private void updateUserWithoutPassword(final PutUserRequest putUserRequest, fina // We must have an existing document securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.USERNAME.getPreferredName(), putUserRequest.username(), @@ -371,7 +371,7 @@ private void indexUser(final PutUserRequest putUserRequest, final ActionListener assert putUserRequest.passwordHash() != null; securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) .setSource(Fields.USERNAME.getPreferredName(), putUserRequest.username(), Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()), @@ -415,7 +415,7 @@ private void setRegularUserEnabled(final String username, final boolean enabled, final ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setRefreshPolicy(refreshPolicy) @@ -450,7 +450,7 @@ private void setReservedUserEnabled(final String username, final boolean enabled boolean clearCache, final ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setUpsert(XContentType.JSON, @@ -485,7 +485,7 @@ public void deleteUser(final DeleteUserRequest deleteUserRequest, final ActionLi listener.onFailure(frozenSecurityIndex.getUnavailableReason()); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { - DeleteRequest request = client.prepareDelete(SECURITY_INDEX_NAME, + DeleteRequest request = client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username())).request(); request.setRefreshPolicy(deleteUserRequest.getRefreshPolicy()); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, @@ -532,7 +532,7 @@ void getReservedUserInfo(String username, ActionListener liste } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)).request(), new ActionListener() { @Override @@ -577,7 +577,7 @@ void getAllReservedUserInfo(ActionListener> listen } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareSearch(SECURITY_INDEX_NAME) + client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE)) .setFetchSource(true).request(), new ActionListener() { 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 3181c14fc272d..7eb5dc8a5b457 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 @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping; import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExpressionModel; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.authc.support.CachingRealm; import org.elasticsearch.xpack.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.security.support.SecurityIndexManager; @@ -60,13 +61,12 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed; /** * This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch - * {@link SecurityIndexManager#SECURITY_INDEX_NAME index}. + * {@link SystemIndicesNames#SECURITY_INDEX_NAME index}. *
* The store is responsible for all read and write operations as well as * {@link #resolveRoles(UserData, ActionListener) resolving roles}. @@ -131,7 +131,7 @@ void loadMappings(ActionListener> listener) { final QueryBuilder query = QueryBuilders.termQuery(DOC_TYPE_FIELD, DOC_TYPE_ROLE_MAPPING); final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setTypes(SECURITY_GENERIC_TYPE) .setQuery(query) @@ -144,7 +144,7 @@ void loadMappings(ActionListener> listener) { listener.onResponse(mappings.stream().filter(Objects::nonNull).collect(Collectors.toList())), ex -> { logger.error(new ParameterizedMessage("failed to load role mappings from index [{}] skipping all mappings.", - SECURITY_INDEX_NAME), ex); + SystemIndicesNames.SECURITY_INDEX_NAME), ex); listener.onResponse(Collections.emptyList()); })), doc -> buildMapping(getNameFromId(doc.getId()), doc.getSourceRef())); @@ -203,7 +203,7 @@ private void innerPutMapping(PutRoleMappingRequest request, ActionListener { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareDelete(SECURITY_INDEX_NAME, SECURITY_GENERIC_TYPE, getIdForName(request.getName())) + client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, SECURITY_GENERIC_TYPE, getIdForName(request.getName())) .setRefreshPolicy(request.getRefreshPolicy()) .request(), new ActionListener() { @@ -287,7 +287,7 @@ private void getMappings(ActionListener> listener) { logger.info("The security index is not yet available - no role mappings can be loaded"); if (logger.isDebugEnabled()) { logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]", - SECURITY_INDEX_NAME, + SystemIndicesNames.SECURITY_INDEX_NAME, securityIndex.indexExists(), securityIndex.isAvailable(), securityIndex.isMappingUpToDate() diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 35a2f5340492d..848525e43696e 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -56,6 +56,7 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.SystemUser; @@ -67,7 +68,6 @@ import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver.ResolvedIndices; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.util.Arrays; import java.util.Collections; @@ -320,7 +320,7 @@ && isSuperuser(authentication.getUser()) == false) { // only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging // purposes. These monitor requests also sometimes resolve indices concretely and then requests them logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]", - authentication.getUser().principal(), action, SecurityIndexManager.SECURITY_INDEX_NAME); + authentication.getUser().principal(), action, SystemIndicesNames.SECURITY_INDEX_NAME); throw denial(auditId, authentication, action, request, permission.names()); } else { putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, indicesAccessControl); @@ -360,7 +360,7 @@ private boolean isInternalUser(User user) { } private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) { - for (String index : SecurityIndexManager.indexNames()) { + for (String index : SystemIndicesNames.indexNames()) { final IndicesAccessControl.IndexAccessControl indexPermissions = indicesAccessControl.getIndexPermissions(index); if (indexPermissions != null && indexPermissions.isGranted()) { return true; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java index 3068a3993d309..3753b94faaa12 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java @@ -8,8 +8,8 @@ import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.xpack.core.security.authz.permission.Role; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.User; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.util.ArrayList; import java.util.Collections; @@ -58,7 +58,7 @@ private List load() { if (isSuperuser(user) == false) { // we should filter out all of the security indices from wildcards - indicesAndAliases.removeAll(SecurityIndexManager.indexNames()); + indicesAndAliases.removeAll(SystemIndicesNames.indexNames()); } return Collections.unmodifiableList(indicesAndAliases); } 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 63b3ba2c9bba7..826c5f556580e 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 @@ -43,6 +43,7 @@ import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheResponse; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.io.IOException; @@ -61,7 +62,6 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; /** * {@code NativePrivilegeStore} is a store that reads/writes {@link ApplicationPrivilegeDescriptor} objects, @@ -122,7 +122,7 @@ public void getPrivileges(Collection applications, Collection na } final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -151,7 +151,7 @@ void getPrivilege(String application, String name, ActionListener executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SECURITY_INDEX_NAME, "doc", toDocId(application, name)).request(), + client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(application, name)).request(), new ActionListener() { @Override public void onResponse(GetResponse response) { @@ -202,7 +202,7 @@ private void innerPutPrivilege(ApplicationPrivilegeDescriptor privilege, WriteRe final String name = privilege.getName(); final XContentBuilder xContentBuilder = privilege.toXContent(jsonBuilder(), true); ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SECURITY_INDEX_NAME, "doc", toDocId(privilege.getApplication(), name)) + client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(privilege.getApplication(), name)) .setSource(xContentBuilder) .setRefreshPolicy(refreshPolicy) .request(), listener, client::index); @@ -233,7 +233,7 @@ public void deletePrivileges(String application, Collection names, Write }, listener::onFailure), names.size(), Collections.emptyList()); for (String name : names) { ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareDelete(SECURITY_INDEX_NAME, "doc", toDocId(application, name)) + client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(application, name)) .setRefreshPolicy(refreshPolicy) .request(), groupListener, client::delete); } 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 a36f830ceacbc..0a70688c19330 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 @@ -47,6 +47,7 @@ import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.io.IOException; @@ -70,7 +71,6 @@ import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; import static org.elasticsearch.xpack.core.security.SecurityField.setting; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ROLE_TYPE; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; /** * NativeRolesStore is a {@code RolesStore} that, instead of reading from a @@ -122,7 +122,7 @@ public void getRoleDescriptors(Set names, final ActionListener supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -140,7 +140,7 @@ public void getRoleDescriptors(Set names, final ActionListener { final String[] roleIds = names.stream().map(NativeRolesStore::getIdForRole).toArray(String[]::new); - MultiGetRequest multiGetRequest = client.prepareMultiGet().add(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); + MultiGetRequest multiGetRequest = client.prepareMultiGet().add(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, multiGetRequest, ActionListener.wrap(mGetResponse -> { final MultiGetItemResponse[] responses = mGetResponse.getResponses(); @@ -176,7 +176,7 @@ public void deleteRole(final DeleteRoleRequest deleteRoleRequest, final ActionLi listener.onFailure(frozenSecurityIndex.getUnavailableReason()); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { - DeleteRequest request = client.prepareDelete(SecurityIndexManager.SECURITY_INDEX_NAME, + DeleteRequest request = client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(deleteRoleRequest.name())).request(); request.setRefreshPolicy(deleteRoleRequest.getRefreshPolicy()); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, @@ -217,7 +217,7 @@ void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final listener.onFailure(e); return; } - final IndexRequest indexRequest = client.prepareIndex(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) + final IndexRequest indexRequest = client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) .setSource(xContentBuilder) .setRefreshPolicy(request.getRefreshPolicy()) .request(); @@ -251,10 +251,10 @@ public void usageStats(ActionListener> listener) { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, client.prepareMultiSearch() - .add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .setSize(0)) - .add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setQuery(QueryBuilders.boolQuery() .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .must(QueryBuilders.boolQuery() @@ -264,7 +264,7 @@ public void usageStats(ActionListener> listener) { .should(existsQuery("indices.fields")))) .setSize(0) .setTerminateAfter(1)) - .add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setQuery(QueryBuilders.boolQuery() .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .filter(existsQuery("indices.query"))) @@ -332,7 +332,7 @@ public void onFailure(Exception e) { private void executeGetRoleRequest(String role, ActionListener listener) { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SECURITY_INDEX_NAME, + client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role)).request(), listener, client::get)); 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 acd4f1c480500..266a4f5c8833c 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 @@ -40,12 +40,10 @@ import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.template.TemplateUtils; -import org.elasticsearch.xpack.core.upgrade.IndexUpgradeCheckVersion; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -67,12 +65,10 @@ */ public class SecurityIndexManager implements ClusterStateListener { - public static final String INTERNAL_SECURITY_INDEX = ".security-" + IndexUpgradeCheckVersion.UPRADE_VERSION; public static final int INTERNAL_INDEX_FORMAT = 6; public static final String SECURITY_VERSION_STRING = "security-version"; public static final String TEMPLATE_VERSION_PATTERN = Pattern.quote("${security.template.version}"); public static final String SECURITY_TEMPLATE_NAME = "security-index-template"; - public static final String SECURITY_INDEX_NAME = ".security"; private static final Logger LOGGER = LogManager.getLogger(SecurityIndexManager.class); private final String indexName; @@ -97,10 +93,6 @@ public SecurityIndexManager freeze() { return new SecurityIndexManager(null, indexName, indexState); } - public static List indexNames() { - return Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)); - } - public boolean checkMappingVersion(Predicate requiredVersion) { // pull value into local variable for consistent view final State currentIndexState = this.indexState; @@ -136,7 +128,7 @@ public ElasticsearchException getUnavailableReason() { if (localState.indexExists) { return new UnavailableShardsException(null, "at least one primary shard for the security index is unavailable"); } else { - return new IndexNotFoundException(SECURITY_INDEX_NAME); + return new IndexNotFoundException(SystemIndicesNames.SECURITY_INDEX_NAME); } } @@ -307,8 +299,8 @@ public void prepareIndexIfNeededThenExecute(final Consumer consumer, "the upgrade API is run on the security index")); } else if (indexState.indexExists == false) { Tuple mappingAndSettings = loadMappingAndSettingsSourceFromTemplate(); - CreateIndexRequest request = new CreateIndexRequest(INTERNAL_SECURITY_INDEX) - .alias(new Alias(SECURITY_INDEX_NAME)) + CreateIndexRequest request = new CreateIndexRequest(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .alias(new Alias(SystemIndicesNames.SECURITY_INDEX_NAME)) .mapping("doc", mappingAndSettings.v1(), XContentType.JSON) .waitForActiveShards(ActiveShardCount.ALL) .settings(mappingAndSettings.v2()); @@ -336,7 +328,7 @@ public void onFailure(Exception e) { } }, client.admin().indices()::create); } else if (indexState.mappingUpToDate == false) { - PutMappingRequest request = new PutMappingRequest(INTERNAL_SECURITY_INDEX) + PutMappingRequest request = new PutMappingRequest(SystemIndicesNames.INTERNAL_SECURITY_INDEX) .source(loadMappingAndSettingsSourceFromTemplate().v1(), XContentType.JSON) .type("doc"); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/ClearRolesCacheTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/ClearRolesCacheTests.java index 79d1d19c50e8a..1fa558321b363 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/ClearRolesCacheTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/integration/ClearRolesCacheTests.java @@ -13,8 +13,8 @@ import org.elasticsearch.xpack.core.security.action.role.PutRoleResponse; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.junit.Before; import org.junit.BeforeClass; @@ -56,7 +56,7 @@ public void setupForTests() { logger.debug("--> created role [{}]", role); } - ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); final Set rolesSet = new HashSet<>(Arrays.asList(roles)); // warm up the caches on every node diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java index c3e3bddf10e97..bf00961605fc8 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java @@ -44,6 +44,7 @@ import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.LocalStateSecurity; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.junit.AfterClass; @@ -67,7 +68,6 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.is; import static org.hamcrest.core.IsCollectionContaining.hasItem; @@ -491,7 +491,7 @@ public void assertSecurityIndexActive(TestCluster testCluster) throws Exception XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().startObject(); assertTrue("security index mapping not sufficient to read:\n" + Strings.toString(clusterState.toXContent(builder, ToXContent.EMPTY_PARAMS).endObject()), - SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, + SecurityIndexManager.checkIndexMappingVersionMatches(SystemIndicesNames.SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT.minimumIndexCompatibilityVersion()::onOrBefore)); Index securityIndex = resolveSecurityIndex(clusterState.metaData()); if (securityIndex != null) { @@ -509,7 +509,7 @@ protected void deleteSecurityIndex() { UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER, SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING))); GetIndexRequest getIndexRequest = new GetIndexRequest(); - getIndexRequest.indices(SECURITY_INDEX_NAME); + getIndexRequest.indices(SystemIndicesNames.SECURITY_INDEX_NAME); getIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); GetIndexResponse getIndexResponse = client.admin().indices().getIndex(getIndexRequest).actionGet(); if (getIndexResponse.getIndices().length > 0) { @@ -520,7 +520,7 @@ protected void deleteSecurityIndex() { } private static Index resolveSecurityIndex(MetaData metaData) { - final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(SECURITY_INDEX_NAME); + final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(SystemIndicesNames.SECURITY_INDEX_NAME); if (aliasOrIndex != null) { return aliasOrIndex.getIndices().get(0).getIndex(); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecuritySettingsTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecuritySettingsTests.java index c928d5b46b654..82cbcd2311505 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecuritySettingsTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecuritySettingsTests.java @@ -8,8 +8,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.XPackSettings; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; - +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import static org.hamcrest.Matchers.containsString; @@ -39,7 +38,7 @@ public void testValidAutoCreateIndex() { .build()); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString(IndexAuditTrailField.INDEX_NAME_PREFIX)); + assertThat(e.getMessage(), containsString(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX)); } Security.validateAutoCreateIndex(Settings.builder() diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java index e9924b9d85245..eb0fb8b0be459 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java @@ -40,6 +40,7 @@ import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions; import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsDefinition; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; @@ -66,7 +67,6 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.discovery.DiscoveryModule.ZEN2_DISCOVERY_TYPE; import static org.elasticsearch.discovery.DiscoveryModule.ZEN_DISCOVERY_TYPE; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; @@ -339,7 +339,7 @@ public void testIndexJoinValidator_Old_And_Rolling() throws Exception { BiConsumer joinValidator = security.getJoinValidator(); assertNotNull(joinValidator); DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); - IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) + IndexMetaData indexMetaData = IndexMetaData.builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT - 1)) .numberOfShards(1).numberOfReplicas(0) .build(); @@ -360,7 +360,7 @@ public void testIndexJoinValidator_FullyCurrentCluster() throws Exception { assertNotNull(joinValidator); DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); int indexFormat = randomBoolean() ? INTERNAL_INDEX_FORMAT : INTERNAL_INDEX_FORMAT - 1; - IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) + IndexMetaData indexMetaData = IndexMetaData.builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), indexFormat)) .numberOfShards(1).numberOfReplicas(0) .build(); @@ -378,7 +378,7 @@ public void testIndexUpgradeValidatorWithUpToDateIndex() throws Exception { assertNotNull(joinValidator); Version version = randomBoolean() ? Version.CURRENT : Version.V_6_1_0; DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); - IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) + IndexMetaData indexMetaData = IndexMetaData.builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(settings(version).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT)) .numberOfShards(1).numberOfReplicas(0) .build(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java index 022328f426fa3..ab0b18b74d02d 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java @@ -23,7 +23,7 @@ import org.elasticsearch.xpack.core.security.ScrollHelper; import org.elasticsearch.xpack.core.security.authc.AuthenticationServiceField; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.audit.AuditTrail; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.joda.time.DateTime; @@ -155,7 +155,7 @@ private Collection> waitForAuditEvents() throws InterruptedE private Collection> getAuditEvents() throws Exception { final Client client = client(); final DateTime now = new DateTime(DateTimeZone.UTC); - final String indexName = IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY); + final String indexName = IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY); assertTrue(awaitBusy(() -> indexExists(client, indexName), 5, TimeUnit.SECONDS)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/IndexAuditTrailTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/IndexAuditTrailTests.java index 9fe510435c5ab..d8c068574226b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/IndexAuditTrailTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/IndexAuditTrailTests.java @@ -56,7 +56,7 @@ import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.core.security.authc.AuthenticationToken; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.security.LocalStateSecurity; @@ -934,7 +934,7 @@ private RestRequest mockRestRequest() { private SearchHit getIndexedAuditMessage(Message message) throws InterruptedException { assertNotNull("no audit message was enqueued", message); - final String indexName = IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, message.timestamp, rollover); + final String indexName = IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, message.timestamp, rollover); ensureYellowAndNoInitializingShards(indexName); GetSettingsResponse settingsResponse = getClient().admin().indices().prepareGetSettings(indexName).get(); assertThat(settingsResponse.getSetting(indexName, "index.number_of_shards"), is(Integer.toString(numShards))); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenAuthIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenAuthIntegTests.java index c4efdc16e10e6..b1512ee4cfcbf 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenAuthIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/TokenAuthIntegTests.java @@ -32,7 +32,7 @@ import org.elasticsearch.xpack.core.security.authc.TokenMetaData; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.junit.After; import org.junit.Before; @@ -147,7 +147,7 @@ public void testExpiredTokensDeletedAfterExpiration() throws Exception { assertTrue(invalidateResponse.isCreated()); AtomicReference docId = new AtomicReference<>(); assertBusy(() -> { - SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + SearchResponse searchResponse = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setSource(SearchSourceBuilder.searchSource() .query(QueryBuilders.termQuery("doc_type", TokenService.INVALIDATED_TOKEN_DOC_TYPE))) .setSize(1) @@ -160,7 +160,7 @@ public void testExpiredTokensDeletedAfterExpiration() throws Exception { // hack doc to modify the time to the day before Instant dayBefore = created.minus(1L, ChronoUnit.DAYS); assertTrue(Instant.now().isAfter(dayBefore)); - client.prepareUpdate(SecurityIndexManager.SECURITY_INDEX_NAME, "doc", docId.get()) + client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", docId.get()) .setDoc("expiration_time", dayBefore.toEpochMilli()) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .get(); @@ -178,8 +178,8 @@ public void testExpiredTokensDeletedAfterExpiration() throws Exception { assertEquals("token malformed", e.getMessage()); } } - client.admin().indices().prepareRefresh(SecurityIndexManager.SECURITY_INDEX_NAME).get(); - SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) + client.admin().indices().prepareRefresh(SystemIndicesNames.SECURITY_INDEX_NAME).get(); + SearchResponse searchResponse = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) .setSource(SearchSourceBuilder.searchSource() .query(QueryBuilders.termQuery("doc_type", TokenService.INVALIDATED_TOKEN_DOC_TYPE))) .setSize(0) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java index 7f3e2cfce9854..41a4436fb29a3 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java @@ -16,7 +16,7 @@ import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.common.CharArrays; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.junit.BeforeClass; import java.nio.charset.StandardCharsets; @@ -84,7 +84,7 @@ public void testRetrieveUsers() throws Exception { addedUsers.add(uname); } logger.error("--> waiting for .security index"); - ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); MockTerminal t = new MockTerminal(); String username = nodeClientUsername(); @@ -133,7 +133,7 @@ public void testRetrieveRoles() throws Exception { addedRoles.add(rname); } logger.error("--> waiting for .security index"); - ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); MockTerminal t = new MockTerminal(); String username = nodeClientUsername(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java index af337cdc718aa..42222fdadefc9 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java @@ -40,6 +40,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.client.SecurityClient; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; @@ -60,8 +61,6 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -138,7 +137,7 @@ public void testAddAndGetUser() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3kirt".toCharArray(), hasher, "role1", "user").get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -193,7 +192,7 @@ public void testAddAndGetRole() throws Exception { .metadata(metadata) .get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); logger.info("--> retrieving role"); GetRolesResponse resp = c.prepareGetRoles().names("test_role").get(); assertTrue("role should exist", resp.hasRoles()); @@ -244,7 +243,7 @@ public void testAddUserAndRoleThenAuth() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -265,7 +264,7 @@ public void testUpdatingUserAndAuthentication() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -301,7 +300,7 @@ public void testCreateDeleteAuthenticate() { c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -339,7 +338,7 @@ public void testCreateAndUpdateRole() { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); if (authenticate) { final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); @@ -389,7 +388,7 @@ public void testAuthenticateWithDeletedRole() { .get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SECURITY_INDEX_NAME); + ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster() @@ -520,12 +519,12 @@ public void testUsersAndRolesDoNotInterfereWithIndicesStats() throws Exception { .get(); } - IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SECURITY_INDEX_NAME).get(); + IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SystemIndicesNames.SECURITY_INDEX_NAME).get(); assertThat(response.getFailedShards(), is(0)); assertThat(response.getIndices().size(), is(2)); - assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX), notNullValue()); - assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX).getIndex(), - is(INTERNAL_SECURITY_INDEX)); + assertThat(response.getIndices().get(SystemIndicesNames.INTERNAL_SECURITY_INDEX), notNullValue()); + assertThat(response.getIndices().get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).getIndex(), + is(SystemIndicesNames.INTERNAL_SECURITY_INDEX)); } public void testOperationsOnReservedUsers() throws Exception { 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 41bd8bfc6e620..036744775d5b7 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 @@ -26,6 +26,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; import org.elasticsearch.xpack.core.security.authc.support.Hasher; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; @@ -109,7 +110,7 @@ public void testBlankPasswordInIndexImpliesDefaultPassword() throws Exception { values.put(PASSWORD_FIELD, BLANK_PASSWORD); final GetResult result = new GetResult( - SecurityIndexManager.SECURITY_INDEX_NAME, + SystemIndicesNames.SECURITY_INDEX_NAME, NativeUsersStore.INDEX_TYPE, NativeUsersStore.getIdForUser(NativeUsersStore.RESERVED_USER_TYPE, randomAlphaOfLength(12)), 1L, @@ -178,7 +179,7 @@ public void testVerifyNonExistentUser() throws Exception { nativeUsersStore.verifyPassword(username, password, future); final GetResult getResult = new GetResult( - SecurityIndexManager.SECURITY_INDEX_NAME, + SystemIndicesNames.SECURITY_INDEX_NAME, NativeUsersStore.INDEX_TYPE, NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username), 1L, @@ -220,7 +221,7 @@ private void respondToGetUserRequest(String username, SecureString password, Str values.put(User.Fields.TYPE.getPreferredName(), NativeUsersStore.USER_DOC_TYPE); final BytesReference source = BytesReference.bytes(jsonBuilder().map(values)); final GetResult getResult = new GetResult( - SecurityIndexManager.SECURITY_INDEX_NAME, + SystemIndicesNames.SECURITY_INDEX_NAME, NativeUsersStore.INDEX_TYPE, NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username), 1L, diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 2a9d832f0f012..427562c9a6234 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -119,6 +119,7 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.SystemUser; @@ -150,7 +151,6 @@ import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.endsWith; @@ -805,7 +805,7 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); @@ -813,21 +813,21 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { List> requests = new ArrayList<>(); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - new DeleteRequest(SECURITY_INDEX_NAME, "type", "id"))); + new DeleteRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(UpdateAction.NAME, - new UpdateRequest(SECURITY_INDEX_NAME, "type", "id"))); + new UpdateRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - new IndexRequest(SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SECURITY_INDEX_NAME))); + new IndexRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)))); + .addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)))); requests.add( - new Tuple<>(UpdateSettingsAction.NAME, new UpdateSettingsRequest().indices(SECURITY_INDEX_NAME))); + new Tuple<>(UpdateSettingsAction.NAME, new UpdateSettingsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); for (Tuple requestTuple : requests) { String action = requestTuple.v1(); @@ -840,12 +840,12 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { } // we should allow waiting for the health of the index or any index if the user has this permission - ClusterHealthRequest request = new ClusterHealthRequest(SECURITY_INDEX_NAME); + ClusterHealthRequest request = new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME); authorize(authentication, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()}); // multiple indices - request = new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar"); + request = new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "foo", "bar"); authorize(authentication, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()}); verifyNoMoreInteractions(auditTrail); @@ -864,21 +864,21 @@ public void testGrantedNonXPackUserCanExecuteMonitoringOperationsAgainstSecurity ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); List> requests = new ArrayList<>(); - requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); requests.add(new Tuple<>(IndicesShardStoresAction.NAME, - new IndicesShardStoresRequest().indices(SECURITY_INDEX_NAME))); + new IndicesShardStoresRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); requests.add(new Tuple<>(UpgradeStatusAction.NAME, - new UpgradeStatusRequest().indices(SECURITY_INDEX_NAME))); + new UpgradeStatusRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); for (final Tuple requestTuple : requests) { final String action = requestTuple.v1(); @@ -894,7 +894,7 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndex() { ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); @@ -902,26 +902,26 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndex() { List> requests = new ArrayList<>(); requests.add(new Tuple<>(DeleteAction.NAME, - new DeleteRequest(SECURITY_INDEX_NAME, "type", "id"))); + new DeleteRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(SECURITY_INDEX_NAME, DeleteRequest::new))); + createBulkShardRequest(SystemIndicesNames.SECURITY_INDEX_NAME, DeleteRequest::new))); requests.add(new Tuple<>(UpdateAction.NAME, - new UpdateRequest(SECURITY_INDEX_NAME, "type", "id"))); + new UpdateRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndexAction.NAME, - new IndexRequest(SECURITY_INDEX_NAME, "type", "id"))); + new IndexRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(SECURITY_INDEX_NAME, IndexRequest::new))); - requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SECURITY_INDEX_NAME))); + createBulkShardRequest(SystemIndicesNames.SECURITY_INDEX_NAME, IndexRequest::new))); + requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)))); - requests.add(new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(SECURITY_INDEX_NAME))); + .addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)))); + requests.add(new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); requests.add(new Tuple<>(ClusterHealthAction.NAME, - new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar"))); + new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "foo", "bar"))); for (final Tuple requestTuple : requests) { final String action = requestTuple.v1(); @@ -939,7 +939,7 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java index c48ac4568989b..2390677afd85d 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java @@ -20,9 +20,9 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.util.List; import java.util.Set; @@ -85,7 +85,7 @@ public void testSecurityIndicesAreRemovedFromRegularUser() { MetaData metaData = MetaData.builder() .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) - .put(new IndexMetaData.Builder(SecurityIndexManager.SECURITY_INDEX_NAME).settings(indexSettings) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).settings(indexSettings) .numberOfShards(1).numberOfReplicas(0).build(), true) .build(); @@ -101,12 +101,12 @@ public void testSecurityIndicesAreNotRemovedFromSuperUsers() { MetaData metaData = MetaData.builder() .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) - .put(new IndexMetaData.Builder(SecurityIndexManager.SECURITY_INDEX_NAME).settings(indexSettings) + .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).settings(indexSettings) .numberOfShards(1).numberOfReplicas(0).build(), true) .build(); AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, role, SearchAction.NAME, metaData); List list = authorizedIndices.get(); - assertThat(list, containsInAnyOrder("an-index", "another-index", SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(list, containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME)); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java index 83edb189e2935..2430d4f142a61 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java @@ -59,6 +59,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; @@ -66,7 +67,6 @@ import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver.ResolvedIndices; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -81,7 +81,6 @@ import java.util.Map; import java.util.Set; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.contains; @@ -121,7 +120,7 @@ public void setup() { indexNameExpressionResolver = new IndexNameExpressionResolver(); final boolean withAlias = randomBoolean(); - final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + final String securityIndexName = SystemIndicesNames.SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); MetaData metaData = MetaData.builder() .put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar")) .putAlias(AliasMetaData.builder("foounauthorized")).settings(settings)) @@ -1223,14 +1222,14 @@ public void testXPackSecurityUserHasAccessToSecurityIndex() { { final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, hasItem(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(indices, hasItem(SystemIndicesNames.SECURITY_INDEX_NAME)); } { IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); - aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)); + aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, IndicesAliasesAction.NAME); List indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); - assertThat(indices, hasItem(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(indices, hasItem(SystemIndicesNames.SECURITY_INDEX_NAME)); } } @@ -1238,7 +1237,7 @@ public void testXPackUserDoesNotHaveAccessToSecurityIndex() { SearchRequest request = new SearchRequest(); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); } public void testNonXPackUserAccessingSecurityIndex() { @@ -1250,7 +1249,7 @@ public void testNonXPackUserAccessingSecurityIndex() { SearchRequest request = new SearchRequest(); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); } { @@ -1258,7 +1257,7 @@ public void testNonXPackUserAccessingSecurityIndex() { aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*")); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME); List indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); } } 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 c95204ddfdf13..78bd130a824ee 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 @@ -38,6 +38,7 @@ import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheRequest; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.hamcrest.Matchers; import org.junit.After; @@ -123,7 +124,7 @@ public void testGetSinglePrivilegeByName() throws Exception { assertThat(requests, iterableWithSize(1)); assertThat(requests.get(0), instanceOf(GetRequest.class)); GetRequest request = (GetRequest) requests.get(0); - assertThat(request.index(), equalTo(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.index(), equalTo(SystemIndicesNames.SECURITY_INDEX_NAME)); assertThat(request.type(), equalTo("doc")); assertThat(request.id(), equalTo("application-privilege_myapp:admin")); @@ -141,7 +142,7 @@ public void testGetMissingPrivilege() throws Exception { assertThat(requests, iterableWithSize(1)); assertThat(requests.get(0), instanceOf(GetRequest.class)); GetRequest request = (GetRequest) requests.get(0); - assertThat(request.index(), equalTo(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.index(), equalTo(SystemIndicesNames.SECURITY_INDEX_NAME)); assertThat(request.type(), equalTo("doc")); assertThat(request.id(), equalTo("application-privilege_myapp:admin")); @@ -164,7 +165,7 @@ public void testGetPrivilegesByApplicationName() throws Exception { assertThat(requests, iterableWithSize(1)); assertThat(requests.get(0), instanceOf(SearchRequest.class)); SearchRequest request = (SearchRequest) requests.get(0); - assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.indices(), arrayContaining(SystemIndicesNames.SECURITY_INDEX_NAME)); final String query = Strings.toString(request.source().query()); assertThat(query, containsString("{\"terms\":{\"application\":[\"myapp\",\"yourapp\"]")); @@ -191,7 +192,7 @@ public void testGetAllPrivileges() throws Exception { assertThat(requests, iterableWithSize(1)); assertThat(requests.get(0), instanceOf(SearchRequest.class)); SearchRequest request = (SearchRequest) requests.get(0); - assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.indices(), arrayContaining(SystemIndicesNames.SECURITY_INDEX_NAME)); final String query = Strings.toString(request.source().query()); assertThat(query, containsString("{\"term\":{\"type\":{\"value\":\"application-privilege\"")); @@ -227,7 +228,7 @@ public void testPutPrivileges() throws Exception { for (int i = 0; i < putPrivileges.size(); i++) { ApplicationPrivilegeDescriptor privilege = putPrivileges.get(i); IndexRequest request = indexRequests.get(i); - assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.indices(), arrayContaining(SystemIndicesNames.SECURITY_INDEX_NAME)); assertThat(request.type(), equalTo("doc")); assertThat(request.id(), equalTo( "application-privilege_" + privilege.getApplication() + ":" + privilege.getName() @@ -236,7 +237,7 @@ public void testPutPrivileges() throws Exception { assertThat(request.source(), equalTo(BytesReference.bytes(builder))); final boolean created = privilege.getName().equals("user") == false; indexListener.onResponse(new IndexResponse( - new ShardId(SecurityIndexManager.SECURITY_INDEX_NAME, uuid, i), + new ShardId(SystemIndicesNames.SECURITY_INDEX_NAME, uuid, i), request.type(), request.id(), 1, 1, 1, created )); } @@ -272,12 +273,12 @@ public void testDeletePrivileges() throws Exception { for (int i = 0; i < privilegeNames.size(); i++) { String name = privilegeNames.get(i); DeleteRequest request = deletes.get(i); - assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); + assertThat(request.indices(), arrayContaining(SystemIndicesNames.SECURITY_INDEX_NAME)); assertThat(request.type(), equalTo("doc")); assertThat(request.id(), equalTo("application-privilege_app1:" + name)); final boolean found = name.equals("p2") == false; deleteListener.onResponse(new DeleteResponse( - new ShardId(SecurityIndexManager.SECURITY_INDEX_NAME, uuid, i), + new ShardId(SystemIndicesNames.SECURITY_INDEX_NAME, uuid, i), request.type(), request.id(), 1, 1, 1, found )); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java index 0cd44e32e3c3d..d30751a90cbf2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java @@ -42,6 +42,7 @@ import org.elasticsearch.xpack.core.security.action.role.PutRoleRequest; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.junit.After; @@ -56,7 +57,6 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; @@ -188,7 +188,7 @@ public void testPutOfRoleWithFlsDlsUnlicensed() throws IOException { final XPackLicenseState licenseState = mock(XPackLicenseState.class); final AtomicBoolean methodCalled = new AtomicBoolean(false); final SecurityIndexManager securityIndex = - new SecurityIndexManager(client, SecurityIndexManager.SECURITY_INDEX_NAME, clusterService); + new SecurityIndexManager(client, SystemIndicesNames.SECURITY_INDEX_NAME, clusterService); final NativeRolesStore rolesStore = new NativeRolesStore(Settings.EMPTY, client, licenseState, securityIndex) { @Override void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener listener) { @@ -248,7 +248,7 @@ void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final private ClusterState getClusterStateWithSecurityIndex() { final boolean withAlias = randomBoolean(); - final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + final String securityIndexName = SystemIndicesNames.SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); Settings settings = Settings.builder() .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) 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 0741d1c04e995..f8914893c737a 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 @@ -47,11 +47,11 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.test.SecurityTestUtils; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.template.TemplateUtils; import org.hamcrest.Matchers; import org.junit.Before; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN; import static org.hamcrest.Matchers.equalTo; @@ -328,8 +328,8 @@ public void testMissingVersionMappingThrowsError() throws IOException { ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); final ClusterState clusterState = clusterStateBuilder.build(); IllegalStateException exception = expectThrows(IllegalStateException.class, - () -> SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); - assertEquals("Cannot read security-version string in index " + SECURITY_INDEX_NAME, exception.getMessage()); + () -> SecurityIndexManager.checkIndexMappingVersionMatches(SystemIndicesNames.SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); + assertEquals("Cannot read security-version string in index " + SystemIndicesNames.SECURITY_INDEX_NAME, exception.getMessage()); } public void testIndexTemplateIsIdentifiedAsUpToDate() throws IOException { @@ -386,7 +386,7 @@ private ClusterState.Builder createClusterStateWithTemplate(String securityTempl private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException { final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build(); final String indexName = clusterState.metaData().getAliasAndIndexLookup() - .get(SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); + .get(SystemIndicesNames.SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); return ClusterState.builder(clusterState).routingTable(SecurityTestUtils.buildIndexRoutingTable(indexName)); } @@ -420,7 +420,7 @@ private static IndexMetaData.Builder createIndexMetadata(String indexName, Strin private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException { final MetaData.Builder metaDataBuilder = new MetaData.Builder(); final boolean withAlias = randomBoolean(); - final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + final String securityIndexName = SystemIndicesNames.SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate)); ClusterState.Builder clusterStateBuilder = ClusterState.builder(state()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java index 12474b7a04d59..fddb0535a049c 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java @@ -19,6 +19,7 @@ import org.elasticsearch.index.Index; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import java.io.IOException; import java.io.OutputStream; @@ -35,7 +36,6 @@ import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; -import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; public class SecurityTestUtils { @@ -83,7 +83,7 @@ public static RoutingTable buildIndexRoutingTable(String indexName) { * Adds the index alias {@code .security} to the underlying concrete index. */ public static MetaData addAliasToMetaData(MetaData metaData, String indexName) { - AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_INDEX_NAME).build(); + AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SystemIndicesNames.SECURITY_INDEX_NAME).build(); MetaData.Builder metaDataBuilder = new MetaData.Builder(metaData); IndexMetaData indexMetaData = metaData.index(indexName); metaDataBuilder.put(IndexMetaData.builder(indexMetaData).putAlias(aliasMetaData)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java index e7b31d88eda19..624d315f50afc 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java @@ -10,10 +10,9 @@ import org.elasticsearch.action.search.SearchAction; import org.elasticsearch.action.update.UpdateAction; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.XPackUser; import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; -import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.hamcrest.Matchers; import org.joda.time.DateTime; @@ -31,8 +30,8 @@ public void testXPackUserCanAccessNonSecurityIndices() { public void testXPackUserCannotAccessSecurityIndex() { final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME); final Predicate predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); - assertThat(predicate.test(SecurityIndexManager.SECURITY_INDEX_NAME), Matchers.is(false)); - assertThat(predicate.test(SecurityIndexManager.INTERNAL_SECURITY_INDEX), Matchers.is(false)); + assertThat(predicate.test(SystemIndicesNames.SECURITY_INDEX_NAME), Matchers.is(false)); + assertThat(predicate.test(SystemIndicesNames.INTERNAL_SECURITY_INDEX), Matchers.is(false)); } public void testXPackUserCanReadAuditTrail() { @@ -50,6 +49,6 @@ public void testXPackUserCannotWriteToAuditTrail() { private String getAuditLogName() { final DateTime date = new DateTime().plusDays(randomIntBetween(1, 360)); final IndexNameResolver.Rollover rollover = randomFrom(IndexNameResolver.Rollover.values()); - return IndexNameResolver.resolve(IndexAuditTrailField.INDEX_NAME_PREFIX, date, rollover); + return IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, date, rollover); } } \ No newline at end of file From c12fa0e015c528962494332ea63059100211bd44 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 11:45:24 +0200 Subject: [PATCH 02/20] getting there --- .../authz/permission/IndicesPermission.java | 26 ++++++++++++++----- .../security/index/SystemIndicesNames.java | 17 +++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 4936071ee8445..c2738d6a8eeae 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -17,6 +17,7 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.Automatons; import java.util.ArrayList; @@ -63,11 +64,23 @@ public IndicesPermission(Group... groups) { }; } + private static boolean isIndexPattern(String indexPattern) { + if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { + return true; + } + return false; + } + + private static boolean isOrdinaryIndex(String index) { + assert false == isIndexPattern(index); + return false == SystemIndicesNames.indexNames().contains(index); + } + static Predicate indexMatcher(List indices) { Set exactMatch = new HashSet<>(); List nonExactMatch = new ArrayList<>(); for (String indexPattern : indices) { - if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { + if (isIndexPattern(indexPattern)) { nonExactMatch.add(indexPattern); } else { exactMatch.add(indexPattern); @@ -95,7 +108,7 @@ private static Predicate buildExactMatchPredicate(Set indices) { private static Predicate buildAutomataPredicate(List indices) { try { - return Automatons.predicate(indices); + return Automatons.predicate(indices).and(index -> isOrdinaryIndex(index)); } catch (TooComplexToDeterminizeException e) { LogManager.getLogger(IndicesPermission.class).debug("Index pattern automaton [{}] is too complex", indices); String description = Strings.collectionToCommaDelimitedString(indices); @@ -232,11 +245,6 @@ public static class Group { private final Predicate actionMatcher; private final String[] indices; private final Predicate indexNameMatcher; - - public FieldPermissions getFieldPermissions() { - return fieldPermissions; - } - private final FieldPermissions fieldPermissions; private final Set query; @@ -258,6 +266,10 @@ public String[] indices() { return indices; } + public FieldPermissions getFieldPermissions() { + return fieldPermissions; + } + @Nullable public Set getQuery() { return query; diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java index fa8b51e2681ab..9d2680c9343c3 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/index/SystemIndicesNames.java @@ -8,26 +8,29 @@ import org.elasticsearch.xpack.core.upgrade.IndexUpgradeCheckVersion; -import java.util.Arrays; import java.util.Collections; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public final class SystemIndicesNames { public static final String AUDIT_INDEX_NAME_PREFIX = ".security_audit_log"; public static final String INTERNAL_SECURITY_INDEX = ".security-" + IndexUpgradeCheckVersion.UPRADE_VERSION; public static final String SECURITY_INDEX_NAME = ".security"; - private static final List index_names; + private static final Set index_names; static { - index_names = Collections.unmodifiableList(Arrays.asList(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)); + Set indexNames = new HashSet<>(); + indexNames.add(SECURITY_INDEX_NAME); + indexNames.add(INTERNAL_SECURITY_INDEX); + index_names = Collections.unmodifiableSet(indexNames); } - private SystemIndicesNames() { + public static Set indexNames() { + return index_names; } - public static List indexNames() { - return index_names; + private SystemIndicesNames() { } } From 59ff695744ba37de4bf086ab846ae457f3a60586 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 11:59:05 +0200 Subject: [PATCH 03/20] HashCode and trimms --- .../authz/permission/IndicesPermission.java | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index c2738d6a8eeae..4d0f0ada43edb 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -31,7 +32,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; +import java.util.concurrent.ConcurrentMap; import java.util.function.Predicate; import static java.util.Collections.unmodifiableMap; @@ -45,23 +46,12 @@ public final class IndicesPermission implements Iterable> loadingFunction; - - private final ConcurrentHashMap> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); + private final ConcurrentMap> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); private final Group[] groups; public IndicesPermission(Group... groups) { this.groups = groups; - loadingFunction = (action) -> { - List indices = new ArrayList<>(); - for (Group group : groups) { - if (group.actionMatcher.test(action)) { - indices.addAll(Arrays.asList(group.indices)); - } - } - return indexMatcher(indices); - }; } private static boolean isIndexPattern(String indexPattern) { @@ -76,7 +66,7 @@ private static boolean isOrdinaryIndex(String index) { return false == SystemIndicesNames.indexNames().contains(index); } - static Predicate indexMatcher(List indices) { + static Predicate indexMatcher(Collection indices) { Set exactMatch = new HashSet<>(); List nonExactMatch = new ArrayList<>(); for (String indexPattern : indices) { @@ -124,7 +114,7 @@ public Iterator iterator() { return Arrays.asList(groups).iterator(); } - public Group[] groups() { + Group[] groups() { return groups; } @@ -133,7 +123,15 @@ public Group[] groups() { * has the privilege for executing the given action on. */ public Predicate allowedIndicesMatcher(String action) { - return allowedIndicesMatchersForAction.computeIfAbsent(action, loadingFunction); + return allowedIndicesMatchersForAction.computeIfAbsent(action, (theAction) -> { + List indices = new ArrayList<>(); + for (Group group : groups) { + if (group.check(theAction)) { + indices.addAll(Arrays.asList(group.indices)); + } + } + return indexMatcher(indices); + }); } /** @@ -287,6 +285,24 @@ private boolean check(String action, String index) { boolean hasQuery() { return query != null; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Group that = (Group) o; + + return Objects.equals(privilege, that.privilege()) + && Arrays.equals(indices, that.indices()) + && Objects.equals(fieldPermissions, that.fieldPermissions) + && Objects.equals(query, that.query); + } + + @Override + public int hashCode() { + return Objects.hash(privilege, indices, fieldPermissions, query); + } } private static class DocumentLevelPermissions { From 536640d5617f2091a343716452fc3d1e4806f81c Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 13:57:02 +0200 Subject: [PATCH 04/20] HasPrivilege --- .../authz/permission/IndicesPermission.java | 78 +++++++++++++++++-- .../user/TransportHasPrivilegesAction.java | 33 +------- 2 files changed, 72 insertions(+), 39 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 4d0f0ada43edb..1ed3091be6524 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -6,7 +6,9 @@ package org.elasticsearch.xpack.core.security.authz.permission; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.apache.lucene.util.automaton.Automaton; +import org.apache.lucene.util.automaton.Operations; import org.apache.lucene.util.automaton.TooComplexToDeterminizeException; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.cluster.metadata.AliasOrIndex; @@ -23,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -46,12 +49,16 @@ public final class IndicesPermission implements Iterable> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); + private static final Logger logger = LogManager.getLogger(); + private final ConcurrentMap> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); + private final ConcurrentMap indexGroupAutomatonCache = new ConcurrentHashMap<>(); private final Group[] groups; + private final Automaton systemIndicesAutomaton; public IndicesPermission(Group... groups) { this.groups = groups; + this.systemIndicesAutomaton = Automatons.patterns(SystemIndicesNames.indexNames()); } private static boolean isIndexPattern(String indexPattern) { @@ -66,7 +73,7 @@ private static boolean isOrdinaryIndex(String index) { return false == SystemIndicesNames.indexNames().contains(index); } - static Predicate indexMatcher(Collection indices) { + private static Predicate indexMatcherPredicate(Collection indices) { Set exactMatch = new HashSet<>(); List nonExactMatch = new ArrayList<>(); for (String indexPattern : indices) { @@ -88,6 +95,31 @@ static Predicate indexMatcher(Collection indices) { } } + private Automaton indexMatcherAutomaton(String... indices) { + final List exactMatch = new ArrayList<>(); + final List patternMatch = new ArrayList<>(); + for (String indexPattern : indices) { + if (isIndexPattern(indexPattern)) { + patternMatch.add(indexPattern); + } else { + exactMatch.add(indexPattern); + } + } + try { + final Automaton exactMatchAutomaton = Automatons.patterns(exactMatch); + final Automaton indexPatternAutomaton = Automatons.patterns(patternMatch); + return Automatons.unionAndMinimize( + Arrays.asList(exactMatchAutomaton, Automatons.minusAndMinimize(indexPatternAutomaton, systemIndicesAutomaton))); + } catch (TooComplexToDeterminizeException e) { + logger.debug("Index pattern automaton [{}] is too complex", Strings.arrayToCommaDelimitedString(indices)); + String description = Strings.arrayToCommaDelimitedString(indices); + if (description.length() > 80) { + description = Strings.cleanTruncate(description, 80) + "..."; + } + throw new ElasticsearchSecurityException("The set of permitted index patterns [{}] is too complex to evaluate", e, description); + } + } + private static Predicate buildExactMatchPredicate(Set indices) { if (indices.size() == 1) { final String singleValue = indices.iterator().next(); @@ -96,17 +128,30 @@ private static Predicate buildExactMatchPredicate(Set indices) { return indices::contains; } - private static Predicate buildAutomataPredicate(List indices) { + private static Predicate buildAutomataPredicate(final Collection indices) { + final Predicate indicesPredicate; try { - return Automatons.predicate(indices).and(index -> isOrdinaryIndex(index)); + indicesPredicate = Automatons.predicate(indices); } catch (TooComplexToDeterminizeException e) { - LogManager.getLogger(IndicesPermission.class).debug("Index pattern automaton [{}] is too complex", indices); + logger.debug("Index pattern automaton [{}] is too complex", indices); String description = Strings.collectionToCommaDelimitedString(indices); if (description.length() > 80) { description = Strings.cleanTruncate(description, 80) + "..."; } throw new ElasticsearchSecurityException("The set of permitted index patterns [{}] is too complex to evaluate", e, description); } + return (index) -> { + if (indicesPredicate.test(index)) { + if (isOrdinaryIndex(index)) { + return true; + } else { + logger.debug("Index pattern automaton [{}] cannot match system indices [{}]", indices, SystemIndicesNames.indexNames()); + return false; + } + } else { + return false; + } + }; } @Override @@ -114,6 +159,7 @@ public Iterator iterator() { return Arrays.asList(groups).iterator(); } + // package-private for testing Group[] groups() { return groups; } @@ -130,7 +176,7 @@ public Predicate allowedIndicesMatcher(String action) { indices.addAll(Arrays.asList(group.indices)); } } - return indexMatcher(indices); + return indexMatcherPredicate(indices); }); } @@ -159,6 +205,24 @@ public Automaton allowedActionsMatcher(String index) { return automatonList.isEmpty() ? Automatons.EMPTY : Automatons.unionAndMinimize(automatonList); } + public boolean testIndexMatch(String checkIndex, String checkPrivilegeName) { + final Automaton checkIndexAutomaton = indexMatcherAutomaton(checkIndex); + final List privilegeAutomatons = new ArrayList<>(); + for (IndicesPermission.Group group : groups) { + final Automaton groupIndexAutomaton = indexGroupAutomatonCache.computeIfAbsent(group, + theGroup -> indexMatcherAutomaton(theGroup.indices())); + if (Operations.subsetOf(checkIndexAutomaton, groupIndexAutomaton)) { + final IndexPrivilege rolePrivilege = group.privilege(); + if (rolePrivilege.name().contains(checkPrivilegeName)) { + return true; + } + privilegeAutomatons.add(rolePrivilege.getAutomaton()); + } + } + final IndexPrivilege checkPrivilege = IndexPrivilege.get(Collections.singleton(checkPrivilegeName)); + return Operations.subsetOf(checkPrivilege.getAutomaton(), Automatons.unionAndMinimize(privilegeAutomatons)); + } + /** * Authorizes the provided action against the provided indices, given the current cluster metadata */ @@ -251,7 +315,7 @@ public Group(IndexPrivilege privilege, FieldPermissions fieldPermissions, @Nulla this.privilege = privilege; this.actionMatcher = privilege.predicate(); this.indices = indices; - this.indexNameMatcher = indexMatcher(Arrays.asList(indices)); + this.indexNameMatcher = indexMatcherPredicate(Arrays.asList(indices)); this.fieldPermissions = Objects.requireNonNull(fieldPermissions); this.query = query; } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java index 20fa9f522e710..1640aae06852b 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java @@ -21,25 +21,20 @@ import org.elasticsearch.xpack.core.security.action.user.HasPrivilegesResponse; import org.elasticsearch.xpack.core.security.authc.Authentication; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; -import org.elasticsearch.xpack.core.security.authz.permission.IndicesPermission; import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; -import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.Privilege; -import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.store.NativePrivilegeStore; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -111,8 +106,6 @@ private void checkPrivileges(HasPrivilegesRequest request, Role userRole, } boolean allMatch = cluster.values().stream().allMatch(Boolean::booleanValue); - final Map predicateCache = new HashMap<>(); - final Map indices = new LinkedHashMap<>(); for (RoleDescriptor.IndicesPrivileges check : request.indexPrivileges()) { for (String index : check.getIndices()) { @@ -122,7 +115,7 @@ private void checkPrivileges(HasPrivilegesRequest request, Role userRole, privileges.putAll(existing.getPrivileges()); } for (String privilege : check.getPrivileges()) { - if (testIndexMatch(index, privilege, userRole, predicateCache)) { + if (userRole.indices().testIndexMatch(index, privilege)) { logger.debug(() -> new ParameterizedMessage("Role [{}] has [{}] on index [{}]", Strings.arrayToCommaDelimitedString(userRole.names()), privilege, index)); privileges.put(privilege, true); @@ -171,30 +164,6 @@ private void checkPrivileges(HasPrivilegesRequest request, Role userRole, listener.onResponse(new HasPrivilegesResponse(request.username(), allMatch, cluster, indices.values(), privilegesByApplication)); } - private boolean testIndexMatch(String checkIndex, String checkPrivilegeName, Role userRole, - Map predicateCache) { - final IndexPrivilege checkPrivilege = IndexPrivilege.get(Collections.singleton(checkPrivilegeName)); - - final Automaton checkIndexAutomaton = Automatons.patterns(checkIndex); - - List privilegeAutomatons = new ArrayList<>(); - for (IndicesPermission.Group group : userRole.indices().groups()) { - final Automaton groupIndexAutomaton = predicateCache.computeIfAbsent(group, g -> Automatons.patterns(g.indices())); - if (testIndex(checkIndexAutomaton, groupIndexAutomaton)) { - final IndexPrivilege rolePrivilege = group.privilege(); - if (rolePrivilege.name().contains(checkPrivilegeName)) { - return true; - } - privilegeAutomatons.add(rolePrivilege.getAutomaton()); - } - } - return testPrivilege(checkPrivilege, Automatons.unionAndMinimize(privilegeAutomatons)); - } - - private static boolean testIndex(Automaton checkIndex, Automaton roleIndex) { - return Operations.subsetOf(checkIndex, roleIndex); - } - private static boolean testPrivilege(Privilege checkPrivilege, Automaton roleAutomaton) { return Operations.subsetOf(checkPrivilege.getAutomaton(), roleAutomaton); } From 4ee6cbd4906fb1d7915bb37359db2216eb6b1ef4 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 14:08:10 +0200 Subject: [PATCH 05/20] Husling --- .../authz/permission/IndicesPermission.java | 34 ++++++++----------- .../TransportGetUserPrivilegesAction.java | 2 +- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 1ed3091be6524..005d9481c5b5b 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -45,7 +45,7 @@ * A permission that is based on privileges for index related actions executed * on specific indices */ -public final class IndicesPermission implements Iterable { +public final class IndicesPermission { public static final IndicesPermission NONE = new IndicesPermission(); @@ -61,18 +61,6 @@ public IndicesPermission(Group... groups) { this.systemIndicesAutomaton = Automatons.patterns(SystemIndicesNames.indexNames()); } - private static boolean isIndexPattern(String indexPattern) { - if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { - return true; - } - return false; - } - - private static boolean isOrdinaryIndex(String index) { - assert false == isIndexPattern(index); - return false == SystemIndicesNames.indexNames().contains(index); - } - private static Predicate indexMatcherPredicate(Collection indices) { Set exactMatch = new HashSet<>(); List nonExactMatch = new ArrayList<>(); @@ -154,13 +142,7 @@ private static Predicate buildAutomataPredicate(final Collection }; } - @Override - public Iterator iterator() { - return Arrays.asList(groups).iterator(); - } - - // package-private for testing - Group[] groups() { + public Group[] groups() { return groups; } @@ -302,6 +284,18 @@ public Map authorize(String act return unmodifiableMap(indexPermissions); } + private static boolean isIndexPattern(String indexPattern) { + if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { + return true; + } + return false; + } + + private static boolean isOrdinaryIndex(String index) { + assert false == isIndexPattern(index); + return false == SystemIndicesNames.indexNames().contains(index); + } + public static class Group { private final IndexPrivilege privilege; private final Predicate actionMatcher; diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java index 518c9cb25a01a..f2193a9ec9917 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java @@ -90,7 +90,7 @@ GetUserPrivilegesResponse buildResponseObject(Role userRole) { } final Set indices = new LinkedHashSet<>(); - for (IndicesPermission.Group group : userRole.indices()) { + for (IndicesPermission.Group group : userRole.indices().groups()) { final Set queries = group.getQuery() == null ? Collections.emptySet() : group.getQuery(); final Set fieldSecurity = group.getFieldPermissions().hasFieldLevelSecurity() ? group.getFieldPermissions().getFieldPermissionsDefinition().getFieldGrantExcludeGroups() : Collections.emptySet(); From ac9ec5ab8c21f8d215565df543fd626f821ad39f Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 14:29:11 +0200 Subject: [PATCH 06/20] ReservedRolesStore --- .../core/security/authz/store/ReservedRolesStore.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java index 046cf59254957..edca566f044b2 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivileges.ManageApplicationPrivileges; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.MetadataUtils; import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.UsernamesField; @@ -32,7 +33,9 @@ public class ReservedRolesStore implements BiConsumer, ActionListene public static final RoleDescriptor SUPERUSER_ROLE_DESCRIPTOR = new RoleDescriptor("superuser", new String[] { "all" }, new RoleDescriptor.IndicesPrivileges[] { - RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build()}, + RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build(), + RoleDescriptor.IndicesPrivileges.builder().indices(SystemIndicesNames.indexNames().toArray(new String[0])) + .privileges("all").build() }, new RoleDescriptor.ApplicationResourcePrivileges[] { RoleDescriptor.ApplicationResourcePrivileges.builder().application("*").privileges("*").resources("*").build() }, @@ -45,7 +48,9 @@ private static Map initializeReservedRoles() { return MapBuilder.newMapBuilder() .put("superuser", new RoleDescriptor("superuser", new String[] { "all" }, new RoleDescriptor.IndicesPrivileges[] { - RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build()}, + RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build(), + RoleDescriptor.IndicesPrivileges.builder().indices(SystemIndicesNames.indexNames().toArray(new String[0])) + .privileges("all").build() }, new String[] { "*" }, MetadataUtils.DEFAULT_RESERVED_METADATA)) .put("transport_client", new RoleDescriptor("transport_client", new String[] { "transport_client" }, null, null, @@ -83,6 +88,8 @@ private static Map initializeReservedRoles() { }, new RoleDescriptor.IndicesPrivileges[] { RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("monitor").build(), + RoleDescriptor.IndicesPrivileges.builder().indices(SystemIndicesNames.indexNames().toArray(new String[0])) + .privileges("monitor").build(), RoleDescriptor.IndicesPrivileges.builder().indices(".kibana*").privileges("read").build() }, null, From c8069700595332d4ea2455c8362de42d1b13de7e Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 18 Dec 2018 20:14:01 +0200 Subject: [PATCH 07/20] Trimming --- .../authz/permission/IndicesPermission.java | 24 +++++++++---------- .../TransportGetUserPrivilegesAction.java | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 005d9481c5b5b..33093da411b36 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -129,12 +128,13 @@ private static Predicate buildAutomataPredicate(final Collection throw new ElasticsearchSecurityException("The set of permitted index patterns [{}] is too complex to evaluate", e, description); } return (index) -> { + assert false == isIndexPattern(index); if (indicesPredicate.test(index)) { - if (isOrdinaryIndex(index)) { - return true; - } else { + if (isSystemIndex(index)) { logger.debug("Index pattern automaton [{}] cannot match system indices [{}]", indices, SystemIndicesNames.indexNames()); return false; + } else { + return true; } } else { return false; @@ -285,15 +285,11 @@ public Map authorize(String act } private static boolean isIndexPattern(String indexPattern) { - if (indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?")) { - return true; - } - return false; + return indexPattern.startsWith("/") || indexPattern.contains("*") || indexPattern.contains("?"); } - private static boolean isOrdinaryIndex(String index) { - assert false == isIndexPattern(index); - return false == SystemIndicesNames.indexNames().contains(index); + private static boolean isSystemIndex(String index) { + return SystemIndicesNames.indexNames().contains(index); } public static class Group { @@ -314,10 +310,14 @@ public Group(IndexPrivilege privilege, FieldPermissions fieldPermissions, @Nulla this.query = query; } - public IndexPrivilege privilege() { + private IndexPrivilege privilege() { return privilege; } + public Set privilegeName() { + return privilege.name(); + } + public String[] indices() { return indices; } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java index f2193a9ec9917..9e7f372fb668c 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java @@ -96,7 +96,7 @@ GetUserPrivilegesResponse buildResponseObject(Role userRole) { ? group.getFieldPermissions().getFieldPermissionsDefinition().getFieldGrantExcludeGroups() : Collections.emptySet(); indices.add(new GetUserPrivilegesResponse.Indices( Arrays.asList(group.indices()), - group.privilege().name(), + group.privilegeName(), fieldSecurity, queries )); From c7f7f2b0621eb3fc0bd189b32ada5dc422b53f27 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 16:24:32 +0200 Subject: [PATCH 08/20] AuthorizedIndices remove hack + tests --- .../authz/store/ReservedRolesStore.java | 8 +- .../authz/store/ReservedRolesStoreTests.java | 94 ++++++++++++++++++- .../security/authz/AuthorizationService.java | 2 +- .../security/authz/AuthorizedIndices.java | 55 ++++------- .../authz/AuthorizedIndicesTests.java | 68 ++++++++++---- 5 files changed, 161 insertions(+), 66 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java index 5541d15d9dddf..e19a169e24238 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStore.java @@ -46,13 +46,7 @@ public class ReservedRolesStore implements BiConsumer, ActionListene private static Map initializeReservedRoles() { return MapBuilder.newMapBuilder() - .put("superuser", new RoleDescriptor("superuser", new String[] { "all" }, - new RoleDescriptor.IndicesPrivileges[] { - RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges("all").build(), - RoleDescriptor.IndicesPrivileges.builder().indices(SystemIndicesNames.indexNames().toArray(new String[0])) - .privileges("all").build() }, - new String[] { "*" }, - MetadataUtils.DEFAULT_RESERVED_METADATA)) + .put("superuser", SUPERUSER_ROLE_DESCRIPTOR) .put("transport_client", new RoleDescriptor("transport_client", new String[] { "transport_client" }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) .put("kibana_user", new RoleDescriptor("kibana_user", null, new RoleDescriptor.IndicesPrivileges[] { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java index fc9869a12803f..bac8569bab4b2 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java @@ -15,10 +15,15 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction; import org.elasticsearch.action.admin.indices.get.GetIndexAction; import org.elasticsearch.action.admin.indices.recovery.RecoveryAction; +import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsAction; +import org.elasticsearch.action.admin.indices.settings.get.GetSettingsAction; import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsAction; +import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresAction; +import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction; import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateAction; import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction; +import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusAction; import org.elasticsearch.action.bulk.BulkAction; import org.elasticsearch.action.delete.DeleteAction; import org.elasticsearch.action.get.GetAction; @@ -95,6 +100,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.LogstashSystemUser; @@ -178,6 +184,9 @@ public void testIngestAdminRole() { is(false)); assertThat(ingestAdminRole.indices().allowedIndicesMatcher(GetAction.NAME).test(randomAlphaOfLengthBetween(8, 24)), is(false)); + + assertNoAccessAllowed(ingestAdminRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(ingestAdminRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testKibanaSystemRole() { @@ -277,6 +286,9 @@ public void testKibanaSystemRole() { assertThat(kibanaRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); assertThat(kibanaRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(true)); assertThat(kibanaRole.indices().allowedIndicesMatcher(READ_CROSS_CLUSTER_NAME).test(index), is(false)); + + assertNoAccessAllowed(kibanaRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(kibanaRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testKibanaUserRole() { @@ -326,6 +338,9 @@ public void testKibanaUserRole() { final String applicationWithRandomIndex = "kibana-.kibana_" + randomAlphaOfLengthBetween(8, 24); assertThat(kibanaUserRole.application().grants(new ApplicationPrivilege(applicationWithRandomIndex, "app-random-index", "all"), "*"), is(false)); + + assertNoAccessAllowed(kibanaUserRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(kibanaUserRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testMonitoringUserRole() { @@ -367,6 +382,9 @@ public void testMonitoringUserRole() { assertThat(monitoringUserRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); assertThat(monitoringUserRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(true)); assertThat(monitoringUserRole.indices().allowedIndicesMatcher(READ_CROSS_CLUSTER_NAME).test(index), is(true)); + + assertNoAccessAllowed(monitoringUserRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(monitoringUserRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testRemoteMonitoringAgentRole() { @@ -424,7 +442,9 @@ public void testRemoteMonitoringAgentRole() { assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(metricbeatIndex), is(false)); assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(metricbeatIndex), is(false)); assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetAction.NAME).test(metricbeatIndex), is(false)); - + + assertNoAccessAllowed(remoteMonitoringAgentRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(remoteMonitoringAgentRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testRemoteMonitoringCollectorRole() { @@ -454,6 +474,27 @@ public void testRemoteMonitoringCollectorRole() { assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetAction.NAME).test(".kibana"), is(true)); assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher("indices:foo") .test(randomAlphaOfLengthBetween(8, 24)), is(false)); + + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetSettingsAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(IndicesShardStoresAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(UpgradeStatusAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(RecoveryAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(IndicesStatsAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(IndicesSegmentsAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(true)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(SearchAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(false)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(false)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(DeleteAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(false)); + assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(IndexAction.NAME) + .test(randomFrom(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME)), is(false)); Arrays.asList( ".monitoring-" + randomAlphaOfLength(randomIntBetween(0, 13)), @@ -471,6 +512,9 @@ public void testRemoteMonitoringCollectorRole() { assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(false)); assertThat(remoteMonitoringAgentRole.indices().allowedIndicesMatcher(GetIndexAction.NAME).test(index), is(false)); }); + + assertNoAccessAllowed(remoteMonitoringAgentRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(remoteMonitoringAgentRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testReportingUserRole() { @@ -509,6 +553,9 @@ public void testReportingUserRole() { assertThat(reportingUserRole.indices().allowedIndicesMatcher(UpdateAction.NAME).test(index), is(false)); assertThat(reportingUserRole.indices().allowedIndicesMatcher(DeleteAction.NAME).test(index), is(false)); assertThat(reportingUserRole.indices().allowedIndicesMatcher(BulkAction.NAME).test(index), is(false)); + + assertNoAccessAllowed(reportingUserRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(reportingUserRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testKibanaDashboardOnlyUserRole() { @@ -554,6 +601,9 @@ public void testKibanaDashboardOnlyUserRole() { final String applicationWithRandomIndex = "kibana-.kibana_" + randomAlphaOfLengthBetween(8, 24); assertThat(dashboardsOnlyUserRole.application().grants( new ApplicationPrivilege(applicationWithRandomIndex, "app-random-index", "all"), "*"), is(false)); + + assertNoAccessAllowed(dashboardsOnlyUserRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(dashboardsOnlyUserRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testSuperuserRole() { @@ -577,6 +627,12 @@ public void testSuperuserRole() { .put(new IndexMetaData.Builder("a2").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("aaaaaa").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("bbbbb").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) + .put(new IndexMetaData.Builder(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).build()) + .build(), true) .put(new IndexMetaData.Builder("b") .settings(indexSettings) .numberOfShards(1) @@ -601,10 +657,19 @@ public void testSuperuserRole() { .authorize(UpdateSettingsAction.NAME, Sets.newHashSet("aaaaaa", "ba"), metaData, fieldPermissionsCache); assertThat(authzMap.get("aaaaaa").isGranted(), is(true)); assertThat(authzMap.get("b").isGranted(), is(true)); + authzMap = superuserRole.indices().authorize(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME), + Sets.newHashSet(SystemIndicesNames.SECURITY_INDEX_NAME), metaData, fieldPermissionsCache); + assertThat(authzMap.get(SystemIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); + assertThat(authzMap.get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).isGranted(), is(true)); assertTrue(superuserRole.indices().check(SearchAction.NAME)); assertFalse(superuserRole.indices().check("unknown")); assertThat(superuserRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(true)); + + assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME)) + .test(SystemIndicesNames.SECURITY_INDEX_NAME), is(true)); + assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME)) + .test(SystemIndicesNames.INTERNAL_SECURITY_INDEX), is(true)); } public void testLogstashSystemRole() { @@ -629,6 +694,9 @@ public void testLogstashSystemRole() { assertThat(logstashSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(".reporting"), is(false)); assertThat(logstashSystemRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), is(false)); + + assertNoAccessAllowed(logstashSystemRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(logstashSystemRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testBeatsAdminRole() { @@ -665,6 +733,9 @@ public void testBeatsAdminRole() { assertThat(beatsAdminRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); assertThat(beatsAdminRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); assertThat(beatsAdminRole.indices().allowedIndicesMatcher(GetAction.NAME).test(index), is(true)); + + assertNoAccessAllowed(beatsAdminRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(beatsAdminRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testBeatsSystemRole() { @@ -689,6 +760,9 @@ public void testBeatsSystemRole() { assertThat(logstashSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(".reporting"), is(false)); assertThat(logstashSystemRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), is(false)); + + assertNoAccessAllowed(logstashSystemRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(logstashSystemRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testAPMSystemRole() { @@ -713,6 +787,9 @@ public void testAPMSystemRole() { assertThat(APMSystemRole.indices().allowedIndicesMatcher(IndexAction.NAME).test(".reporting"), is(false)); assertThat(APMSystemRole.indices().allowedIndicesMatcher("indices:foo").test(randomAlphaOfLengthBetween(8, 24)), is(false)); + + assertNoAccessAllowed(APMSystemRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(APMSystemRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testMachineLearningAdminRole() { @@ -765,6 +842,9 @@ public void testMachineLearningAdminRole() { assertOnlyReadAllowed(role, AnomalyDetectorsIndex.jobStateIndexName()); assertOnlyReadAllowed(role, AnomalyDetectorsIndexFields.RESULTS_INDEX_PREFIX + AnomalyDetectorsIndexFields.RESULTS_INDEX_DEFAULT); assertOnlyReadAllowed(role, AuditorField.NOTIFICATIONS_INDEX); + + assertNoAccessAllowed(role, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(role, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testMachineLearningUserRole() { @@ -817,6 +897,9 @@ public void testMachineLearningUserRole() { assertNoAccessAllowed(role, AnomalyDetectorsIndex.jobStateIndexName()); assertOnlyReadAllowed(role, AnomalyDetectorsIndexFields.RESULTS_INDEX_PREFIX + AnomalyDetectorsIndexFields.RESULTS_INDEX_DEFAULT); assertOnlyReadAllowed(role, AuditorField.NOTIFICATIONS_INDEX); + + assertNoAccessAllowed(role, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(role, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testWatcherAdminRole() { @@ -844,6 +927,9 @@ public void testWatcherAdminRole() { for (String index : new String[]{ Watch.INDEX, historyIndex, TriggeredWatchStoreField.INDEX_NAME }) { assertOnlyReadAllowed(role, index); } + + assertNoAccessAllowed(role, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(role, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } public void testWatcherUserRole() { @@ -872,6 +958,9 @@ public void testWatcherUserRole() { for (String index : new String[]{ Watch.INDEX, historyIndex }) { assertOnlyReadAllowed(role, index); } + + assertNoAccessAllowed(role, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(role, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } private void assertOnlyReadAllowed(Role role, String index) { @@ -929,5 +1018,8 @@ public void testLogstashAdminRole() { assertThat(logstashAdminRole.indices().allowedIndicesMatcher(SearchAction.NAME).test(index), is(true)); assertThat(logstashAdminRole.indices().allowedIndicesMatcher(MultiSearchAction.NAME).test(index), is(true)); assertThat(logstashAdminRole.indices().allowedIndicesMatcher(UpdateSettingsAction.NAME).test(index), is(true)); + + assertNoAccessAllowed(logstashAdminRole, SystemIndicesNames.SECURITY_INDEX_NAME); + assertNoAccessAllowed(logstashAdminRole, SystemIndicesNames.INTERNAL_SECURITY_INDEX); } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 848525e43696e..900851f5a88e7 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -290,7 +290,7 @@ public void authorize(Authentication authentication, String action, TransportReq } final MetaData metaData = clusterService.state().metaData(); - final AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData); + final AuthorizedIndices authorizedIndices = new AuthorizedIndices(permission, action, metaData); final ResolvedIndices resolvedIndices = resolveIndexNames(auditId, authentication, action, request, metaData, authorizedIndices, permission); assert !resolvedIndices.isEmpty() diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java index 3753b94faaa12..464eeec1b8e71 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java @@ -7,9 +7,8 @@ import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.util.LazyInitializable; import org.elasticsearch.xpack.core.security.authz.permission.Role; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; -import org.elasticsearch.xpack.core.security.user.User; import java.util.ArrayList; import java.util.Collections; @@ -17,49 +16,31 @@ import java.util.Map; import java.util.function.Predicate; -import static org.elasticsearch.xpack.security.authz.AuthorizationService.isSuperuser; - /** * Abstraction used to make sure that we lazily load authorized indices only when requested and only maximum once per request. Also * makes sure that authorized indices don't get updated throughout the same request for the same user. */ class AuthorizedIndices { - private final User user; - private final String action; - private final MetaData metaData; - private final Role userRoles; - private List authorizedIndices; + private final LazyInitializable, RuntimeException> authorizedIndices; + + AuthorizedIndices(Role userRoles, String action, MetaData metaData) { + this.authorizedIndices = new LazyInitializable<>(() -> { + Predicate predicate = userRoles.indices().allowedIndicesMatcher(action); + + List indicesAndAliases = new ArrayList<>(); + // TODO: can this be done smarter? I think there are usually more indices/aliases in the cluster then indices defined a roles? + for (Map.Entry entry : metaData.getAliasAndIndexLookup().entrySet()) { + String aliasOrIndex = entry.getKey(); + if (predicate.test(aliasOrIndex)) { + indicesAndAliases.add(aliasOrIndex); + } + } - AuthorizedIndices(User user, Role userRoles, String action, MetaData metaData) { - this.user = user; - this.userRoles = userRoles; - this.action = action; - this.metaData = metaData; + return Collections.unmodifiableList(indicesAndAliases); + }); } List get() { - if (authorizedIndices == null) { - authorizedIndices = load(); - } - return authorizedIndices; - } - - private List load() { - Predicate predicate = userRoles.indices().allowedIndicesMatcher(action); - - List indicesAndAliases = new ArrayList<>(); - // TODO: can this be done smarter? I think there are usually more indices/aliases in the cluster then indices defined a roles? - for (Map.Entry entry : metaData.getAliasAndIndexLookup().entrySet()) { - String aliasOrIndex = entry.getKey(); - if (predicate.test(aliasOrIndex)) { - indicesAndAliases.add(aliasOrIndex); - } - } - - if (isSuperuser(user) == false) { - // we should filter out all of the security indices from wildcards - indicesAndAliases.removeAll(SystemIndicesNames.indexNames()); - } - return Collections.unmodifiableList(indicesAndAliases); + return authorizedIndices.getOrCompute(); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java index 2390677afd85d..18d3d634f4f91 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java @@ -20,27 +20,26 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; -import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; import java.util.List; import java.util.Set; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.contains; public class AuthorizedIndicesTests extends ESTestCase { public void testAuthorizedIndicesUserWithoutRoles() { - User user = new User("test user"); - AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, Role.EMPTY, "", - MetaData.EMPTY_META_DATA); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(Role.EMPTY, "", MetaData.EMPTY_META_DATA); List list = authorizedIndices.get(); assertTrue(list.isEmpty()); } public void testAuthorizedIndicesUserWithSomeRoles() { - User user = new User("test user", "a_star", "b"); RoleDescriptor aStarRole = new RoleDescriptor("a_star", null, new IndicesPrivileges[] { IndicesPrivileges.builder().indices("a*").privileges("all").build() }, null); RoleDescriptor bRole = new RoleDescriptor("b", null, @@ -58,55 +57,84 @@ public void testAuthorizedIndicesUserWithSomeRoles() { .putAlias(new AliasMetaData.Builder("ab").build()) .putAlias(new AliasMetaData.Builder("ba").build()) .build(), true) + .put(new IndexMetaData.Builder(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).build()) + .build(), true) .build(); final PlainActionFuture future = new PlainActionFuture<>(); final Set descriptors = Sets.newHashSet(aStarRole, bRole); CompositeRolesStore.buildRoleFromDescriptors(descriptors, new FieldPermissionsCache(Settings.EMPTY), null, future); Role roles = future.actionGet(); - AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, roles, SearchAction.NAME, metaData); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(roles, SearchAction.NAME, metaData); List list = authorizedIndices.get(); assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab")); assertFalse(list.contains("bbbbb")); assertFalse(list.contains("ba")); + assertThat(list, not(contains(SystemIndicesNames.INTERNAL_SECURITY_INDEX))); + assertThat(list, not(contains(SystemIndicesNames.SECURITY_INDEX_NAME))); } public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() { - User user = new User("test user", "role"); Role role = Role.builder("role").add(IndexPrivilege.ALL, "*").build(); - AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, role, SearchAction.NAME, MetaData.EMPTY_META_DATA); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(role, SearchAction.NAME, MetaData.EMPTY_META_DATA); List list = authorizedIndices.get(); assertTrue(list.isEmpty()); } public void testSecurityIndicesAreRemovedFromRegularUser() { - User user = new User("test user", "user_role"); - Role role = Role.builder("user_role").add(IndexPrivilege.ALL, "*").cluster(ClusterPrivilege.ALL).build(); + Role role = Role.builder(randomFrom("user_role", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName())) + .add(IndexPrivilege.ALL, "*") + .add(IndexPrivilege.ALL, SystemIndicesNames.SECURITY_INDEX_NAME + "*") // wildcards not allowed over security indices + .add(IndexPrivilege.ALL, SystemIndicesNames.INTERNAL_SECURITY_INDEX + "*") + .cluster(ClusterPrivilege.ALL) + .build(); Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); MetaData metaData = MetaData.builder() .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).settings(indexSettings) - .numberOfShards(1).numberOfReplicas(0).build(), true) + .put(new IndexMetaData.Builder(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).build()) + .build(), true) .build(); - AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, role, SearchAction.NAME, metaData); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(role, SearchAction.NAME, metaData); List list = authorizedIndices.get(); assertThat(list, containsInAnyOrder("an-index", "another-index")); + assertThat(list, not(contains(SystemIndicesNames.INTERNAL_SECURITY_INDEX))); + assertThat(list, not(contains(SystemIndicesNames.SECURITY_INDEX_NAME))); } public void testSecurityIndicesAreNotRemovedFromSuperUsers() { - User user = new User("admin", "kibana_user", "superuser"); - Role role = Role.builder("kibana_user+superuser").add(IndexPrivilege.ALL, "*").cluster(ClusterPrivilege.ALL).build(); + Role role = Role.builder(randomAlphaOfLength(8)) // role name is not important + .add(IndexPrivilege.ALL, "*") + .add(IndexPrivilege.ALL, SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .add(IndexPrivilege.ALL, SystemIndicesNames.SECURITY_INDEX_NAME) + .cluster(ClusterPrivilege.ALL) + .build(); Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); MetaData metaData = MetaData.builder() .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).settings(indexSettings) - .numberOfShards(1).numberOfReplicas(0).build(), true) + .put(new IndexMetaData.Builder(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).build()) + .build(), true) .build(); - AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, role, SearchAction.NAME, metaData); - List list = authorizedIndices.get(); - assertThat(list, containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME)); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(role, SearchAction.NAME, metaData); + assertThat(authorizedIndices.get(), containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME, + SystemIndicesNames.INTERNAL_SECURITY_INDEX)); + + AuthorizedIndices authorizedIndicesSuperUser = new AuthorizedIndices(ReservedRolesStore.SUPERUSER_ROLE, SearchAction.NAME, metaData); + assertThat(authorizedIndicesSuperUser.get(), containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME, + SystemIndicesNames.INTERNAL_SECURITY_INDEX)); } } From f77fff1715a080143864cb38dd25d15b835a3841 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 19:48:42 +0200 Subject: [PATCH 09/20] More tests and checkstyle --- .../authz/permission/IndicesPermission.java | 7 ++-- .../authz/store/NativeRolesStore.java | 6 ++- .../security/audit/index/AuditTrailTests.java | 3 +- .../authz/AuthorizedIndicesTests.java | 7 ++-- .../authz/IndicesAndAliasesResolverTests.java | 2 +- .../accesscontrol/IndicesPermissionTests.java | 41 +++++++++++++++++++ .../support/SecurityIndexManagerTests.java | 4 +- 7 files changed, 57 insertions(+), 13 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 33093da411b36..bac2fac2b1f00 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -47,17 +47,16 @@ public final class IndicesPermission { public static final IndicesPermission NONE = new IndicesPermission(); + private static final Automaton systemIndicesAutomaton = Automatons.patterns(SystemIndicesNames.indexNames()); private static final Logger logger = LogManager.getLogger(); private final ConcurrentMap> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); private final ConcurrentMap indexGroupAutomatonCache = new ConcurrentHashMap<>(); private final Group[] groups; - private final Automaton systemIndicesAutomaton; public IndicesPermission(Group... groups) { this.groups = groups; - this.systemIndicesAutomaton = Automatons.patterns(SystemIndicesNames.indexNames()); } private static Predicate indexMatcherPredicate(Collection indices) { @@ -82,7 +81,7 @@ private static Predicate indexMatcherPredicate(Collection indice } } - private Automaton indexMatcherAutomaton(String... indices) { + private static Automaton indexMatcherAutomaton(String... indices) { final List exactMatch = new ArrayList<>(); final List patternMatch = new ArrayList<>(); for (String indexPattern : indices) { @@ -310,7 +309,7 @@ public Group(IndexPrivilege privilege, FieldPermissions fieldPermissions, @Nulla this.query = query; } - private IndexPrivilege privilege() { + public IndexPrivilege privilege() { return privilege; } 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 0a70688c19330..ed844f6477cc8 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 @@ -140,7 +140,8 @@ public void getRoleDescriptors(Set names, final ActionListener { final String[] roleIds = names.stream().map(NativeRolesStore::getIdForRole).toArray(String[]::new); - MultiGetRequest multiGetRequest = client.prepareMultiGet().add(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); + MultiGetRequest multiGetRequest = client.prepareMultiGet() + .add(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, multiGetRequest, ActionListener.wrap(mGetResponse -> { final MultiGetItemResponse[] responses = mGetResponse.getResponses(); @@ -217,7 +218,8 @@ void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final listener.onFailure(e); return; } - final IndexRequest indexRequest = client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) + final IndexRequest indexRequest = client + .prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) .setSource(xContentBuilder) .setRefreshPolicy(request.getRefreshPolicy()) .request(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java index ab0b18b74d02d..d90f28a311647 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/audit/index/AuditTrailTests.java @@ -155,7 +155,8 @@ private Collection> waitForAuditEvents() throws InterruptedE private Collection> getAuditEvents() throws Exception { final Client client = client(); final DateTime now = new DateTime(DateTimeZone.UTC); - final String indexName = IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now, IndexNameResolver.Rollover.DAILY); + final String indexName = IndexNameResolver.resolve(SystemIndicesNames.AUDIT_INDEX_NAME_PREFIX, now, + IndexNameResolver.Rollover.DAILY); assertTrue(awaitBusy(() -> indexExists(client, indexName), 5, TimeUnit.SECONDS)); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java index 18d3d634f4f91..9edfff5b8dec2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java @@ -84,7 +84,7 @@ public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() { assertTrue(list.isEmpty()); } - public void testSecurityIndicesAreRemovedFromRegularUser() { + public void testSecurityIndicesAreNotAuthorizedForWildcardPermission() { Role role = Role.builder(randomFrom("user_role", ReservedRolesStore.SUPERUSER_ROLE_DESCRIPTOR.getName())) .add(IndexPrivilege.ALL, "*") .add(IndexPrivilege.ALL, SystemIndicesNames.SECURITY_INDEX_NAME + "*") // wildcards not allowed over security indices @@ -110,7 +110,7 @@ public void testSecurityIndicesAreRemovedFromRegularUser() { assertThat(list, not(contains(SystemIndicesNames.SECURITY_INDEX_NAME))); } - public void testSecurityIndicesAreNotRemovedFromSuperUsers() { + public void testSecurityIndicesAreAuthorizedWhenNamedExplicitly() { Role role = Role.builder(randomAlphaOfLength(8)) // role name is not important .add(IndexPrivilege.ALL, "*") .add(IndexPrivilege.ALL, SystemIndicesNames.INTERNAL_SECURITY_INDEX) @@ -133,7 +133,8 @@ public void testSecurityIndicesAreNotRemovedFromSuperUsers() { assertThat(authorizedIndices.get(), containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME, SystemIndicesNames.INTERNAL_SECURITY_INDEX)); - AuthorizedIndices authorizedIndicesSuperUser = new AuthorizedIndices(ReservedRolesStore.SUPERUSER_ROLE, SearchAction.NAME, metaData); + AuthorizedIndices authorizedIndicesSuperUser = new AuthorizedIndices(ReservedRolesStore.SUPERUSER_ROLE, SearchAction.NAME, + metaData); assertThat(authorizedIndicesSuperUser.get(), containsInAnyOrder("an-index", "another-index", SystemIndicesNames.SECURITY_INDEX_NAME, SystemIndicesNames.INTERNAL_SECURITY_INDEX)); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java index 2430d4f142a61..a307829221ef0 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java @@ -1365,7 +1365,7 @@ public void testDynamicPutMappingRequestFromAlias() { private AuthorizedIndices buildAuthorizedIndices(User user, String action) { PlainActionFuture rolesListener = new PlainActionFuture<>(); authzService.roles(user, rolesListener); - return new AuthorizedIndices(user, rolesListener.actionGet(), action, metaData); + return new AuthorizedIndices(rolesListener.actionGet(), action, metaData); } public static IndexMetaData.Builder indexBuilder(String index) { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java index 61724e44f6154..955dbc23c1b4b 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.xpack.core.security.authz.permission.IndicesPermission; import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import java.io.IOException; import java.util.ArrayList; @@ -39,6 +40,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.is; public class IndicesPermissionTests extends ESTestCase { @@ -267,6 +269,45 @@ public void testErrorMessageIfIndexPatternIsTooComplex() { assertThat(e.getMessage(), containsString("too complex to evaluate")); } + public void testSecurityIndicesPermissions() { + final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); + final MetaData metaData = new MetaData.Builder() + .put(new IndexMetaData.Builder(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME).build()) + .build(), true) + .build(); + FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY); + + // global wildcard + IndicesPermission.Group group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, "*"); + Map authzMap = new IndicesPermission(group).authorize(SearchAction.NAME, + Sets.newHashSet(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME), metaData, + fieldPermissionsCache); + assertThat(authzMap.get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).isGranted(), is(false)); + assertThat(authzMap.get(SystemIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(false)); + + // narrow wildcard + group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, SystemIndicesNames.SECURITY_INDEX_NAME + "*", + SystemIndicesNames.INTERNAL_SECURITY_INDEX + "*"); + authzMap = new IndicesPermission(group).authorize(SearchAction.NAME, + Sets.newHashSet(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME), metaData, + fieldPermissionsCache); + assertThat(authzMap.get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).isGranted(), is(false)); + assertThat(authzMap.get(SystemIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(false)); + + // specific name in permission + group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, SystemIndicesNames.SECURITY_INDEX_NAME, + SystemIndicesNames.INTERNAL_SECURITY_INDEX); + authzMap = new IndicesPermission(group).authorize(SearchAction.NAME, + Sets.newHashSet(SystemIndicesNames.INTERNAL_SECURITY_INDEX, SystemIndicesNames.SECURITY_INDEX_NAME), metaData, + fieldPermissionsCache); + assertThat(authzMap.get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).isGranted(), is(true)); + assertThat(authzMap.get(SystemIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); + } + private static FieldPermissionsDefinition fieldPermissionDef(String[] granted, String[] denied) { return new FieldPermissionsDefinition(granted, denied); } 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 f8914893c737a..e9dfd803dfcab 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 @@ -327,8 +327,8 @@ public void testMissingVersionMappingThrowsError() throws IOException { String templateString = "/missing-version-" + SECURITY_TEMPLATE_NAME + ".json"; ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); final ClusterState clusterState = clusterStateBuilder.build(); - IllegalStateException exception = expectThrows(IllegalStateException.class, - () -> SecurityIndexManager.checkIndexMappingVersionMatches(SystemIndicesNames.SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); + IllegalStateException exception = expectThrows(IllegalStateException.class, () -> SecurityIndexManager + .checkIndexMappingVersionMatches(SystemIndicesNames.SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); assertEquals("Cannot read security-version string in index " + SystemIndicesNames.SECURITY_INDEX_NAME, exception.getMessage()); } From 2e92793843499abbfc7907725d32d0551f51bb6e Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 20:48:39 +0200 Subject: [PATCH 10/20] Javadoc and renames --- .../authz/permission/IndicesPermission.java | 25 ++++++++++++++++--- .../user/TransportHasPrivilegesAction.java | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index bac2fac2b1f00..afef4db210f94 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -59,6 +59,10 @@ public IndicesPermission(Group... groups) { this.groups = groups; } + /** + * Builds a predicate out of a collection of index names and index patterns. The returned predicate checks a given concrete index for + * membership. + */ private static Predicate indexMatcherPredicate(Collection indices) { Set exactMatch = new HashSet<>(); List nonExactMatch = new ArrayList<>(); @@ -81,6 +85,10 @@ private static Predicate indexMatcherPredicate(Collection indice } } + /** + * Builds an {@code Automaton} out of a collection of index names and index patterns. The automaton can be used to check other index + * patterns for inclusion. + */ private static Automaton indexMatcherAutomaton(String... indices) { final List exactMatch = new ArrayList<>(); final List patternMatch = new ArrayList<>(); @@ -93,9 +101,9 @@ private static Automaton indexMatcherAutomaton(String... indices) { } try { final Automaton exactMatchAutomaton = Automatons.patterns(exactMatch); - final Automaton indexPatternAutomaton = Automatons.patterns(patternMatch); - return Automatons.unionAndMinimize( - Arrays.asList(exactMatchAutomaton, Automatons.minusAndMinimize(indexPatternAutomaton, systemIndicesAutomaton))); + // index patterns don't cover certain system indices, these have to be named explicitly + final Automaton indexPatternAutomaton = Automatons.minusAndMinimize(Automatons.patterns(patternMatch), systemIndicesAutomaton); + return Automatons.unionAndMinimize(Arrays.asList(exactMatchAutomaton, indexPatternAutomaton)); } catch (TooComplexToDeterminizeException e) { logger.debug("Index pattern automaton [{}] is too complex", Strings.arrayToCommaDelimitedString(indices)); String description = Strings.arrayToCommaDelimitedString(indices); @@ -176,7 +184,11 @@ public boolean check(String action) { return false; } + /** + * Computes and returns an {@code Automaton} for action names, given a concrete (no pattern) index name. + */ public Automaton allowedActionsMatcher(String index) { + assert false == isIndexPattern(index); List automatonList = new ArrayList<>(); for (Group group : groups) { if (group.indexNameMatcher.test(index)) { @@ -186,7 +198,12 @@ public Automaton allowedActionsMatcher(String index) { return automatonList.isEmpty() ? Automatons.EMPTY : Automatons.unionAndMinimize(automatonList); } - public boolean testIndexMatch(String checkIndex, String checkPrivilegeName) { + /** + * Checks if a privilege (or an action pattern) is granted over an index pattern. + * @param checkIndex The index pattern to check + * @param checkPrivilegeName The privilege name or pattern to check + */ + public boolean checkPrivilegeOverIndexPattern(String checkIndex, String checkPrivilegeName) { final Automaton checkIndexAutomaton = indexMatcherAutomaton(checkIndex); final List privilegeAutomatons = new ArrayList<>(); for (IndicesPermission.Group group : groups) { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java index 1640aae06852b..ca36bec65ec83 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/user/TransportHasPrivilegesAction.java @@ -115,7 +115,7 @@ private void checkPrivileges(HasPrivilegesRequest request, Role userRole, privileges.putAll(existing.getPrivileges()); } for (String privilege : check.getPrivileges()) { - if (userRole.indices().testIndexMatch(index, privilege)) { + if (userRole.indices().checkPrivilegeOverIndexPattern(index, privilege)) { logger.debug(() -> new ParameterizedMessage("Role [{}] has [{}] on index [{}]", Strings.arrayToCommaDelimitedString(userRole.names()), privilege, index)); privileges.put(privilege, true); From 675030694d856a0a5f1f8bbb35158e5e92b7f508 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 21:01:22 +0200 Subject: [PATCH 11/20] two comments --- .../core/security/authz/permission/IndicesPermission.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index afef4db210f94..d39b7bd286252 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -154,8 +154,8 @@ public Group[] groups() { } /** - * @return A predicate that will match all the indices that this permission - * has the privilege for executing the given action on. + * @return A predicate that will match all the indices that this permission has the privilege for executing the given action on. The + * predicate is lazily built and cached. */ public Predicate allowedIndicesMatcher(String action) { return allowedIndicesMatchersForAction.computeIfAbsent(action, (theAction) -> { @@ -207,6 +207,7 @@ public boolean checkPrivilegeOverIndexPattern(String checkIndex, String checkPri final Automaton checkIndexAutomaton = indexMatcherAutomaton(checkIndex); final List privilegeAutomatons = new ArrayList<>(); for (IndicesPermission.Group group : groups) { + // caches the index match automaton for each group final Automaton groupIndexAutomaton = indexGroupAutomatonCache.computeIfAbsent(group, theGroup -> indexMatcherAutomaton(theGroup.indices())); if (Operations.subsetOf(checkIndexAutomaton, groupIndexAutomaton)) { From b6ea0b39023a09baec493a7969abf63459269396 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 22:03:58 +0200 Subject: [PATCH 12/20] import static --- .../authc/esnative/NativeUsersStore.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) 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 aeca14173fa9a..d80e7a76c94fc 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 @@ -47,7 +47,6 @@ import org.elasticsearch.xpack.core.security.authc.esnative.ClientReservedRealm; import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User.Fields; @@ -67,6 +66,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; /** * NativeUsersStore is a store for users that reads from an Elasticsearch index. This store is responsible for fetching the full @@ -147,7 +147,7 @@ public void getUsers(String[] userNames, final ActionListener> } final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -172,7 +172,7 @@ void getUserCount(final ActionListener listener) { } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + client.prepareSearch(SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), USER_DOC_TYPE)) .setSize(0) .request(), @@ -205,7 +205,7 @@ private void getUserAndPassword(final String user, final ActionListener executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, + client.prepareGet(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, user)).request(), new ActionListener() { @Override @@ -246,7 +246,7 @@ public void changePassword(final ChangePasswordRequest request, final ActionList securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(docType, username)) + client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(docType, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.PASSWORD.getPreferredName(), String.valueOf(request.passwordHash())) .setRefreshPolicy(request.getRefreshPolicy()).request(), @@ -284,7 +284,7 @@ public void onFailure(Exception e) { private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)) .setSource(Fields.PASSWORD.getPreferredName(), String.valueOf(passwordHash), Fields.ENABLED.getPreferredName(), true, @@ -326,7 +326,7 @@ private void updateUserWithoutPassword(final PutUserRequest putUserRequest, fina // We must have an existing document securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.USERNAME.getPreferredName(), putUserRequest.username(), @@ -371,7 +371,7 @@ private void indexUser(final PutUserRequest putUserRequest, final ActionListener assert putUserRequest.passwordHash() != null; securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareIndex(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) .setSource(Fields.USERNAME.getPreferredName(), putUserRequest.username(), Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()), @@ -415,7 +415,7 @@ private void setRegularUserEnabled(final String username, final boolean enabled, final ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setRefreshPolicy(refreshPolicy) @@ -450,7 +450,7 @@ private void setReservedUserEnabled(final String username, final boolean enabled boolean clearCache, final ActionListener listener) { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareUpdate(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareUpdate(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setUpsert(XContentType.JSON, @@ -485,7 +485,7 @@ public void deleteUser(final DeleteUserRequest deleteUserRequest, final ActionLi listener.onFailure(frozenSecurityIndex.getUnavailableReason()); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { - DeleteRequest request = client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, + DeleteRequest request = client.prepareDelete(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username())).request(); request.setRefreshPolicy(deleteUserRequest.getRefreshPolicy()); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, @@ -532,7 +532,7 @@ void getReservedUserInfo(String username, ActionListener liste } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, INDEX_TYPE, + client.prepareGet(SECURITY_INDEX_NAME, INDEX_TYPE, getIdForUser(RESERVED_USER_TYPE, username)).request(), new ActionListener() { @Override @@ -577,7 +577,7 @@ void getAllReservedUserInfo(ActionListener> listen } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + client.prepareSearch(SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE)) .setFetchSource(true).request(), new ActionListener() { From 527a22e7674339160085eca5f3654e693bc05712 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 19 Dec 2018 22:17:38 +0200 Subject: [PATCH 13/20] import static --- .../support/mapper/NativeRoleMappingStore.java | 11 ++++++----- .../authz/store/NativePrivilegeStore.java | 10 +++++----- .../security/authz/store/NativeRolesStore.java | 18 +++++++++--------- .../security/support/SecurityIndexManager.java | 11 ++++++----- .../support/SecurityIndexManagerTests.java | 10 +++++----- 5 files changed, 31 insertions(+), 29 deletions(-) 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 7eb5dc8a5b457..7a8db0388b92d 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 @@ -61,6 +61,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed; @@ -131,7 +132,7 @@ void loadMappings(ActionListener> listener) { final QueryBuilder query = QueryBuilders.termQuery(DOC_TYPE_FIELD, DOC_TYPE_ROLE_MAPPING); final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setTypes(SECURITY_GENERIC_TYPE) .setQuery(query) @@ -144,7 +145,7 @@ void loadMappings(ActionListener> listener) { listener.onResponse(mappings.stream().filter(Objects::nonNull).collect(Collectors.toList())), ex -> { logger.error(new ParameterizedMessage("failed to load role mappings from index [{}] skipping all mappings.", - SystemIndicesNames.SECURITY_INDEX_NAME), ex); + SECURITY_INDEX_NAME), ex); listener.onResponse(Collections.emptyList()); })), doc -> buildMapping(getNameFromId(doc.getId()), doc.getSourceRef())); @@ -203,7 +204,7 @@ private void innerPutMapping(PutRoleMappingRequest request, ActionListener { executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, SECURITY_GENERIC_TYPE, getIdForName(request.getName())) + client.prepareDelete(SECURITY_INDEX_NAME, SECURITY_GENERIC_TYPE, getIdForName(request.getName())) .setRefreshPolicy(request.getRefreshPolicy()) .request(), new ActionListener() { @@ -287,7 +288,7 @@ private void getMappings(ActionListener> listener) { logger.info("The security index is not yet available - no role mappings can be loaded"); if (logger.isDebugEnabled()) { logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]", - SystemIndicesNames.SECURITY_INDEX_NAME, + SECURITY_INDEX_NAME, securityIndex.indexExists(), securityIndex.isAvailable(), securityIndex.isMappingUpToDate() 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 826c5f556580e..003056e1b0703 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 @@ -43,7 +43,6 @@ import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheResponse; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.io.IOException; @@ -62,6 +61,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; /** * {@code NativePrivilegeStore} is a store that reads/writes {@link ApplicationPrivilegeDescriptor} objects, @@ -122,7 +122,7 @@ public void getPrivileges(Collection applications, Collection na } final Supplier supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -151,7 +151,7 @@ void getPrivilege(String application, String name, ActionListener executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(application, name)).request(), + client.prepareGet(SECURITY_INDEX_NAME, "doc", toDocId(application, name)).request(), new ActionListener() { @Override public void onResponse(GetResponse response) { @@ -202,7 +202,7 @@ private void innerPutPrivilege(ApplicationPrivilegeDescriptor privilege, WriteRe final String name = privilege.getName(); final XContentBuilder xContentBuilder = privilege.toXContent(jsonBuilder(), true); ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(privilege.getApplication(), name)) + client.prepareIndex(SECURITY_INDEX_NAME, "doc", toDocId(privilege.getApplication(), name)) .setSource(xContentBuilder) .setRefreshPolicy(refreshPolicy) .request(), listener, client::index); @@ -233,7 +233,7 @@ public void deletePrivileges(String application, Collection names, Write }, listener::onFailure), names.size(), Collections.emptyList()); for (String name : names) { ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, "doc", toDocId(application, name)) + client.prepareDelete(SECURITY_INDEX_NAME, "doc", toDocId(application, name)) .setRefreshPolicy(refreshPolicy) .request(), groupListener, client::delete); } 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 ed844f6477cc8..78be47fcac0a2 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 @@ -47,7 +47,6 @@ import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.support.SecurityIndexManager; import java.io.IOException; @@ -71,6 +70,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.stashWithOrigin; import static org.elasticsearch.xpack.core.security.SecurityField.setting; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ROLE_TYPE; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; /** * NativeRolesStore is a {@code RolesStore} that, instead of reading from a @@ -122,7 +122,7 @@ public void getRoleDescriptors(Set names, final ActionListener supplier = client.threadPool().getThreadContext().newRestorableContext(false); try (ThreadContext.StoredContext ignore = stashWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN)) { - SearchRequest request = client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setQuery(query) .setSize(1000) @@ -141,7 +141,7 @@ public void getRoleDescriptors(Set names, final ActionListener { final String[] roleIds = names.stream().map(NativeRolesStore::getIdForRole).toArray(String[]::new); MultiGetRequest multiGetRequest = client.prepareMultiGet() - .add(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); + .add(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, roleIds).request(); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, multiGetRequest, ActionListener.wrap(mGetResponse -> { final MultiGetItemResponse[] responses = mGetResponse.getResponses(); @@ -177,7 +177,7 @@ public void deleteRole(final DeleteRoleRequest deleteRoleRequest, final ActionLi listener.onFailure(frozenSecurityIndex.getUnavailableReason()); } else { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { - DeleteRequest request = client.prepareDelete(SystemIndicesNames.SECURITY_INDEX_NAME, + DeleteRequest request = client.prepareDelete(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(deleteRoleRequest.name())).request(); request.setRefreshPolicy(deleteRoleRequest.getRefreshPolicy()); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, @@ -219,7 +219,7 @@ void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final return; } final IndexRequest indexRequest = client - .prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) + .prepareIndex(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role.getName())) .setSource(xContentBuilder) .setRefreshPolicy(request.getRefreshPolicy()) .request(); @@ -253,10 +253,10 @@ public void usageStats(ActionListener> listener) { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, client.prepareMultiSearch() - .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SECURITY_INDEX_NAME) .setQuery(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .setSize(0)) - .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SECURITY_INDEX_NAME) .setQuery(QueryBuilders.boolQuery() .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .must(QueryBuilders.boolQuery() @@ -266,7 +266,7 @@ public void usageStats(ActionListener> listener) { .should(existsQuery("indices.fields")))) .setSize(0) .setTerminateAfter(1)) - .add(client.prepareSearch(SystemIndicesNames.SECURITY_INDEX_NAME) + .add(client.prepareSearch(SECURITY_INDEX_NAME) .setQuery(QueryBuilders.boolQuery() .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .filter(existsQuery("indices.query"))) @@ -334,7 +334,7 @@ public void onFailure(Exception e) { private void executeGetRoleRequest(String role, ActionListener listener) { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, - client.prepareGet(SystemIndicesNames.SECURITY_INDEX_NAME, + client.prepareGet(SECURITY_INDEX_NAME, ROLE_DOC_TYPE, getIdForRole(role)).request(), listener, client::get)); 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 266a4f5c8833c..c49af2032466c 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 @@ -40,7 +40,6 @@ import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.template.TemplateUtils; import java.nio.charset.StandardCharsets; @@ -59,6 +58,8 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.INTERNAL_SECURITY_INDEX; /** * Manages the lifecycle of a single index, its template, mapping and and data upgrades/migrations. @@ -128,7 +129,7 @@ public ElasticsearchException getUnavailableReason() { if (localState.indexExists) { return new UnavailableShardsException(null, "at least one primary shard for the security index is unavailable"); } else { - return new IndexNotFoundException(SystemIndicesNames.SECURITY_INDEX_NAME); + return new IndexNotFoundException(SECURITY_INDEX_NAME); } } @@ -299,8 +300,8 @@ public void prepareIndexIfNeededThenExecute(final Consumer consumer, "the upgrade API is run on the security index")); } else if (indexState.indexExists == false) { Tuple mappingAndSettings = loadMappingAndSettingsSourceFromTemplate(); - CreateIndexRequest request = new CreateIndexRequest(SystemIndicesNames.INTERNAL_SECURITY_INDEX) - .alias(new Alias(SystemIndicesNames.SECURITY_INDEX_NAME)) + CreateIndexRequest request = new CreateIndexRequest(INTERNAL_SECURITY_INDEX) + .alias(new Alias(SECURITY_INDEX_NAME)) .mapping("doc", mappingAndSettings.v1(), XContentType.JSON) .waitForActiveShards(ActiveShardCount.ALL) .settings(mappingAndSettings.v2()); @@ -328,7 +329,7 @@ public void onFailure(Exception e) { } }, client.admin().indices()::create); } else if (indexState.mappingUpToDate == false) { - PutMappingRequest request = new PutMappingRequest(SystemIndicesNames.INTERNAL_SECURITY_INDEX) + PutMappingRequest request = new PutMappingRequest(INTERNAL_SECURITY_INDEX) .source(loadMappingAndSettingsSourceFromTemplate().v1(), XContentType.JSON) .type("doc"); executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, 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 e9dfd803dfcab..d06058ca0a69c 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 @@ -47,13 +47,13 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.security.test.SecurityTestUtils; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.template.TemplateUtils; import org.hamcrest.Matchers; import org.junit.Before; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -328,8 +328,8 @@ public void testMissingVersionMappingThrowsError() throws IOException { ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); final ClusterState clusterState = clusterStateBuilder.build(); IllegalStateException exception = expectThrows(IllegalStateException.class, () -> SecurityIndexManager - .checkIndexMappingVersionMatches(SystemIndicesNames.SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); - assertEquals("Cannot read security-version string in index " + SystemIndicesNames.SECURITY_INDEX_NAME, exception.getMessage()); + .checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); + assertEquals("Cannot read security-version string in index " + SECURITY_INDEX_NAME, exception.getMessage()); } public void testIndexTemplateIsIdentifiedAsUpToDate() throws IOException { @@ -386,7 +386,7 @@ private ClusterState.Builder createClusterStateWithTemplate(String securityTempl private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException { final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build(); final String indexName = clusterState.metaData().getAliasAndIndexLookup() - .get(SystemIndicesNames.SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); + .get(SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); return ClusterState.builder(clusterState).routingTable(SecurityTestUtils.buildIndexRoutingTable(indexName)); } @@ -420,7 +420,7 @@ private static IndexMetaData.Builder createIndexMetadata(String indexName, Strin private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException { final MetaData.Builder metaDataBuilder = new MetaData.Builder(); final boolean withAlias = randomBoolean(); - final String securityIndexName = SystemIndicesNames.SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate)); ClusterState.Builder clusterStateBuilder = ClusterState.builder(state()); From 2a3f38d9fb0175fc3d06cb160c85ae891c284139 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 25 Dec 2018 11:58:58 +0200 Subject: [PATCH 14/20] Fix check --- .../java/org/elasticsearch/xpack/security/SecurityTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java index fa9dc3f872b25..cbaa724e78bd0 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java @@ -68,6 +68,8 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.discovery.DiscoveryModule.ZEN2_DISCOVERY_TYPE; import static org.elasticsearch.discovery.DiscoveryModule.ZEN_DISCOVERY_TYPE; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; +import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; From aadd06267eda79bf9097057b0eebd9d1f37ebb5d Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 25 Dec 2018 12:50:28 +0200 Subject: [PATCH 15/20] Implicit authorize monitoring passthrough --- .../authz/permission/IndicesPermission.java | 48 +++++++++++++++---- .../security/authz/AuthorizationService.java | 26 ++-------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index d39b7bd286252..5d999b3c7e10e 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -17,6 +17,7 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; @@ -35,7 +36,9 @@ import java.util.SortedMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.BiPredicate; import java.util.function.Predicate; +import java.util.stream.Collectors; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; @@ -85,6 +88,20 @@ private static Predicate indexMatcherPredicate(Collection indice } } + private static Predicate indicesPatternsPredicate(Collection indicesAndPatterns) { + final List patterns = indicesAndPatterns.stream().filter(IndicesPermission::isIndexPattern).collect(Collectors.toList()); + try { + return Automatons.predicate(patterns); + } catch (TooComplexToDeterminizeException e) { + logger.debug("Index pattern automaton [{}] is too complex", patterns); + String description = Strings.collectionToCommaDelimitedString(patterns); + if (description.length() > 80) { + description = Strings.cleanTruncate(description, 80) + "..."; + } + throw new ElasticsearchSecurityException("The set of permitted index patterns [{}] is too complex to evaluate", e, description); + } + } + /** * Builds an {@code Automaton} out of a collection of index names and index patterns. The automaton can be used to check other index * patterns for inclusion. @@ -161,7 +178,7 @@ public Predicate allowedIndicesMatcher(String action) { return allowedIndicesMatchersForAction.computeIfAbsent(action, (theAction) -> { List indices = new ArrayList<>(); for (Group group : groups) { - if (group.check(theAction)) { + if (group.checkAction(theAction)) { indices.addAll(Arrays.asList(group.indices)); } } @@ -177,7 +194,7 @@ public Predicate allowedIndicesMatcher(String action) { */ public boolean check(String action) { for (Group group : groups) { - if (group.check(action)) { + if (group.checkAction(action)) { return true; } } @@ -191,7 +208,7 @@ public Automaton allowedActionsMatcher(String index) { assert false == isIndexPattern(index); List automatonList = new ArrayList<>(); for (Group group : groups) { - if (group.indexNameMatcher.test(index)) { + if (group.checkIndex(index)) { automatonList.add(group.privilege.getAutomaton()); } } @@ -311,20 +328,24 @@ private static boolean isSystemIndex(String index) { public static class Group { private final IndexPrivilege privilege; - private final Predicate actionMatcher; private final String[] indices; private final Predicate indexNameMatcher; private final FieldPermissions fieldPermissions; private final Set query; + private final BiPredicate implicitlyAuthorizeMonitorSystemIndices; public Group(IndexPrivilege privilege, FieldPermissions fieldPermissions, @Nullable Set query, String... indices) { assert indices.length != 0; this.privilege = privilege; - this.actionMatcher = privilege.predicate(); this.indices = indices; this.indexNameMatcher = indexMatcherPredicate(Arrays.asList(indices)); this.fieldPermissions = Objects.requireNonNull(fieldPermissions); this.query = query; + final Predicate indicesPatternPredicate = indicesPatternsPredicate(Arrays.asList(indices)); + this.implicitlyAuthorizeMonitorSystemIndices = (action, index) -> { + return SystemIndicesNames.indexNames().contains(index) && IndexPrivilege.MONITOR.predicate().test(action) + && indicesPatternPredicate.test(index) && privilege.predicate().test(action); + }; } public IndexPrivilege privilege() { @@ -348,13 +369,24 @@ public Set getQuery() { return query; } - private boolean check(String action) { - return actionMatcher.test(action); + private boolean checkAction(String action) { + return privilege.predicate().test(action); + } + + private boolean checkIndex(String index) { + return indexNameMatcher.test(index); } private boolean check(String action, String index) { + assert action != null; assert index != null; - return check(action) && indexNameMatcher.test(index); + if (implicitlyAuthorizeMonitorSystemIndices.test(action, index)) { + // we allow indices monitoring actions through for debugging purposes. These monitor requests resolve indices concretely and + // then requests them. WE SHOULD BREAK THIS BEHAVIOR + logger.debug("Granted monitoring passthrough for index [{}] and action [{}]", index, action); + return true; + } + return checkAction(action) && checkIndex(index); } boolean hasQuery() { diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 900851f5a88e7..754308316ebe2 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -56,7 +56,6 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.support.Automatons; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.SystemUser; @@ -87,7 +86,6 @@ public class AuthorizationService { public static final String ORIGINATING_ACTION_KEY = "_originating_action_name"; public static final String ROLE_NAMES_KEY = "_effective_role_names"; - private static final Predicate MONITOR_INDEX_PREDICATE = IndexPrivilege.MONITOR.predicate(); private static final Predicate SAME_USER_PRIVILEGE = Automatons.predicate( ChangePasswordAction.NAME, AuthenticateAction.NAME, HasPrivilegesAction.NAME, GetUserPrivilegesAction.NAME); @@ -312,18 +310,10 @@ public void authorize(Authentication authentication, String action, TransportReq final Set localIndices = new HashSet<>(resolvedIndices.getLocal()); IndicesAccessControl indicesAccessControl = permission.authorize(action, localIndices, metaData, fieldPermissionsCache); - if (!indicesAccessControl.isGranted()) { - throw denial(auditId, authentication, action, request, permission.names()); - } else if (hasSecurityIndexAccess(indicesAccessControl) - && MONITOR_INDEX_PREDICATE.test(action) == false - && isSuperuser(authentication.getUser()) == false) { - // only the XPackUser is allowed to work with this index, but we should allow indices monitoring actions through for debugging - // purposes. These monitor requests also sometimes resolve indices concretely and then requests them - logger.debug("user [{}] attempted to directly perform [{}] against the security index [{}]", - authentication.getUser().principal(), action, SystemIndicesNames.SECURITY_INDEX_NAME); - throw denial(auditId, authentication, action, request, permission.names()); - } else { + if (indicesAccessControl.isGranted()) { putTransientIfNonExisting(AuthorizationServiceField.INDICES_PERMISSIONS_KEY, indicesAccessControl); + } else { + throw denial(auditId, authentication, action, request, permission.names()); } //if we are creating an index we need to authorize potential aliases created at the same time @@ -359,16 +349,6 @@ private boolean isInternalUser(User user) { return SystemUser.is(user) || XPackUser.is(user) || XPackSecurityUser.is(user); } - private boolean hasSecurityIndexAccess(IndicesAccessControl indicesAccessControl) { - for (String index : SystemIndicesNames.indexNames()) { - final IndicesAccessControl.IndexAccessControl indexPermissions = indicesAccessControl.getIndexPermissions(index); - if (indexPermissions != null && indexPermissions.isGranted()) { - return true; - } - } - return false; - } - /** * Performs authorization checks on the items within a {@link BulkShardRequest}. * This inspects the {@link BulkItemRequest items} within the request, computes From d63577dcb9e19ca51ac9ec363d71b60350ade91f Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 26 Dec 2018 08:59:53 +0200 Subject: [PATCH 16/20] import static --- .../authz/permission/IndicesPermission.java | 6 +- .../authz/store/ReservedRolesStoreTests.java | 4 +- .../mapper/NativeRoleMappingStore.java | 3 +- .../security/authz/AuthorizationService.java | 12 ++-- .../authc/esnative/NativeRealmIntegTests.java | 25 +++---- .../authz/AuthorizationServiceTests.java | 68 +++++++++---------- .../authz/IndicesAndAliasesResolverTests.java | 16 ++--- .../accesscontrol/IndicesPermissionTests.java | 8 +-- 8 files changed, 71 insertions(+), 71 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 5d999b3c7e10e..69da0c7603411 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -192,7 +192,7 @@ public Predicate allowedIndicesMatcher(String action) { * The usecase for this is composite actions that are initially only authorized based on the action name (indices are not * checked on the coordinating node), and properly authorized later at the shard level checking their indices as well. */ - public boolean check(String action) { + public boolean checkAction(String action) { for (Group group : groups) { if (group.checkAction(action)) { return true; @@ -341,10 +341,10 @@ public Group(IndexPrivilege privilege, FieldPermissions fieldPermissions, @Nulla this.indexNameMatcher = indexMatcherPredicate(Arrays.asList(indices)); this.fieldPermissions = Objects.requireNonNull(fieldPermissions); this.query = query; - final Predicate indicesPatternPredicate = indicesPatternsPredicate(Arrays.asList(indices)); + final Predicate indicesPatternsPredicate = indicesPatternsPredicate(Arrays.asList(indices)); this.implicitlyAuthorizeMonitorSystemIndices = (action, index) -> { return SystemIndicesNames.indexNames().contains(index) && IndexPrivilege.MONITOR.predicate().test(action) - && indicesPatternPredicate.test(index) && privilege.predicate().test(action); + && indicesPatternsPredicate.test(index) && privilege.predicate().test(action); }; } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java index bac8569bab4b2..6de0869533f07 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java @@ -661,8 +661,8 @@ public void testSuperuserRole() { Sets.newHashSet(SystemIndicesNames.SECURITY_INDEX_NAME), metaData, fieldPermissionsCache); assertThat(authzMap.get(SystemIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); assertThat(authzMap.get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).isGranted(), is(true)); - assertTrue(superuserRole.indices().check(SearchAction.NAME)); - assertFalse(superuserRole.indices().check("unknown")); + assertTrue(superuserRole.indices().checkAction(SearchAction.NAME)); + assertFalse(superuserRole.indices().checkAction("unknown")); assertThat(superuserRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(true)); 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 7a8db0388b92d..2374288c7df7d 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 @@ -34,7 +34,6 @@ import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping; import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExpressionModel; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.security.authc.support.CachingRealm; import org.elasticsearch.xpack.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.security.support.SecurityIndexManager; @@ -67,7 +66,7 @@ /** * This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch - * {@link SystemIndicesNames#SECURITY_INDEX_NAME index}. + * {@link SECURITY_INDEX_NAME index}. *
* The store is responsible for all read and write operations as well as * {@link #resolveRoles(UserData, ActionListener) resolving roles}. diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 754308316ebe2..fd35edf910f9d 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -216,7 +216,7 @@ public void authorize(Authentication authentication, String action, TransportReq + ", " + request.getClass().getSimpleName() + " doesn't"); } // we check if the user can execute the action, without looking at indices, which will be authorized at the shard level - if (permission.indices().check(action)) { + if (permission.indices().checkAction(action)) { auditTrail.accessGranted(auditId, authentication, action, request, permission.names()); return; } @@ -227,7 +227,7 @@ public void authorize(Authentication authentication, String action, TransportReq + ", " + request.getClass().getSimpleName() + " doesn't"); } // we check if the user can execute the action, without looking at indices, which will be authorized at the shard level - if (permission.indices().check(action)) { + if (permission.indices().checkAction(action)) { auditTrail.accessGranted(auditId, authentication, action, request, permission.names()); return; } @@ -238,7 +238,7 @@ public void authorize(Authentication authentication, String action, TransportReq throw new IllegalStateException("originalRequest is not a proxy request: [" + originalRequest + "] but action: [" + action + "] is a proxy action"); } - if (permission.indices().check(action)) { + if (permission.indices().checkAction(action)) { auditTrail.accessGranted(auditId, authentication, action, request, permission.names()); return; } else { @@ -262,7 +262,7 @@ public void authorize(Authentication authentication, String action, TransportReq // if the action is a search scroll action, we first authorize that the user can execute the action for some // index and if they cannot, we can fail the request early before we allow the execution of the action and in // turn the shard actions - if (SearchScrollAction.NAME.equals(action) && permission.indices().check(action) == false) { + if (SearchScrollAction.NAME.equals(action) && permission.indices().checkAction(action) == false) { throw denial(auditId, authentication, action, request, permission.names()); } else { // we store the request as a transient in the ThreadContext in case of a authorization failure at the shard @@ -283,7 +283,7 @@ public void authorize(Authentication authentication, String action, TransportReq // If this request does not allow remote indices // then the user must have permission to perform this action on at least 1 local index - if (allowsRemoteIndices == false && permission.indices().check(action) == false) { + if (allowsRemoteIndices == false && permission.indices().checkAction(action) == false) { throw denial(auditId, authentication, action, request, permission.names()); } @@ -296,7 +296,7 @@ public void authorize(Authentication authentication, String action, TransportReq // If this request does reference any remote indices // then the user must have permission to perform this action on at least 1 local index - if (resolvedIndices.getRemote().isEmpty() && permission.indices().check(action) == false) { + if (resolvedIndices.getRemote().isEmpty() && permission.indices().checkAction(action) == false) { throw denial(auditId, authentication, action, request, permission.names()); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java index 42222fdadefc9..97ef0f4b7bbf2 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealmIntegTests.java @@ -40,7 +40,6 @@ import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.client.SecurityClient; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.KibanaUser; @@ -61,6 +60,8 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.INTERNAL_SECURITY_INDEX; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -137,7 +138,7 @@ public void testAddAndGetUser() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3kirt".toCharArray(), hasher, "role1", "user").get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -192,7 +193,7 @@ public void testAddAndGetRole() throws Exception { .metadata(metadata) .get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); logger.info("--> retrieving role"); GetRolesResponse resp = c.prepareGetRoles().names("test_role").get(); assertTrue("role should exist", resp.hasRoles()); @@ -243,7 +244,7 @@ public void testAddUserAndRoleThenAuth() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -264,7 +265,7 @@ public void testUpdatingUserAndAuthentication() throws Exception { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -300,7 +301,7 @@ public void testCreateDeleteAuthenticate() { c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); logger.info("--> retrieving user"); GetUsersResponse resp = c.prepareGetUsers("joe").get(); assertTrue("user should exist", resp.hasUsers()); @@ -338,7 +339,7 @@ public void testCreateAndUpdateRole() { logger.error("--> creating user"); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); if (authenticate) { final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); @@ -388,7 +389,7 @@ public void testAuthenticateWithDeletedRole() { .get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); logger.error("--> waiting for .security index"); - ensureGreen(SystemIndicesNames.SECURITY_INDEX_NAME); + ensureGreen(SECURITY_INDEX_NAME); final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster() @@ -519,12 +520,12 @@ public void testUsersAndRolesDoNotInterfereWithIndicesStats() throws Exception { .get(); } - IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SystemIndicesNames.SECURITY_INDEX_NAME).get(); + IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SECURITY_INDEX_NAME).get(); assertThat(response.getFailedShards(), is(0)); assertThat(response.getIndices().size(), is(2)); - assertThat(response.getIndices().get(SystemIndicesNames.INTERNAL_SECURITY_INDEX), notNullValue()); - assertThat(response.getIndices().get(SystemIndicesNames.INTERNAL_SECURITY_INDEX).getIndex(), - is(SystemIndicesNames.INTERNAL_SECURITY_INDEX)); + assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX), notNullValue()); + assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX).getIndex(), + is(INTERNAL_SECURITY_INDEX)); } public void testOperationsOnReservedUsers() throws Exception { diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 427562c9a6234..4cbd2e622302d 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -119,7 +119,6 @@ import org.elasticsearch.xpack.core.security.authz.privilege.ClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.SystemUser; @@ -151,6 +150,7 @@ import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.endsWith; @@ -805,7 +805,7 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); @@ -813,21 +813,21 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { List> requests = new ArrayList<>(); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - new DeleteRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new DeleteRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(UpdateAction.NAME, - new UpdateRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new UpdateRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - new IndexRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); + new IndexRequest(SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)))); + .addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)))); requests.add( - new Tuple<>(UpdateSettingsAction.NAME, new UpdateSettingsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + new Tuple<>(UpdateSettingsAction.NAME, new UpdateSettingsRequest().indices(SECURITY_INDEX_NAME))); for (Tuple requestTuple : requests) { String action = requestTuple.v1(); @@ -840,12 +840,12 @@ public void testNonXPackUserCannotExecuteOperationAgainstSecurityIndex() { } // we should allow waiting for the health of the index or any index if the user has this permission - ClusterHealthRequest request = new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME); + ClusterHealthRequest request = new ClusterHealthRequest(SECURITY_INDEX_NAME); authorize(authentication, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()}); // multiple indices - request = new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "foo", "bar"); + request = new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar"); authorize(authentication, ClusterHealthAction.NAME, request); verify(auditTrail).accessGranted(requestId, authentication, ClusterHealthAction.NAME, request, new String[]{role.getName()}); verifyNoMoreInteractions(auditTrail); @@ -864,21 +864,21 @@ public void testGrantedNonXPackUserCanExecuteMonitoringOperationsAgainstSecurity ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); List> requests = new ArrayList<>(); - requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); - requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_INDEX_NAME))); + requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(IndicesShardStoresAction.NAME, - new IndicesShardStoresRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + new IndicesShardStoresRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(UpgradeStatusAction.NAME, - new UpgradeStatusRequest().indices(SystemIndicesNames.SECURITY_INDEX_NAME))); + new UpgradeStatusRequest().indices(SECURITY_INDEX_NAME))); for (final Tuple requestTuple : requests) { final String action = requestTuple.v1(); @@ -894,7 +894,7 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndex() { ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); @@ -902,26 +902,26 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndex() { List> requests = new ArrayList<>(); requests.add(new Tuple<>(DeleteAction.NAME, - new DeleteRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new DeleteRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(SystemIndicesNames.SECURITY_INDEX_NAME, DeleteRequest::new))); + createBulkShardRequest(SECURITY_INDEX_NAME, DeleteRequest::new))); requests.add(new Tuple<>(UpdateAction.NAME, - new UpdateRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new UpdateRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndexAction.NAME, - new IndexRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new IndexRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(BulkAction.NAME + "[s]", - createBulkShardRequest(SystemIndicesNames.SECURITY_INDEX_NAME, IndexRequest::new))); - requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); + createBulkShardRequest(SECURITY_INDEX_NAME, IndexRequest::new))); + requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); - requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); + requests.add(new Tuple<>(GetAction.NAME, new GetRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(TermVectorsAction.NAME, - new TermVectorsRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "type", "id"))); + new TermVectorsRequest(SECURITY_INDEX_NAME, "type", "id"))); requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() - .addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)))); - requests.add(new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME))); + .addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)))); + requests.add(new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(ClusterHealthAction.NAME, - new ClusterHealthRequest(SystemIndicesNames.SECURITY_INDEX_NAME, "foo", "bar"))); + new ClusterHealthRequest(SECURITY_INDEX_NAME, "foo", "bar"))); for (final Tuple requestTuple : requests) { final String action = requestTuple.v1(); @@ -939,7 +939,7 @@ public void testSuperusersCanExecuteOperationAgainstSecurityIndexWithWildcard() ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder(SystemIndicesNames.SECURITY_INDEX_NAME) + .put(new IndexMetaData.Builder(SECURITY_INDEX_NAME) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .numberOfShards(1).numberOfReplicas(0).build(), true) .build()); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java index a307829221ef0..04bd661edb21d 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java @@ -59,7 +59,6 @@ import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; -import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; @@ -81,6 +80,7 @@ import java.util.Map; import java.util.Set; +import static org.elasticsearch.xpack.core.security.index.SystemIndicesNames.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.contains; @@ -120,7 +120,7 @@ public void setup() { indexNameExpressionResolver = new IndexNameExpressionResolver(); final boolean withAlias = randomBoolean(); - final String securityIndexName = SystemIndicesNames.SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); MetaData metaData = MetaData.builder() .put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar")) .putAlias(AliasMetaData.builder("foounauthorized")).settings(settings)) @@ -1222,14 +1222,14 @@ public void testXPackSecurityUserHasAccessToSecurityIndex() { { final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, hasItem(SystemIndicesNames.SECURITY_INDEX_NAME)); + assertThat(indices, hasItem(SECURITY_INDEX_NAME)); } { IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); - aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SystemIndicesNames.SECURITY_INDEX_NAME)); + aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, IndicesAliasesAction.NAME); List indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); - assertThat(indices, hasItem(SystemIndicesNames.SECURITY_INDEX_NAME)); + assertThat(indices, hasItem(SECURITY_INDEX_NAME)); } } @@ -1237,7 +1237,7 @@ public void testXPackUserDoesNotHaveAccessToSecurityIndex() { SearchRequest request = new SearchRequest(); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SECURITY_INDEX_NAME))); } public void testNonXPackUserAccessingSecurityIndex() { @@ -1249,7 +1249,7 @@ public void testNonXPackUserAccessingSecurityIndex() { SearchRequest request = new SearchRequest(); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME); List indices = resolveIndices(request, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SECURITY_INDEX_NAME))); } { @@ -1257,7 +1257,7 @@ public void testNonXPackUserAccessingSecurityIndex() { aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*")); final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME); List indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); - assertThat(indices, not(hasItem(SystemIndicesNames.SECURITY_INDEX_NAME))); + assertThat(indices, not(hasItem(SECURITY_INDEX_NAME))); } } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java index 955dbc23c1b4b..38446a196fb40 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesPermissionTests.java @@ -232,8 +232,8 @@ public void testCorePermissionAuthorize() { // did not define anything for ba so we allow all assertFalse(authzMap.get("ba").getFieldPermissions().hasFieldLevelSecurity()); - assertTrue(core.check(SearchAction.NAME)); - assertFalse(core.check("unknown")); + assertTrue(core.checkAction(SearchAction.NAME)); + assertFalse(core.checkAction("unknown")); // test with two indices group1 = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, "a1"); @@ -252,8 +252,8 @@ public void testCorePermissionAuthorize() { assertTrue(authzMap.get("a2").getFieldPermissions().grantsAccessTo(randomAlphaOfLength(5) + "_field2")); assertTrue(authzMap.get("a2").getFieldPermissions().hasFieldLevelSecurity()); - assertTrue(core.check(SearchAction.NAME)); - assertFalse(core.check("unknown")); + assertTrue(core.checkAction(SearchAction.NAME)); + assertFalse(core.checkAction("unknown")); } public void testErrorMessageIfIndexPatternIsTooComplex() { From ee7e2c228058690749205326528c18eeefccb603 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 9 Jan 2019 16:57:23 +0200 Subject: [PATCH 17/20] review nits --- .../authz/permission/IndicesPermission.java | 6 +- .../xpack/security/authc/TokenService.java | 70 ------------------- 2 files changed, 3 insertions(+), 73 deletions(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java index 69da0c7603411..847282d16cb7b 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java @@ -17,7 +17,6 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; import org.elasticsearch.xpack.core.security.authz.accesscontrol.IndicesAccessControl; import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; import org.elasticsearch.xpack.core.security.index.SystemIndicesNames; @@ -52,7 +51,7 @@ public final class IndicesPermission { public static final IndicesPermission NONE = new IndicesPermission(); private static final Automaton systemIndicesAutomaton = Automatons.patterns(SystemIndicesNames.indexNames()); - private static final Logger logger = LogManager.getLogger(); + private static final Logger logger = LogManager.getLogger(IndicesPermission.class); private final ConcurrentMap> allowedIndicesMatchersForAction = new ConcurrentHashMap<>(); private final ConcurrentMap indexGroupAutomatonCache = new ConcurrentHashMap<>(); @@ -383,7 +382,8 @@ private boolean check(String action, String index) { if (implicitlyAuthorizeMonitorSystemIndices.test(action, index)) { // we allow indices monitoring actions through for debugging purposes. These monitor requests resolve indices concretely and // then requests them. WE SHOULD BREAK THIS BEHAVIOR - logger.debug("Granted monitoring passthrough for index [{}] and action [{}]", index, action); + logger.debug("Privileges [{}] over the indices [{}], granted monitoring passthrough for index [{}] and action [{}]", + privilege.name(), indices, index, action); return true; } return checkAction(action) && checkIndex(index); 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 7f727096eeae3..3246f0ecd9c2f 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 @@ -562,76 +562,6 @@ private void invalidateAllTokens(Collection accessTokenIds, ActionListen listener::onFailure), new AtomicInteger(0), "refresh_token", null); } - /** -<<<<<<< HEAD - * Performs the actual bwc invalidation of a collection of tokens and then kicks off the new invalidation method. - * - * @param tokenIds the collection of token ids or token document ids that should be invalidated - * @param listener the listener to notify upon completion - * @param attemptCount the number of attempts to invalidate that have already been tried - * @param expirationEpochMilli the expiration time as milliseconds since the epoch - * @param previousResult if this not the initial attempt for invalidation, it contains the result of invalidating - * tokens up to the point of the retry. This result is added to the result of the current attempt - */ - private void indexBwcInvalidation(Collection tokenIds, ActionListener listener, - AtomicInteger attemptCount, long expirationEpochMilli, - @Nullable TokensInvalidationResult previousResult) { - - if (tokenIds.isEmpty()) { - logger.warn("No tokens provided for invalidation"); - listener.onFailure(invalidGrantException("No tokens provided for invalidation")); - } else if (attemptCount.get() > MAX_RETRY_ATTEMPTS) { - logger.warn("Failed to invalidate [{}] tokens after [{}] attempts", tokenIds.size(), - attemptCount.get()); - listener.onFailure(invalidGrantException("failed to invalidate tokens")); - } else { - BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); - for (String tokenId : tokenIds) { - final String invalidatedTokenId = getInvalidatedTokenDocumentId(tokenId); - IndexRequest indexRequest = client.prepareIndex(SystemIndicesNames.SECURITY_INDEX_NAME, TYPE, invalidatedTokenId) - .setOpType(OpType.CREATE) - .setSource("doc_type", INVALIDATED_TOKEN_DOC_TYPE, "expiration_time", expirationEpochMilli) - .request(); - bulkRequestBuilder.add(indexRequest); - } - bulkRequestBuilder.setRefreshPolicy(RefreshPolicy.WAIT_UNTIL); - final BulkRequest bulkRequest = bulkRequestBuilder.request(); - securityIndex.prepareIndexIfNeededThenExecute(ex -> listener.onFailure(traceLog("prepare security index", ex)), - () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, bulkRequest, - ActionListener.wrap(bulkResponse -> { - List retryTokenIds = new ArrayList<>(); - for (BulkItemResponse bulkItemResponse : bulkResponse.getItems()) { - if (bulkItemResponse.isFailed()) { - Throwable cause = bulkItemResponse.getFailure().getCause(); - logger.error(cause.getMessage()); - traceLog("(bwc) invalidate tokens", cause); - if (isShardNotAvailableException(cause)) { - retryTokenIds.add(getTokenIdFromInvalidatedTokenDocumentId(bulkItemResponse.getFailure().getId())); - } else if ((cause instanceof VersionConflictEngineException) == false){ - // We don't handle VersionConflictEngineException, the ticket has been invalidated - listener.onFailure(bulkItemResponse.getFailure().getCause()); - } - } - } - if (retryTokenIds.isEmpty() == false) { - attemptCount.incrementAndGet(); - indexBwcInvalidation(retryTokenIds, listener, attemptCount, expirationEpochMilli, previousResult); - } - indexInvalidation(tokenIds, listener, attemptCount, "access_token", previousResult); - }, e -> { - Throwable cause = ExceptionsHelper.unwrapCause(e); - traceLog("(bwc) invalidate tokens", cause); - if (isShardNotAvailableException(cause)) { - attemptCount.incrementAndGet(); - indexBwcInvalidation(tokenIds, listener, attemptCount, expirationEpochMilli, previousResult); - } else { - listener.onFailure(e); - } - }), - client::bulk)); - } - } - /** * Performs the actual invalidation of a collection of tokens * From d6191cf9be71fba40fb706031839a71e4c52041b Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 9 Jan 2019 17:25:55 +0200 Subject: [PATCH 18/20] Compilation minor error --- .../security/authc/support/mapper/NativeRoleMappingStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2374288c7df7d..e941f9475adf7 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 @@ -66,7 +66,7 @@ /** * This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch - * {@link SECURITY_INDEX_NAME index}. + * {@link SECURITY_INDEX_NAME} index. *
* The store is responsible for all read and write operations as well as * {@link #resolveRoles(UserData, ActionListener) resolving roles}. From 9f6c73926c14c0ff24826aff1f3be6f21e7ba768 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 15 Jan 2019 18:00:31 +0200 Subject: [PATCH 19/20] RoleDescriptor allow_restricted_indices --- .../core/security/authz/RoleDescriptor.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java index 9efbf985b832e..cfdea1e642dbf 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java @@ -428,6 +428,7 @@ private static RoleDescriptor.IndicesPrivileges parseIndex(String roleName, XCon String[] privileges = null; String[] grantedFields = null; String[] deniedFields = null; + boolean allow_restricted_indices = false; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -444,6 +445,13 @@ private static RoleDescriptor.IndicesPrivileges parseIndex(String roleName, XCon throw new ElasticsearchParseException("failed to parse indices privileges for role [{}]. expected field [{}] " + "value to be a string or an array of strings, but found [{}] instead", roleName, currentFieldName, token); } + } else if (Fields.ALLOW_RESTRICTED_INDICES.match(currentFieldName, parser.getDeprecationHandler())) { + if (token == XContentParser.Token.VALUE_BOOLEAN) { + allow_restricted_indices = parser.booleanValue(); + } else { + throw new ElasticsearchParseException("failed to parse indices privileges for role [{}]. expected field [{}] " + + "value to be a boolean, but found [{}] instead", roleName, currentFieldName, token); + } } else if (Fields.QUERY.match(currentFieldName, parser.getDeprecationHandler())) { if (token == XContentParser.Token.START_OBJECT) { XContentBuilder builder = JsonXContent.contentBuilder(); @@ -543,6 +551,7 @@ private static RoleDescriptor.IndicesPrivileges parseIndex(String roleName, XCon .grantedFields(grantedFields) .deniedFields(deniedFields) .query(query) + .allowRestrictedIndices(allow_restricted_indices) .build(); } @@ -590,6 +599,10 @@ public static class IndicesPrivileges implements ToXContentObject, Writeable { private String[] grantedFields = null; private String[] deniedFields = null; private BytesReference query; + // by default certain restricted indices are exempted when granting privileges, as they should generally be hidden for ordinary + // users. Setting this flag eliminates this special status, and any index name pattern in the permission will cover restricted + // indices as well. + private boolean allow_restricted_indices = false; private IndicesPrivileges() { } @@ -600,6 +613,11 @@ public IndicesPrivileges(StreamInput in) throws IOException { this.deniedFields = in.readOptionalStringArray(); this.privileges = in.readStringArray(); this.query = in.readOptionalBytesReference(); + if (in.getVersion().onOrAfter(Version.V_6_7_0)) { + allow_restricted_indices = in.readBoolean(); + } else { + allow_restricted_indices = false; + } } @Override @@ -609,6 +627,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeOptionalStringArray(deniedFields); out.writeStringArray(privileges); out.writeOptionalBytesReference(query); + if (out.getVersion().onOrAfter(Version.V_6_7_0)) { + out.writeBoolean(allow_restricted_indices); + } } public static Builder builder() { @@ -646,6 +667,10 @@ public boolean isUsingFieldLevelSecurity() { return hasDeniedFields() || hasGrantedFields(); } + public boolean allowsRestrictedIndices() { + return allow_restricted_indices; + } + private boolean hasDeniedFields() { return deniedFields != null && deniedFields.length > 0; } @@ -666,6 +691,7 @@ private boolean hasGrantedFields() { public String toString() { StringBuilder sb = new StringBuilder("IndicesPrivileges["); sb.append("indices=[").append(Strings.arrayToCommaDelimitedString(indices)); + sb.append("], allows_restricted_indices=[").append(allow_restricted_indices); sb.append("], privileges=[").append(Strings.arrayToCommaDelimitedString(privileges)); sb.append("], "); if (grantedFields != null || deniedFields != null) { @@ -702,6 +728,7 @@ public boolean equals(Object o) { IndicesPrivileges that = (IndicesPrivileges) o; if (!Arrays.equals(indices, that.indices)) return false; + if (allow_restricted_indices != that.allow_restricted_indices) return false; if (!Arrays.equals(privileges, that.privileges)) return false; if (!Arrays.equals(grantedFields, that.grantedFields)) return false; if (!Arrays.equals(deniedFields, that.deniedFields)) return false; @@ -711,6 +738,7 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = Arrays.hashCode(indices); + result = 31 * result + (allow_restricted_indices ? 1 : 0); result = 31 * result + Arrays.hashCode(privileges); result = 31 * result + Arrays.hashCode(grantedFields); result = 31 * result + Arrays.hashCode(deniedFields); @@ -736,6 +764,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (query != null) { builder.field("query", query.utf8ToString()); } + builder.field(RoleDescriptor.Fields.ALLOW_RESTRICTED_INDICES.getPreferredName(), allow_restricted_indices); return builder.endObject(); } @@ -774,6 +803,11 @@ public Builder query(@Nullable String query) { return query(query == null ? null : new BytesArray(query)); } + public Builder allowRestrictedIndices(boolean allow) { + indicesPrivileges.allow_restricted_indices = allow; + return this; + } + public Builder query(@Nullable BytesReference query) { if (query == null) { indicesPrivileges.query = null; @@ -954,6 +988,7 @@ public interface Fields { ParseField APPLICATIONS = new ParseField("applications"); ParseField RUN_AS = new ParseField("run_as"); ParseField NAMES = new ParseField("names"); + ParseField ALLOW_RESTRICTED_INDICES = new ParseField("allow_restricted_indices"); ParseField RESOURCES = new ParseField("resources"); ParseField QUERY = new ParseField("query"); ParseField PRIVILEGES = new ParseField("privileges"); From e50ebfcebacf486d6f4d178ddbb49e156320cba9 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Tue, 15 Jan 2019 18:13:47 +0200 Subject: [PATCH 20/20] Mapping --- .../core/src/main/resources/security-index-template.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugin/core/src/main/resources/security-index-template.json b/x-pack/plugin/core/src/main/resources/security-index-template.json index bac5930c0d5c9..3723aff9054de 100644 --- a/x-pack/plugin/core/src/main/resources/security-index-template.json +++ b/x-pack/plugin/core/src/main/resources/security-index-template.json @@ -88,6 +88,9 @@ }, "query" : { "type" : "keyword" + }, + "allow_restricted_indices" : { + "type" : "boolean" } } },