diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 2ad12e9205e..7cdaa3b6293 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -19,12 +19,9 @@ import org.elasticsearch.action.search.SearchScrollAction; import org.elasticsearch.action.search.SearchTransportService; import org.elasticsearch.action.support.replication.TransportReplicationAction.ConcreteShardRequest; import org.elasticsearch.action.termvectors.MultiTermVectorsAction; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.service.ClusterService; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; @@ -38,8 +35,6 @@ import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler; import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; -import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; -import org.elasticsearch.xpack.security.authz.indicesresolver.IndicesAndAliasesResolver; import org.elasticsearch.xpack.security.authz.permission.ClusterPermission; import org.elasticsearch.xpack.security.authz.permission.DefaultRole; import org.elasticsearch.xpack.security.authz.permission.GlobalPermission; @@ -56,13 +51,14 @@ import org.elasticsearch.xpack.security.user.XPackUser; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.function.Predicate; +import static org.bouncycastle.asn1.x500.style.RFC4519Style.name; import static org.elasticsearch.xpack.security.Security.setting; import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError; @@ -78,7 +74,7 @@ public class AuthorizationService extends AbstractComponent { private final ClusterService clusterService; private final CompositeRolesStore rolesStore; private final AuditTrailService auditTrail; - private final IndicesAndAliasesResolver[] indicesAndAliasesResolvers; + private final IndicesAndAliasesResolver indicesAndAliasesResolver; private final AuthenticationFailureHandler authcFailureHandler; private final ThreadContext threadContext; private final AnonymousUser anonymousUser; @@ -92,9 +88,7 @@ public class AuthorizationService extends AbstractComponent { this.rolesStore = rolesStore; this.clusterService = clusterService; this.auditTrail = auditTrail; - this.indicesAndAliasesResolvers = new IndicesAndAliasesResolver[] { - new DefaultIndicesAndAliasesResolver(this, new IndexNameExpressionResolver(settings)) - }; + this.indicesAndAliasesResolver = new IndicesAndAliasesResolver(new IndexNameExpressionResolver(settings)); this.authcFailureHandler = authcFailureHandler; this.threadContext = threadPool.getThreadContext(); this.anonymousUser = anonymousUser; @@ -102,56 +96,6 @@ public class AuthorizationService extends AbstractComponent { this.anonymousAuthzExceptionEnabled = ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.get(settings); } - /** - * Returns all indices and aliases the given user is allowed to execute the given action on. - * - * @param user The user - * @param action The action - */ - public List authorizedIndicesAndAliases(User user, String action) { - final String[] anonymousRoles = isAnonymousEnabled ? anonymousUser.roles() : Strings.EMPTY_ARRAY; - String[] rolesNames = user.roles(); - if (rolesNames.length == 0 && anonymousRoles.length == 0) { - return Collections.emptyList(); - } - - List> predicates = new ArrayList<>(); - for (String roleName : rolesNames) { - Role role = rolesStore.role(roleName); - if (role != null) { - predicates.add(role.indices().allowedIndicesMatcher(action)); - } - } - if (anonymousUser.equals(user) == false) { - for (String roleName : anonymousRoles) { - Role role = rolesStore.role(roleName); - if (role != null) { - predicates.add(role.indices().allowedIndicesMatcher(action)); - } - } - } - Predicate predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2)); - - List indicesAndAliases = new ArrayList<>(); - MetaData metaData = clusterService.state().metaData(); - // 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 (XPackUser.is(user) == false && Arrays.binarySearch(user.roles(), SuperuserRole.NAME) < 0) { - // we should filter out the .security index from wildcards - if (indicesAndAliases.remove(SecurityTemplateService.SECURITY_INDEX_NAME)) { - logger.debug("removed [{}] from user [{}] list of authorized indices", - SecurityTemplateService.SECURITY_INDEX_NAME, user.principal()); - } - } - return Collections.unmodifiableList(indicesAndAliases); - } - /** * Verifies that the given user can execute the given request (and action). If the user doesn't * have the appropriate privileges for this action/request, an {@link ElasticsearchSecurityException} @@ -181,12 +125,11 @@ public class AuthorizationService extends AbstractComponent { } // get the roles of the authenticated user, which may be different than the effective - GlobalPermission permission = permission(authentication.getUser().roles()); - + Collection roles = roles(authentication.getUser()); + GlobalPermission permission = permission(roles); final boolean isRunAs = authentication.getUser() != authentication.getRunAsUser(); - // permission can be null as it might be that the user's role - // is unknown - if (permission == null || permission.isEmpty()) { + // permission can be empty as it might be that the user's role is unknown + if (permission.isEmpty()) { if (isRunAs) { // the request is a run as request so we should call the specific audit event for a denied run as attempt throw denyRunAs(authentication, action, request); @@ -194,18 +137,16 @@ public class AuthorizationService extends AbstractComponent { throw denial(authentication, action, request); } } - // check if the request is a run as request if (isRunAs) { // first we must authorize for the RUN_AS action RunAsPermission runAs = permission.runAs(); if (runAs != null && runAs.check(authentication.getRunAsUser().principal())) { grantRunAs(authentication, action, request); - permission = permission(authentication.getRunAsUser().roles()); - - // permission can be null as it might be that the user's role - // is unknown - if (permission == null || permission.isEmpty()) { + roles = roles(authentication.getRunAsUser()); + permission = permission(roles); + // permission can be empty as it might be that the run as user's role is unknown + if (permission.isEmpty()) { throw denial(authentication, action, request); } } else { @@ -213,8 +154,7 @@ public class AuthorizationService extends AbstractComponent { } } - // first, we'll check if the action is a cluster action. If it is, we'll only check it - // against the cluster permissions + // first, we'll check if the action is a cluster action. If it is, we'll only check it against the cluster permissions if (ClusterPrivilege.ACTION_MATCHER.test(action)) { ClusterPermission cluster = permission.cluster(); // we use the effectiveUser for permission checking since we are running as a user! @@ -235,7 +175,7 @@ public class AuthorizationService extends AbstractComponent { if (isCompositeAction(action)) { if (request instanceof CompositeIndicesRequest == false) { throw new IllegalStateException("Composite actions must implement " + CompositeIndicesRequest.class.getSimpleName() - + ", " + request.getClass().getSimpleName() + " doesn't"); + + ", " + request.getClass().getSimpleName() + " doesn't"); } //we check if the user can execute the action, without looking at indices, whici will be authorized at the shard level if (permission.indices().check(action)) { @@ -267,19 +207,19 @@ public class AuthorizationService extends AbstractComponent { throw denial(authentication, action, request); } - ClusterState clusterState = clusterService.state(); - Set indexNames = resolveIndices(authentication, action, request, clusterState); + MetaData metaData = clusterService.state().metaData(); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getRunAsUser(), roles, action, metaData); + Set indexNames = indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices); assert !indexNames.isEmpty() : "every indices request needs to have its indices set thus the resolved indices must not be empty"; //all wildcard expressions have been resolved and only the security plugin could have set '-*' here. //'-*' matches no indices so we allow the request to go through, which will yield an empty response - if (indexNames.size() == 1 && indexNames.contains(DefaultIndicesAndAliasesResolver.NO_INDEX)) { + if (indexNames.size() == 1 && indexNames.contains(IndicesAndAliasesResolver.NO_INDEX)) { setIndicesAccessControl(IndicesAccessControl.ALLOW_NO_INDICES); grant(authentication, action, request); return; } - MetaData metaData = clusterState.metaData(); IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData); if (!indicesAccessControl.isGranted()) { throw denial(authentication, action, request); @@ -331,38 +271,32 @@ public class AuthorizationService extends AbstractComponent { } } - private GlobalPermission permission(String[] roleNames) { - final String[] anonymousRoles = isAnonymousEnabled ? anonymousUser.roles() : Strings.EMPTY_ARRAY; - if (roleNames.length == 0) { - if (anonymousRoles.length == 0) { - assert isAnonymousEnabled == false : "anonymous is only enabled when the anonymous user has roles"; - return DefaultRole.INSTANCE; - } + private GlobalPermission permission(Collection roles) { + GlobalPermission.Compound.Builder rolesBuilder = GlobalPermission.Compound.builder(); + for (Role role : roles) { + rolesBuilder.add(role); } + return rolesBuilder.build(); + } - // we'll take all the roles and combine their associated permissions - final Set uniqueNames = new HashSet<>(Arrays.asList(roleNames)); - uniqueNames.addAll(Arrays.asList(anonymousRoles)); - - GlobalPermission.Compound.Builder roles = GlobalPermission.Compound.builder().add(DefaultRole.INSTANCE); - for (String roleName : uniqueNames) { + Collection roles(User user) { + Set roleNames = new HashSet<>(); + Collections.addAll(roleNames, user.roles()); + if (isAnonymousEnabled && anonymousUser.equals(user) == false) { + if (anonymousUser.roles().length == 0) { + throw new IllegalStateException("anonymous is only enabled when the anonymous user has roles"); + } + Collections.addAll(roleNames, anonymousUser.roles()); + } + List roles = new ArrayList<>(); + roles.add(DefaultRole.INSTANCE); + for (String roleName : roleNames) { Role role = rolesStore.role(roleName); if (role != null) { roles.add(role); } } - return roles.build(); - } - - private Set resolveIndices(Authentication authentication, String action, TransportRequest request, ClusterState clusterState) { - MetaData metaData = clusterState.metaData(); - for (IndicesAndAliasesResolver resolver : indicesAndAliasesResolvers) { - if (resolver.requestType().isInstance(request)) { - return resolver.resolve(authentication.getRunAsUser(), action, request, metaData); - } - } - assert false : "we should be able to resolve indices for any known request that requires indices privileges"; - throw denial(authentication, action, request); + return Collections.unmodifiableList(roles); } private static boolean isCompositeAction(String action) { diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java new file mode 100644 index 00000000000..86a60ce2283 --- /dev/null +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizedIndices.java @@ -0,0 +1,76 @@ +/* + * 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.security.authz; + +import org.elasticsearch.cluster.metadata.AliasOrIndex; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.xpack.security.SecurityTemplateService; +import org.elasticsearch.xpack.security.authz.permission.Role; +import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; +import org.elasticsearch.xpack.security.user.User; +import org.elasticsearch.xpack.security.user.XPackUser; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +/** + * 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 Collection userRoles; + private List authorizedIndices; + + AuthorizedIndices(User user, Collection userRoles, String action, MetaData metaData) { + this.user = user; + this.userRoles = userRoles; + this.action = action; + this.metaData = metaData; + } + + List get() { + if (authorizedIndices == null) { + authorizedIndices = load(); + } + return authorizedIndices; + } + + private List load() { + if (userRoles.isEmpty()) { + return Collections.emptyList(); + } + + List> predicates = new ArrayList<>(); + for (Role userRole : userRoles) { + predicates.add(userRole.indices().allowedIndicesMatcher(action)); + } + + Predicate predicate = predicates.stream().reduce(s -> false, Predicate::or); + + 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 (XPackUser.is(user) == false && Arrays.binarySearch(user.roles(), SuperuserRole.NAME) < 0) { + // we should filter out the .security index from wildcards + indicesAndAliases.remove(SecurityTemplateService.SECURITY_INDEX_NAME); + } + return Collections.unmodifiableList(indicesAndAliases); + } +} diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java similarity index 86% rename from elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java rename to elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java index cd9ebd13746..111e0fac696 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolver.java @@ -3,7 +3,7 @@ * 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.security.authz.indicesresolver; +package org.elasticsearch.xpack.security.authz; import org.elasticsearch.action.AliasesRequest; import org.elasticsearch.action.IndicesRequest; @@ -20,8 +20,6 @@ import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.transport.TransportRequest; -import org.elasticsearch.xpack.security.authz.AuthorizationService; -import org.elasticsearch.xpack.security.user.User; import java.util.ArrayList; import java.util.Arrays; @@ -32,31 +30,23 @@ import java.util.Set; import java.util.SortedMap; import java.util.stream.Collectors; -public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolver { +public class IndicesAndAliasesResolver { public static final String NO_INDEX = "-*"; private static final List NO_INDICES = Collections.singletonList(NO_INDEX); - private final AuthorizationService authzService; private final IndexNameExpressionResolver nameExpressionResolver; - public DefaultIndicesAndAliasesResolver(AuthorizationService authzService, IndexNameExpressionResolver nameExpressionResolver) { - this.authzService = authzService; + public IndicesAndAliasesResolver(IndexNameExpressionResolver nameExpressionResolver) { this.nameExpressionResolver = nameExpressionResolver; } - @Override - public Class requestType() { - return TransportRequest.class; - } - - @Override - public Set resolve(User user, String action, TransportRequest request, MetaData metaData) { + public Set resolve(TransportRequest request, MetaData metaData, AuthorizedIndices authorizedIndices) { if (request instanceof IndicesAliasesRequest) { Set indices = new HashSet<>(); IndicesAliasesRequest indicesAliasesRequest = (IndicesAliasesRequest) request; for (IndicesRequest indicesRequest : indicesAliasesRequest.getAliasActions()) { - indices.addAll(resolveIndicesAndAliases(user, action, indicesRequest, metaData)); + indices.addAll(resolveIndicesAndAliases(indicesRequest, metaData, authorizedIndices)); } return indices; } @@ -65,10 +55,11 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv if (request instanceof IndicesRequest == false) { throw new IllegalStateException("Request [" + request + "] is not an Indices request, but should be."); } - return resolveIndicesAndAliases(user, action, (IndicesRequest) request, metaData); + return resolveIndicesAndAliases((IndicesRequest) request, metaData, authorizedIndices); } - private Set resolveIndicesAndAliases(User user, String action, IndicesRequest indicesRequest, MetaData metaData) { + private Set resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData metaData, + AuthorizedIndices authorizedIndices) { boolean indicesReplacedWithNoIndices = false; final Set indices; if (indicesRequest instanceof PutMappingRequest @@ -85,8 +76,6 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv IndicesRequest.Replaceable replaceable = (IndicesRequest.Replaceable) indicesRequest; final boolean replaceWildcards = indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed(); - List authorizedIndicesAndAliases = authzService.authorizedIndicesAndAliases(user, action); - IndicesOptions indicesOptions = indicesRequest.indicesOptions(); if (indicesRequest instanceof IndicesExistsRequest) { //indices exists api should never throw exception, make sure that ignore_unavailable and allow_no_indices are true @@ -99,7 +88,7 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv // check for all and return list of authorized indices if (IndexNameExpressionResolver.isAllIndices(indicesList(indicesRequest.indices()))) { if (replaceWildcards) { - for (String authorizedIndex : authorizedIndicesAndAliases) { + for (String authorizedIndex : authorizedIndices.get()) { if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) { replacedIndices.add(authorizedIndex); } @@ -109,11 +98,11 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv // we honour allow_no_indices like es core does. } else { replacedIndices = replaceWildcardsWithAuthorizedIndices(indicesRequest.indices(), - indicesOptions, metaData, authorizedIndicesAndAliases, replaceWildcards); + indicesOptions, metaData, authorizedIndices.get(), replaceWildcards); if (indicesOptions.ignoreUnavailable()) { //out of all the explicit names (expanded from wildcards and original ones that were left untouched) //remove all the ones that the current user is not authorized for and ignore them - replacedIndices = replacedIndices.stream().filter(authorizedIndicesAndAliases::contains).collect(Collectors.toList()); + replacedIndices = replacedIndices.stream().filter(authorizedIndices.get()::contains).collect(Collectors.toList()); } } if (replacedIndices.isEmpty()) { @@ -149,18 +138,19 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv //AliasesRequest extends IndicesRequest.Replaceable, hence its indices have already been properly replaced. AliasesRequest aliasesRequest = (AliasesRequest) indicesRequest; if (aliasesRequest.expandAliasesWildcards()) { - List authorizedIndices = authzService.authorizedIndicesAndAliases(user, action); - List aliases = replaceWildcardsWithAuthorizedAliases(aliasesRequest.aliases(), loadAuthorizedAliases - (authorizedIndices, metaData)); + List aliases = replaceWildcardsWithAuthorizedAliases(aliasesRequest.aliases(), + loadAuthorizedAliases(authorizedIndices.get(), metaData)); aliasesRequest.aliases(aliases.toArray(new String[aliases.size()])); } if (indicesReplacedWithNoIndices) { - assert indicesRequest instanceof GetAliasesRequest : GetAliasesRequest.class.getSimpleName() + " is the only known " + - "request implementing " + AliasesRequest.class.getSimpleName() + " that may allow no indices. Found [" + - indicesRequest.getClass().getName() + "] which ended up with an empty set of indices."; + if (indicesRequest instanceof GetAliasesRequest == false) { + throw new IllegalStateException(GetAliasesRequest.class.getSimpleName() + " is the only known " + + "request implementing " + AliasesRequest.class.getSimpleName() + " that may allow no indices. Found [" + + indicesRequest.getClass().getName() + "] which ended up with an empty set of indices."); + } + //if we replaced the indices with '-*' we shouldn't be adding the aliases to the list otherwise the request will + //not get authorized. Leave only '-*' and ignore the rest, result will anyway be empty. } else { - //if we are returning '-*' we shouldn't be adding the aliases to the list or the request will not get authorized. - //Leave only '-*' and ignore the rest, result will anyway be empty. Collections.addAll(indices, aliasesRequest.aliases()); } } @@ -203,10 +193,11 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv } } - //throw exception if the wildcards expansion to authorized aliases resulted in no indices. - // This is important as we always need to replace wildcards for security reason, - //to make sure that the operation is executed on the aliases that we authorized it to execute on. - //If we can't replace because we got an empty set, we can only throw exception. + //Throw exception if the wildcards expansion to authorized aliases resulted in no indices. + //We always need to replace wildcards for security reasons, to make sure that the operation is executed on the aliases that we + //authorized it to execute on. Empty set gets converted to _all by es core though, and unlike with indices, here we don't have + //a special expression to replace empty set with, which gives us the guarantee that nothing will be returned. + //This is because existing aliases can contain all kinds of special characters, they are only validated since 5.1. if (finalAliases.isEmpty()) { String indexName = matchAllAliases ? MetaData.ALL : Arrays.toString(aliases); throw new IndexNotFoundException(indexName); diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java index 71349af6b79..024b3e2d03b 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/accesscontrol/IndicesAccessControl.java @@ -7,7 +7,7 @@ package org.elasticsearch.xpack.security.authz.accesscontrol; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; +import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver; import org.elasticsearch.xpack.security.authz.permission.FieldPermissions; import java.util.Collections; @@ -24,7 +24,7 @@ public class IndicesAccessControl { public static final IndicesAccessControl ALLOW_ALL = new IndicesAccessControl(true, Collections.emptyMap()); public static final IndicesAccessControl ALLOW_NO_INDICES = new IndicesAccessControl(true, - Collections.singletonMap(DefaultIndicesAndAliasesResolver.NO_INDEX, + Collections.singletonMap(IndicesAndAliasesResolver.NO_INDEX, new IndicesAccessControl.IndexAccessControl(true, new FieldPermissions(), null))); private final boolean granted; diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolver.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolver.java deleted file mode 100644 index 19f67af90ee..00000000000 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolver.java +++ /dev/null @@ -1,20 +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.security.authz.indicesresolver; - -import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.transport.TransportRequest; - -import java.util.Set; - -public interface IndicesAndAliasesResolver { - - Class requestType(); - - Set resolve(User user, String action, Request request, MetaData metaData); - -} diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 87fb465b6cc..9557bd8b6b1 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -61,7 +61,6 @@ import org.elasticsearch.action.termvectors.TermVectorsRequest; import org.elasticsearch.action.update.UpdateAction; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.service.ClusterService; @@ -77,7 +76,7 @@ import org.elasticsearch.xpack.security.authc.Authentication; import org.elasticsearch.xpack.security.authc.Authentication.RealmRef; import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler; import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl; -import org.elasticsearch.xpack.security.authz.indicesresolver.DefaultIndicesAndAliasesResolver; +import org.elasticsearch.xpack.security.authz.permission.DefaultRole; import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; @@ -92,6 +91,7 @@ import org.junit.Before; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -99,8 +99,9 @@ import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationExce import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs; import static org.hamcrest.Matchers.arrayContaining; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.either; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.mockito.Mockito.mock; @@ -172,6 +173,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testNoRolesCausesDenial() { TransportRequest request = new SearchRequest(); User user = new User("test user"); + mockEmptyMetaData(); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(user), "indices:a", request), "indices:a", "test user"); @@ -182,6 +184,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testUnknownRoleCausesDenial() { TransportRequest request = new SearchRequest(); User user = new User("test user", "non-existent-role"); + mockEmptyMetaData(); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(user), "indices:a", request), "indices:a", "test user"); @@ -205,6 +208,7 @@ public class AuthorizationServiceTests extends ESTestCase { TransportRequest request = new IndicesExistsRequest("a"); User user = new User("test user", "no_indices"); when(rolesStore.role("no_indices")).thenReturn(Role.builder("no_indices").cluster(ClusterPrivilege.action("")).build()); + mockEmptyMetaData(); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(user), "indices:a", request), @@ -216,9 +220,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testSearchAgainstEmptyCluster() { User user = new User("test user", "a_all"); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build()); - ClusterState state = mock(ClusterState.class); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); + mockEmptyMetaData(); { //ignore_unavailable set to false, user is not authorized for this index nor does it exist @@ -240,7 +242,7 @@ public class AuthorizationServiceTests extends ESTestCase { verify(auditTrail).accessGranted(user, SearchAction.NAME, searchRequest); IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY); IndicesAccessControl.IndexAccessControl indexAccessControl = - indicesAccessControl.getIndexPermissions(DefaultIndicesAndAliasesResolver.NO_INDEX); + indicesAccessControl.getIndexPermissions(IndicesAndAliasesResolver.NO_INDEX); assertFalse(indexAccessControl.getFieldPermissions().hasFieldLevelSecurity()); assertNull(indexAccessControl.getQueries()); } @@ -249,6 +251,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testScrollRelatedRequestsAllowed() { User user = new User("test user", "a_all"); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_role").add(IndexPrivilege.ALL, "a").build()); + mockEmptyMetaData(); ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); authorizationService.authorize(createAuthentication(user), ClearScrollAction.NAME, clearScrollRequest); @@ -280,29 +283,25 @@ public class AuthorizationServiceTests extends ESTestCase { public void testAuthorizeIndicesFailures() { TransportRequest request = new GetIndexRequest().indices("b"); - ClusterState state = mock(ClusterState.class); + ClusterState state = mockEmptyMetaData(); User user = new User("test user", "a_all"); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(user), "indices:a", request), "indices:a", "test user"); verify(auditTrail).accessDenied(user, "indices:a", request); verifyNoMoreInteractions(auditTrail); - verify(clusterService, times(2)).state(); - verify(state, times(3)).metaData(); + verify(clusterService, times(1)).state(); + verify(state, times(1)).metaData(); } public void testCreateIndexWithAliasWithoutPermissions() { CreateIndexRequest request = new CreateIndexRequest("a"); request.alias(new Alias("a2")); - ClusterState state = mock(ClusterState.class); + ClusterState state = mockEmptyMetaData(); User user = new User("test user", "a_all"); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request), @@ -310,84 +309,46 @@ public class AuthorizationServiceTests extends ESTestCase { verify(auditTrail).accessDenied(user, IndicesAliasesAction.NAME, request); verifyNoMoreInteractions(auditTrail); verify(clusterService).state(); - verify(state, times(2)).metaData(); + verify(state, times(1)).metaData(); } public void testCreateIndexWithAlias() { CreateIndexRequest request = new CreateIndexRequest("a"); request.alias(new Alias("a2")); - ClusterState state = mock(ClusterState.class); + ClusterState state = mockEmptyMetaData(); User user = new User("test user", "a_all"); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a", "a2").build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); authorizationService.authorize(createAuthentication(user), CreateIndexAction.NAME, request); verify(auditTrail).accessGranted(user, CreateIndexAction.NAME, request); verifyNoMoreInteractions(auditTrail); verify(clusterService).state(); - verify(state, times(2)).metaData(); - } - - public void testIndicesAliasesWithNoRolesUser() { - User user = new User("test user"); - - List list = authorizationService.authorizedIndicesAndAliases(user, ""); - assertThat(list.isEmpty(), is(true)); - } - - public void testIndicesAliasesWithUserHavingRoles() { - User user = new User("test user", "a_star", "b"); - ClusterState state = mock(ClusterState.class); - when(rolesStore.role("a_star")).thenReturn(Role.builder("a_star").add(IndexPrivilege.ALL, "a*").build()); - when(rolesStore.role("b")).thenReturn(Role.builder("a_star").add(IndexPrivilege.READ, "b").build()); - when(clusterService.state()).thenReturn(state); - Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); - when(state.metaData()).thenReturn(MetaData.builder() - .put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) - .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("b") - .settings(indexSettings) - .numberOfShards(1) - .numberOfReplicas(0) - .putAlias(new AliasMetaData.Builder("ab").build()) - .putAlias(new AliasMetaData.Builder("ba").build()) - .build(), true) - .build()); - - List list = authorizationService.authorizedIndicesAndAliases(user, SearchAction.NAME); - assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab")); - assertThat(list.contains("bbbbb"), is(false)); - assertThat(list.contains("ba"), is(false)); + verify(state, times(1)).metaData(); } public void testDenialForAnonymousUser() { TransportRequest request = new GetIndexRequest().indices("b"); - ClusterState state = mock(ClusterState.class); + ClusterState state = mockEmptyMetaData(); Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, anonymousUser); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); assertThrowsAuthorizationException( () -> authorizationService.authorize(createAuthentication(anonymousUser), "indices:a", request), "indices:a", anonymousUser.principal()); verify(auditTrail).accessDenied(anonymousUser, "indices:a", request); verifyNoMoreInteractions(auditTrail); - verify(clusterService, times(2)).state(); - verify(state, times(3)).metaData(); + verify(clusterService, times(1)).state(); + verify(state, times(1)).metaData(); } public void testDenialForAnonymousUserAuthorizationExceptionDisabled() { TransportRequest request = new GetIndexRequest().indices("b"); - ClusterState state = mock(ClusterState.class); + ClusterState state = mockEmptyMetaData(); Settings settings = Settings.builder() .put(AnonymousUser.ROLES_SETTING.getKey(), "a_all") .put(AuthorizationService.ANONYMOUS_AUTHORIZATION_EXCEPTION_SETTING.getKey(), false) @@ -397,19 +358,14 @@ public class AuthorizationServiceTests extends ESTestCase { new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(settings)); when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); - try { - authorizationService.authorize(createAuthentication(anonymousUser), "indices:a", request); - fail("indices request for b should be denied since there is no such index"); - } catch (ElasticsearchSecurityException e) { - assertAuthenticationException(e, containsString("action [indices:a] requires authentication")); - verify(auditTrail).accessDenied(anonymousUser, "indices:a", request); - verifyNoMoreInteractions(auditTrail); - verify(clusterService, times(2)).state(); - verify(state, times(3)).metaData(); - } + ElasticsearchSecurityException securityException = expectThrows(ElasticsearchSecurityException.class, + () -> authorizationService.authorize(createAuthentication(anonymousUser), "indices:a", request)); + assertAuthenticationException(securityException, containsString("action [indices:a] requires authentication")); + verify(auditTrail).accessDenied(anonymousUser, "indices:a", request); + verifyNoMoreInteractions(auditTrail); + verify(clusterService, times(1)).state(); + verify(state, times(1)).metaData(); } public void testRunAsRequestWithNoRolesUser() { @@ -425,7 +381,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testRunAsRequestRunningAsUnAllowedUser() { TransportRequest request = mock(TransportRequest.class); - User user = new User("test user", new String[] { "can run as" }, new User("run as me", new String[] { "doesn't exist" })); + User user = new User("test user", new String[] { "can run as" }, new User("run as me", "doesn't exist")); assertThat(user.runAs(), is(notNullValue())); when(rolesStore.role("can run as")).thenReturn(Role .builder("can run as") @@ -462,6 +418,8 @@ public class AuthorizationServiceTests extends ESTestCase { .builder("b") .add(IndexPrivilege.ALL, "b") .build()); + } else { + mockEmptyMetaData(); } assertThrowsAuthorizationExceptionRunAs( @@ -474,7 +432,7 @@ public class AuthorizationServiceTests extends ESTestCase { public void testRunAsRequestWithValidPermissions() { TransportRequest request = new GetIndexRequest().indices("b"); - User user = new User("test user", new String[] { "can run as" }, new User("run as me", new String[] { "b" })); + User user = new User("test user", new String[] { "can run as" }, new User("run as me", "b")); assertThat(user.runAs(), is(notNullValue())); when(rolesStore.role("can run as")).thenReturn(Role .builder("can run as") @@ -551,7 +509,7 @@ public class AuthorizationServiceTests extends ESTestCase { SearchRequest searchRequest = new SearchRequest("_all"); authorizationService.authorize(createAuthentication(user), SearchAction.NAME, searchRequest); assertEquals(1, searchRequest.indices().length); - assertEquals(DefaultIndicesAndAliasesResolver.NO_INDEX, searchRequest.indices()[0]); + assertEquals(IndicesAndAliasesResolver.NO_INDEX, searchRequest.indices()[0]); } public void testGrantedNonXPackUserCanExecuteMonitoringOperationsAgainstSecurityIndex() { @@ -649,19 +607,16 @@ public class AuthorizationServiceTests extends ESTestCase { public void testAnonymousRolesAreAppliedToOtherUsers() { TransportRequest request = new ClusterHealthRequest(); - ClusterState state = mock(ClusterState.class); Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "anonymous_user_role").build(); final AnonymousUser anonymousUser = new AnonymousUser(settings); authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, anonymousUser); - when(rolesStore.role("anonymous_user_role")) .thenReturn(Role.builder("anonymous_user_role") .cluster(ClusterPrivilege.ALL) .add(IndexPrivilege.ALL, "a") .build()); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(MetaData.EMPTY_META_DATA); + mockEmptyMetaData(); // sanity check the anonymous user authorizationService.authorize(createAuthentication(anonymousUser), ClusterHealthAction.NAME, request); @@ -673,6 +628,43 @@ public class AuthorizationServiceTests extends ESTestCase { authorizationService.authorize(createAuthentication(userWithNoRoles), IndicesExistsAction.NAME, new IndicesExistsRequest("a")); } + public void testDefaultRoleUserWithoutRoles() { + Collection roles = authorizationService.roles(new User("no role user")); + assertEquals(1, roles.size()); + assertEquals(DefaultRole.NAME, roles.iterator().next().name()); + } + + public void testDefaultRoleUserWithoutRolesAnonymousUserEnabled() { + Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "anonymous_user_role").build(); + final AnonymousUser anonymousUser = new AnonymousUser(settings); + authorizationService = new AuthorizationService(settings, rolesStore, clusterService, auditTrail, + new DefaultAuthenticationFailureHandler(), threadPool, anonymousUser); + when(rolesStore.role("anonymous_user_role")) + .thenReturn(Role.builder("anonymous_user_role") + .cluster(ClusterPrivilege.ALL) + .add(IndexPrivilege.ALL, "a") + .build()); + mockEmptyMetaData(); + Collection roles = authorizationService.roles(new User("no role user")); + assertEquals(2, roles.size()); + for (Role role : roles) { + assertThat(role.name(), either(equalTo(DefaultRole.NAME)).or(equalTo("anonymous_user_role"))); + } + } + + public void testDefaultRoleUserWithSomeRole() { + when(rolesStore.role("role")) + .thenReturn(Role.builder("role") + .cluster(ClusterPrivilege.ALL) + .add(IndexPrivilege.ALL, "a") + .build()); + Collection roles = authorizationService.roles(new User("user with role", "role")); + assertEquals(2, roles.size()); + for (Role role : roles) { + assertThat(role.name(), either(equalTo(DefaultRole.NAME)).or(equalTo("role"))); + } + } + public void testCompositeActionsAreImmediatelyRejected() { //if the user has no permission for composite actions against any index, the request fails straight-away in the main action Tuple compositeRequest = randomCompositeRequest(); @@ -782,7 +774,6 @@ public class AuthorizationServiceTests extends ESTestCase { } private static class MockCompositeIndicesRequest extends TransportRequest implements CompositeIndicesRequest { - @Override public List subRequests() { return Collections.singletonList(new MockIndicesRequest()); @@ -793,7 +784,7 @@ public class AuthorizationServiceTests extends ESTestCase { RealmRef lookedUpBy = user.runAs() == null ? null : new RealmRef("looked", "up", "by"); return new Authentication(user, new RealmRef("test", "test", "foo"), lookedUpBy); } - + private ClusterState mockEmptyMetaData() { ClusterState state = mock(ClusterState.class); when(clusterService.state()).thenReturn(state); diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java new file mode 100644 index 00000000000..3ae44471c90 --- /dev/null +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizedIndicesTests.java @@ -0,0 +1,69 @@ +/* + * 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.security.authz; + +import org.elasticsearch.Version; +import org.elasticsearch.action.search.SearchAction; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.security.authz.permission.Role; +import org.elasticsearch.xpack.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.security.user.User; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.Matchers.containsInAnyOrder; + +public class AuthorizedIndicesTests extends ESTestCase { + + public void testAuthorizedIndicesUserWithoutRoles() { + User user = new User("test user"); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, Collections.emptyList(), "", MetaData.EMPTY_META_DATA); + List list = authorizedIndices.get(); + assertTrue(list.isEmpty()); + } + + public void testAuthorizedIndicesUserWithSomeRoles() { + User user = new User("test user", "a_star", "b"); + Role aStarRole = Role.builder("a_star").add(IndexPrivilege.ALL, "a*").build(); + Role bRole = Role.builder("b").add(IndexPrivilege.READ, "b").build(); + Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); + MetaData metaData = MetaData.builder() + .put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) + .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("b") + .settings(indexSettings) + .numberOfShards(1) + .numberOfReplicas(0) + .putAlias(new AliasMetaData.Builder("ab").build()) + .putAlias(new AliasMetaData.Builder("ba").build()) + .build(), true) + .build(); + Collection roles = Arrays.asList(aStarRole, bRole); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, roles, SearchAction.NAME, metaData); + List list = authorizedIndices.get(); + assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab")); + assertFalse(list.contains("bbbbb")); + assertFalse(list.contains("ba")); + } + + public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() { + User user = new User("test user", "role"); + Role role = Role.builder("role").add(IndexPrivilege.ALL, "*").build(); + Collection roles = Collections.singletonList(role); + AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, roles, SearchAction.NAME, MetaData.EMPTY_META_DATA); + List list = authorizedIndices.get(); + assertTrue(list.isEmpty()); + } +} diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java similarity index 82% rename from elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java rename to elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java index 648072f415f..72fce6616a0 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java @@ -3,7 +3,7 @@ * 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.security.authz.indicesresolver; +package org.elasticsearch.xpack.security.authz; import org.elasticsearch.Version; import org.elasticsearch.action.IndicesRequest; @@ -24,7 +24,6 @@ import org.elasticsearch.action.search.SearchAction; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.termvectors.MultiTermVectorsRequest; -import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -38,7 +37,6 @@ import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.xpack.security.SecurityTemplateService; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler; -import org.elasticsearch.xpack.security.authz.AuthorizationService; import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.permission.SuperuserRole; import org.elasticsearch.xpack.security.authz.privilege.ClusterPrivilege; @@ -49,24 +47,26 @@ import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.XPackUser; import org.junit.Before; +import java.util.Collection; +import java.util.List; import java.util.Set; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class DefaultIndicesResolverTests extends ESTestCase { +public class IndicesAndAliasesResolverTests extends ESTestCase { private User user; private User userNoIndices; private CompositeRolesStore rolesStore; private MetaData metaData; - private DefaultIndicesAndAliasesResolver defaultIndicesResolver; + private AuthorizationService authzService; + private IndicesAndAliasesResolver defaultIndicesResolver; private IndexNameExpressionResolver indexNameExpressionResolver; @Before @@ -78,7 +78,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { .build(); indexNameExpressionResolver = new IndexNameExpressionResolver(Settings.EMPTY); - MetaData.Builder mdBuilder = MetaData.builder() + metaData = MetaData.builder() .put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar")).settings(settings)) .put(indexBuilder("foobar").putAlias(AliasMetaData.builder("foofoobar")).settings(settings)) .put(indexBuilder("closed").state(IndexMetaData.State.CLOSE) @@ -90,8 +90,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { .put(indexBuilder("bar-closed").state(IndexMetaData.State.CLOSE).settings(settings)) .put(indexBuilder("bar2").settings(settings)) .put(indexBuilder(indexNameExpressionResolver.resolveDateMathExpression("")).settings(settings)) - .put(indexBuilder(SecurityTemplateService.SECURITY_INDEX_NAME).settings(settings)); - metaData = mdBuilder.build(); + .put(indexBuilder(SecurityTemplateService.SECURITY_INDEX_NAME).settings(settings)).build(); user = new User("user", "role"); userNoIndices = new User("test", "test"); @@ -101,20 +100,16 @@ public class DefaultIndicesResolverTests extends ESTestCase { when(rolesStore.role("test")).thenReturn(Role.builder("test").cluster(ClusterPrivilege.MONITOR).build()); when(rolesStore.role(SuperuserRole.NAME)).thenReturn(Role.builder(SuperuserRole.DESCRIPTOR).build()); ClusterService clusterService = mock(ClusterService.class); - ClusterState state = mock(ClusterState.class); - when(clusterService.state()).thenReturn(state); - when(state.metaData()).thenReturn(metaData); - - AuthorizationService authzService = new AuthorizationService(settings, rolesStore, clusterService, + authzService = new AuthorizationService(settings, rolesStore, clusterService, mock(AuditTrailService.class), new DefaultAuthenticationFailureHandler(), mock(ThreadPool.class), new AnonymousUser(settings)); - defaultIndicesResolver = new DefaultIndicesAndAliasesResolver(authzService, indexNameExpressionResolver); + defaultIndicesResolver = new IndicesAndAliasesResolver(indexNameExpressionResolver); } public void testResolveEmptyIndicesExpandWilcardsOpenAndClosed() { SearchRequest request = new SearchRequest(); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -125,7 +120,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveEmptyIndicesExpandWilcardsOpen() { SearchRequest request = new SearchRequest(); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -136,7 +131,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveAllExpandWilcardsOpenAndClosed() { SearchRequest request = new SearchRequest("_all"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -147,7 +142,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveAllExpandWilcardsOpen() { SearchRequest request = new SearchRequest("_all"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -158,7 +153,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsStrictExpand() { SearchRequest request = new SearchRequest("barbaz", "foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -169,7 +164,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsExpandOpenAndClosedIgnoreUnavailable() { SearchRequest request = new SearchRequest("barbaz", "foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -180,7 +175,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsStrictExpandOpen() { SearchRequest request = new SearchRequest("barbaz", "foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -191,7 +186,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsLenientExpandOpen() { SearchRequest request = new SearchRequest("barbaz", "foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"foofoobar", "foofoo"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -202,7 +197,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsMinusExpandWilcardsOpen() { SearchRequest request = new SearchRequest("-foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -213,7 +208,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsMinusExpandWilcardsOpenAndClosed() { SearchRequest request = new SearchRequest("-foofoo*"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "bar-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -224,7 +219,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenStrict() { SearchRequest request = new SearchRequest("-foofoo*", "+barbaz", "+foob*"); request.indicesOptions(IndicesOptions.fromOptions(false, true, true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "barbaz"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -235,7 +230,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenIgnoreUnavailable() { SearchRequest request = new SearchRequest("-foofoo*", "+barbaz", "+foob*"); request.indicesOptions(IndicesOptions.fromOptions(true, true, true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -246,7 +241,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenAndClosedStrict() { SearchRequest request = new SearchRequest("-foofoo*", "+barbaz"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -257,7 +252,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveWildcardsPlusAndMinusExpandWilcardsOpenAndClosedIgnoreUnavailable() { SearchRequest request = new SearchRequest("-foofoo*", "+barbaz"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, true)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar", "bar-closed"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -268,21 +263,21 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveNonMatchingIndicesAllowNoIndices() { SearchRequest request = new SearchRequest("missing*"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); - assertNoIndices(request, defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); } public void testResolveNonMatchingIndicesDisallowNoIndices() { SearchRequest request = new SearchRequest("missing*"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), false, true, randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); assertEquals("no such index", e.getMessage()); } public void testResolveExplicitIndicesStrict() { SearchRequest request = new SearchRequest("missing", "bar", "barbaz"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean())); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"missing", "bar", "barbaz"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -293,7 +288,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveExplicitIndicesIgnoreUnavailable() { SearchRequest request = new SearchRequest("missing", "bar", "barbaz"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), randomBoolean(), randomBoolean())); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] replacedIndices = new String[]{"bar"}; assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(request.indices().length, equalTo(replacedIndices.length)); @@ -304,21 +299,22 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveNoAuthorizedIndicesAllowNoIndices() { SearchRequest request = new SearchRequest(); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); - assertNoIndices(request, defaultIndicesResolver.resolve(userNoIndices, SearchAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(userNoIndices, SearchAction.NAME))); } public void testResolveNoAuthorizedIndicesDisallowNoIndices() { SearchRequest request = new SearchRequest(); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), false, true, randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(userNoIndices, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userNoIndices, SearchAction.NAME))); assertEquals("no such index", e.getMessage()); } public void testResolveMissingIndexStrict() { SearchRequest request = new SearchRequest("bar*", "missing"); request.indicesOptions(IndicesOptions.fromOptions(false, true, true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] expectedIndices = new String[]{"bar", "missing"}; assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(request.indices().length, equalTo(expectedIndices.length)); @@ -329,7 +325,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveMissingIndexIgnoreUnavailable() { SearchRequest request = new SearchRequest("bar*", "missing"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] expectedIndices = new String[]{"bar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(request.indices().length, equalTo(expectedIndices.length)); @@ -340,7 +336,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveNonMatchingIndicesAndExplicit() { SearchRequest request = new SearchRequest("missing*", "bar"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] expectedIndices = new String[]{"bar"}; assertThat(indices.toArray(new String[indices.size()]), equalTo(expectedIndices)); assertThat(request.indices(), equalTo(expectedIndices)); @@ -349,7 +345,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveNoExpandStrict() { SearchRequest request = new SearchRequest("missing*"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), false, false)); - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); String[] expectedIndices = new String[]{"missing*"}; assertThat(indices.toArray(new String[indices.size()]), equalTo(expectedIndices)); assertThat(request.indices(), equalTo(expectedIndices)); @@ -358,14 +354,14 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveNoExpandIgnoreUnavailable() { SearchRequest request = new SearchRequest("missing*"); request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false)); - assertNoIndices(request, defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); } public void testResolveIndicesAliasesRequest() { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").indices("foo", "foofoo")); request.addAliasAction(AliasActions.add().alias("alias2").indices("foo", "foobar")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all indices and aliases gets returned String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -380,7 +376,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").indices("foo", "foofoo")); request.addAliasAction(AliasActions.add().alias("foofoobar").indices("foo", "foobar")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all indices and aliases gets returned, foofoobar is an existing alias but that doesn't make any difference String[] expectedIndices = new String[]{"alias1", "foofoobar", "foo", "foofoo", "foobar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -395,7 +391,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").indices("foo", "foofoo")); request.addAliasAction(AliasActions.add().alias("alias2").index("missing")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all indices and aliases gets returned, missing is not an existing index/alias but that doesn't make any difference String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "missing"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -410,7 +406,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").index("foo*")); request.addAliasAction(AliasActions.add().alias("alias2").index("bar*")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for String[] expectedIndices = new String[]{"alias1", "alias2", "foofoo", "foofoobar", "bar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -428,19 +424,15 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.addAliasAction(AliasActions.add().alias("alias2").index("bar*")); request.addAliasAction(AliasActions.add().alias("alias3").index("non_matching_*")); //if a single operation contains wildcards and ends up being resolved to no indices, it makes the whole request fail - try { - defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); - fail("Expected IndexNotFoundException"); - } catch (IndexNotFoundException e) { - assertThat(e.getMessage(), is("no such index")); - } + expectThrows(IndexNotFoundException.class, + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME))); } public void testResolveAllIndicesAliasesRequest() { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").index("_all")); request.addAliasAction(AliasActions.add().alias("alias2").index("_all")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo", "alias1", "alias2"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -457,31 +449,23 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").index("_all")); //current user is not authorized for any index, _all resolves to no indices, the request fails - try { - defaultIndicesResolver.resolve(userNoIndices, IndicesAliasesAction.NAME, request, metaData); - fail("Expected IndexNotFoundException"); - } catch (IndexNotFoundException e) { - assertThat(e.getMessage(), is("no such index")); - } + expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve( + request, metaData, buildAuthorizedIndices(userNoIndices, IndicesAliasesAction.NAME))); } public void testResolveWildcardsIndicesAliasesRequestNoAuthorizedIndices() { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.add().alias("alias1").index("foo*")); //current user is not authorized for any index, foo* resolves to no indices, the request fails - try { - defaultIndicesResolver.resolve(userNoIndices, IndicesAliasesAction.NAME, request, metaData); - fail("Expected IndexNotFoundException"); - } catch (IndexNotFoundException e) { - assertThat(e.getMessage(), is("no such index")); - } + expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve( + request, metaData, buildAuthorizedIndices(userNoIndices, IndicesAliasesAction.NAME))); } public void testResolveIndicesAliasesRequestDeleteActions() { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("foo").alias("foofoobar")); request.addAliasAction(AliasActions.remove().index("foofoo").alias("barbaz")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all indices and aliases gets returned String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -496,7 +480,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("foo").alias("foofoobar")); request.addAliasAction(AliasActions.remove().index("missing_index").alias("missing_alias")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //the union of all indices and aliases gets returned, doesn't matter is some of them don't exist String[] expectedIndices = new String[]{"foo", "foofoobar", "missing_index", "missing_alias"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -511,7 +495,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("foo*").alias("foofoobar")); request.addAliasAction(AliasActions.remove().index("bar*").alias("barbaz")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //union of all resolved indices and aliases gets returned, based on what user is authorized for String[] expectedIndices = new String[]{"foofoobar", "foofoo", "bar", "barbaz"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -527,7 +511,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("*").alias("foo*")); request.addAliasAction(AliasActions.remove().index("*bar").alias("foo*")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //union of all resolved indices and aliases gets returned, based on what user is authorized for //note that the index side will end up containing matching aliases too, which is fine, as es core would do //the same and resolve those aliases to their corresponding concrete indices (which we let core do) @@ -545,7 +529,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("*").alias("_all")); request.addAliasAction(AliasActions.remove().index("_all").aliases("_all", "explicit")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //union of all resolved indices and aliases gets returned, based on what user is authorized for //note that the index side will end up containing matching aliases too, which is fine, as es core would do //the same and resolve those aliases to their corresponding concrete indices (which we let core do) @@ -564,19 +548,15 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.addAliasAction(AliasActions.remove().index("foo*").alias("foo*")); //no authorized aliases match bar*, hence this action fails and makes the whole request fail request.addAliasAction(AliasActions.remove().index("*bar").alias("bar*")); - try { - defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); - fail("Expected IndexNotFoundException"); - } catch (IndexNotFoundException e) { - assertThat(e.getMessage(), is("no such index")); - } + expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve( + request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME))); } public void testResolveWildcardsIndicesAliasesRequestAddAndDeleteActions() { IndicesAliasesRequest request = new IndicesAliasesRequest(); request.addAliasAction(AliasActions.remove().index("foo*").alias("foofoobar")); request.addAliasAction(AliasActions.add().index("bar*").alias("foofoobar")); - Set indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)); //union of all resolved indices and aliases gets returned, based on what user is authorized for String[] expectedIndices = new String[]{"foofoobar", "foofoo", "bar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -591,7 +571,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveGetAliasesRequestStrict() { GetAliasesRequest request = new GetAliasesRequest("alias1").indices("foo", "foofoo"); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean())); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all indices and aliases gets returned String[] expectedIndices = new String[]{"alias1", "foo", "foofoo"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -603,7 +583,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testResolveGetAliasesRequestIgnoreUnavailable() { GetAliasesRequest request = new GetAliasesRequest("alias1").indices("foo", "foofoo"); request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), randomBoolean(), randomBoolean())); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); String[] expectedIndices = new String[]{"alias1", "foofoo"}; assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices, hasItems(expectedIndices)); @@ -616,7 +596,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, randomBoolean())); request.indices("missing"); request.aliases("alias2"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all indices and aliases gets returned, missing is not an existing index/alias but that doesn't make any difference String[] expectedIndices = new String[]{"alias2", "missing"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -631,7 +611,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indices("missing"); request.aliases("alias2"); IndexNotFoundException exception = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME))); assertEquals("no such index", exception.getMessage()); } @@ -640,7 +620,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean())); request.indices("missing"); request.aliases("alias2"); - assertNoIndices(request, defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME))); } public void testGetAliasesRequestMissingIndexStrict() { @@ -648,7 +628,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean())); request.indices("missing"); request.aliases("alias2"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); String[] expectedIndices = new String[]{"alias2", "missing"}; assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices, hasItems(expectedIndices)); @@ -661,7 +641,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true)); request.aliases("alias1"); request.indices("foo*"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for String[] expectedIndices = new String[]{"alias1", "foofoo", "foofoo-closed", "foofoobar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -676,7 +656,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, false)); request.aliases("alias1"); request.indices("foo*"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for String[] expectedIndices = new String[]{"alias1", "foofoo", "foofoobar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -691,7 +671,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false)); request.aliases("alias1"); request.indices("foo*", "bar", "missing"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for String[] expectedIndices = new String[]{"alias1", "foofoo", "foofoobar", "bar"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -707,7 +687,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.aliases("alias3"); request.indices("non_matching_*"); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME))); assertEquals("no such index", e.getMessage()); } @@ -716,7 +696,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); request.aliases("alias3"); request.indices("non_matching_*"); - assertNoIndices(request, defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME))); } public void testResolveAllGetAliasesRequest() { @@ -726,7 +706,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indices("_all"); } request.aliases("alias1"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed", "alias1"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -746,7 +726,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indices("_all"); } request.aliases("alias1"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo", "alias1"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -762,7 +742,8 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); request.aliases("alias1"); request.indices("_all"); - assertNoIndices(request, defaultIndicesResolver.resolve(userNoIndices, GetAliasesAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME))); } public void testAllGetAliasesRequestNoAuthorizedIndicesDisallowNoIndices() { @@ -771,7 +752,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.aliases("alias1"); request.indices("_all"); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(userNoIndices, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME))); assertEquals("no such index", e.getMessage()); } @@ -780,7 +761,8 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.aliases("alias1"); request.indices("foo*"); request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean())); - assertNoIndices(request, defaultIndicesResolver.resolve(userNoIndices, GetAliasesAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME))); } public void testWildcardsGetAliasesRequestNoAuthorizedIndicesDisallowNoIndices() { @@ -790,7 +772,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indices("foo*"); //current user is not authorized for any index, foo* resolves to no indices, the request fails IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(userNoIndices, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME))); assertEquals("no such index", e.getMessage()); } @@ -802,7 +784,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { if (randomBoolean()) { request.indices("_all"); } - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -817,7 +799,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { if (randomBoolean()) { request.indices("_all"); } - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed", "explicit"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -832,7 +814,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { if (randomBoolean()) { request.indices("_all"); } - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all resolved indices and aliases gets returned String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -846,7 +828,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { GetAliasesRequest request = new GetAliasesRequest(); request.indices("*bar"); request.aliases("foo*"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //union of all resolved indices and aliases gets returned, based on what user is authorized for //note that the index side will end up containing matching aliases too, which is fine, as es core would do //the same and resolve those aliases to their corresponding concrete indices (which we let core do) @@ -864,7 +846,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.aliases("bar*"); request.indices("*bar"); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME))); assertEquals("no such index", e.getMessage()); } @@ -876,19 +858,20 @@ public class DefaultIndicesResolverTests extends ESTestCase { request.indices("non_existing"); //current user is not authorized for any index, foo* resolves to no indices, the request fails IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(userNoIndices, GetAliasesAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME))); assertEquals("no such index", e.getMessage()); } public void testCompositeIndicesRequestIsNotSupported() { TransportRequest request = randomFrom(new MultiSearchRequest(), new MultiGetRequest(), new MultiTermVectorsRequest(), new BulkRequest()); - expectThrows(IllegalStateException.class, () -> defaultIndicesResolver.resolve(user, MultiSearchAction.NAME, request, metaData)); + expectThrows(IllegalStateException.class, () -> defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(user, MultiSearchAction.NAME))); } public void testResolveAdminAction() { DeleteIndexRequest request = new DeleteIndexRequest("*"); - Set indices = defaultIndicesResolver.resolve(user, DeleteIndexAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, DeleteIndexAction.NAME)); String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices, hasItems(expectedIndices)); @@ -900,55 +883,71 @@ public class DefaultIndicesResolverTests extends ESTestCase { //indices exists api never throws exception due to missing indices, but only returns false instead. { IndicesExistsRequest request = new IndicesExistsRequest(); - assertNoIndices(request, defaultIndicesResolver.resolve(userNoIndices, IndicesExistsAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(userNoIndices, IndicesExistsAction.NAME))); } + { IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist"); - assertNoIndices(request, defaultIndicesResolver.resolve(user, IndicesExistsAction.NAME, request, metaData)); + + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(user, IndicesExistsAction.NAME))); } { IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist_*"); - assertNoIndices(request, defaultIndicesResolver.resolve(user, IndicesExistsAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(user, IndicesExistsAction.NAME))); } } public void testXPackUserHasAccessToSecurityIndex() { SearchRequest request = new SearchRequest(); - Set indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, SearchAction.NAME, request, metaData); - assertThat(indices, hasItem(SecurityTemplateService.SECURITY_INDEX_NAME)); - - IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); - aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index("*")); - indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, IndicesAliasesAction.NAME, aliasesRequest, metaData); - assertThat(indices, hasItem(SecurityTemplateService.SECURITY_INDEX_NAME)); + { + Set indices = defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME)); + assertThat(indices, hasItem(SecurityTemplateService.SECURITY_INDEX_NAME)); + } + { + IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); + aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index("*")); + Set indices = defaultIndicesResolver.resolve(aliasesRequest, + metaData, buildAuthorizedIndices(XPackUser.INSTANCE, IndicesAliasesAction.NAME)); + assertThat(indices, hasItem(SecurityTemplateService.SECURITY_INDEX_NAME)); + } } public void testNonXPackUserAccessingSecurityIndex() { - User allAccessUser = new User("all_access", new String[] { "all_access" } ); + User allAccessUser = new User("all_access", "all_access"); when(rolesStore.role("all_access")).thenReturn( Role.builder("all_access").add(IndexPrivilege.ALL, "*").cluster(ClusterPrivilege.ALL).build()); - SearchRequest request = new SearchRequest(); - Set indices = defaultIndicesResolver.resolve(allAccessUser, SearchAction.NAME, request, metaData); - assertThat(indices, not(hasItem(SecurityTemplateService.SECURITY_INDEX_NAME))); - - IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); - aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*")); - indices = defaultIndicesResolver.resolve(allAccessUser, IndicesAliasesAction.NAME, aliasesRequest, metaData); - assertThat(indices, not(hasItem(SecurityTemplateService.SECURITY_INDEX_NAME))); + { + SearchRequest request = new SearchRequest(); + Set indices = defaultIndicesResolver.resolve(request, + metaData, buildAuthorizedIndices(allAccessUser, SearchAction.NAME)); + assertThat(indices, not(hasItem(SecurityTemplateService.SECURITY_INDEX_NAME))); + } + + { + IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); + aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*")); + Set indices = defaultIndicesResolver.resolve(aliasesRequest, + metaData, buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME)); + assertThat(indices, not(hasItem(SecurityTemplateService.SECURITY_INDEX_NAME))); + } } public void testUnauthorizedDateMathExpressionIgnoreUnavailable() { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean())); - assertNoIndices(request, defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); } public void testUnauthorizedDateMathExpressionIgnoreUnavailableDisallowNoIndices() { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(true, false, randomBoolean(), randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); assertEquals("no such index" , e.getMessage()); } @@ -956,7 +955,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); assertEquals("no such index" , e.getMessage()); } @@ -970,7 +969,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { if (randomBoolean()) { request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean())); } - Set indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)); assertThat(indices.size(), equalTo(1)); assertThat(request.indices()[0], equalTo(indexNameExpressionResolver.resolveDateMathExpression(""))); } @@ -978,14 +977,14 @@ public class DefaultIndicesResolverTests extends ESTestCase { public void testMissingDateMathExpressionIgnoreUnavailable() { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean())); - assertNoIndices(request, defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); } public void testMissingDateMathExpressionIgnoreUnavailableDisallowNoIndices() { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(true, false, randomBoolean(), randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); assertEquals("no such index" , e.getMessage()); } @@ -993,7 +992,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { SearchRequest request = new SearchRequest(""); request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean())); IndexNotFoundException e = expectThrows(IndexNotFoundException.class, - () -> defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData)); + () -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME))); assertEquals("no such index" , e.getMessage()); } @@ -1003,7 +1002,7 @@ public class DefaultIndicesResolverTests extends ESTestCase { indexNameExpressionResolver.resolveDateMathExpression("")}; when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build()); GetAliasesRequest request = new GetAliasesRequest("").indices("foo", "foofoo"); - Set indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData); + Set indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)); //the union of all indices and aliases gets returned String[] expectedIndices = new String[]{"", "foo", "foofoo"}; assertThat(indices.size(), equalTo(expectedIndices.length)); @@ -1014,6 +1013,11 @@ public class DefaultIndicesResolverTests extends ESTestCase { // TODO with the removal of DeleteByQuery is there another way to test resolving a write action? + private AuthorizedIndices buildAuthorizedIndices(User user, String action) { + Collection roles = authzService.roles(user); + return new AuthorizedIndices(user, roles, action, metaData); + } + private static IndexMetaData.Builder indexBuilder(String index) { return IndexMetaData.builder(index).settings(Settings.builder() .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) @@ -1022,8 +1026,8 @@ public class DefaultIndicesResolverTests extends ESTestCase { private static void assertNoIndices(IndicesRequest.Replaceable request, Set resolvedIndices) { assertEquals(1, resolvedIndices.size()); - assertEquals(DefaultIndicesAndAliasesResolver.NO_INDEX, resolvedIndices.iterator().next()); + assertEquals(IndicesAndAliasesResolver.NO_INDEX, resolvedIndices.iterator().next()); assertEquals(1, request.indices().length); - assertEquals(DefaultIndicesAndAliasesResolver.NO_INDEX, request.indices()[0]); + assertEquals(IndicesAndAliasesResolver.NO_INDEX, request.indices()[0]); } }