Simplify AuthorizationService and extract loading of authorized indices to its own class

extracted loading of authorized indices and aliases to separate class (AuthorizedIndices) with reduced dependencies. Allows also to lazily load authorized indices the first time they are required, and reuse them if they are needed again later. Removes AuthzService dependency in indices resolver.

 Removed array of resolvers in authorization service as we support only one. Removed IndicesAndAliasesResolver interface and rename DefaultIndicesAndAliasesResolver to IndicesAndAliasesResolver.

Original commit: elastic/x-pack-elasticsearch@a267fefa07
This commit is contained in:
javanna 2016-10-06 23:45:16 +02:00 committed by Luca Cavanna
parent 06b5d42741
commit 71d2c25fcb
8 changed files with 414 additions and 369 deletions

View File

@ -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<String> 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<Predicate<String>> 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<String> predicate = predicates.stream().reduce(s -> false, (p1, p2) -> p1.or(p2));
List<String> 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<String, AliasOrIndex> 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<Role> 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<String> indexNames = resolveIndices(authentication, action, request, clusterState);
MetaData metaData = clusterService.state().metaData();
AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getRunAsUser(), roles, action, metaData);
Set<String> 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<Role> 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<String> 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<Role> roles(User user) {
Set<String> 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<Role> 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<String> 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) {

View File

@ -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<Role> userRoles;
private List<String> authorizedIndices;
AuthorizedIndices(User user, Collection<Role> userRoles, String action, MetaData metaData) {
this.user = user;
this.userRoles = userRoles;
this.action = action;
this.metaData = metaData;
}
List<String> get() {
if (authorizedIndices == null) {
authorizedIndices = load();
}
return authorizedIndices;
}
private List<String> load() {
if (userRoles.isEmpty()) {
return Collections.emptyList();
}
List<Predicate<String>> predicates = new ArrayList<>();
for (Role userRole : userRoles) {
predicates.add(userRole.indices().allowedIndicesMatcher(action));
}
Predicate<String> predicate = predicates.stream().reduce(s -> false, Predicate::or);
List<String> 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<String, AliasOrIndex> 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);
}
}

View File

@ -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<TransportRequest> {
public class IndicesAndAliasesResolver {
public static final String NO_INDEX = "-*";
private static final List<String> 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<TransportRequest> requestType() {
return TransportRequest.class;
}
@Override
public Set<String> resolve(User user, String action, TransportRequest request, MetaData metaData) {
public Set<String> resolve(TransportRequest request, MetaData metaData, AuthorizedIndices authorizedIndices) {
if (request instanceof IndicesAliasesRequest) {
Set<String> 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<String> resolveIndicesAndAliases(User user, String action, IndicesRequest indicesRequest, MetaData metaData) {
private Set<String> resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData metaData,
AuthorizedIndices authorizedIndices) {
boolean indicesReplacedWithNoIndices = false;
final Set<String> 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<String> 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<String> authorizedIndices = authzService.authorizedIndicesAndAliases(user, action);
List<String> aliases = replaceWildcardsWithAuthorizedAliases(aliasesRequest.aliases(), loadAuthorizedAliases
(authorizedIndices, metaData));
List<String> 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);

View File

@ -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;

View File

@ -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<Request extends TransportRequest> {
Class<Request> requestType();
Set<String> resolve(User user, String action, Request request, MetaData metaData);
}

View File

@ -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<String> 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<String> 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<Role> 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<Role> 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<Role> 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<String, TransportRequest> compositeRequest = randomCompositeRequest();
@ -782,7 +774,6 @@ public class AuthorizationServiceTests extends ESTestCase {
}
private static class MockCompositeIndicesRequest extends TransportRequest implements CompositeIndicesRequest {
@Override
public List<? extends IndicesRequest> 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);

View File

@ -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<String> 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<Role> roles = Arrays.asList(aStarRole, bRole);
AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, roles, SearchAction.NAME, metaData);
List<String> 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<Role> roles = Collections.singletonList(role);
AuthorizedIndices authorizedIndices = new AuthorizedIndices(user, roles, SearchAction.NAME, MetaData.EMPTY_META_DATA);
List<String> list = authorizedIndices.get();
assertTrue(list.isEmpty());
}
}

View File

@ -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("<datetime-{now/M}>")).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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> 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<String> indices = defaultIndicesResolver.resolve(user, DeleteIndexAction.NAME, request, metaData);
Set<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> indices = defaultIndicesResolver.resolve(aliasesRequest,
metaData, buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME));
assertThat(indices, not(hasItem(SecurityTemplateService.SECURITY_INDEX_NAME)));
}
}
public void testUnauthorizedDateMathExpressionIgnoreUnavailable() {
SearchRequest request = new SearchRequest("<datetime-{now/M}>");
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("<datetime-{now/M}>");
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("<datetime-{now/M}>");
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<String> indices = defaultIndicesResolver.resolve(user, SearchAction.NAME, request, metaData);
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
assertThat(indices.size(), equalTo(1));
assertThat(request.indices()[0], equalTo(indexNameExpressionResolver.resolveDateMathExpression("<datetime-{now/M}>")));
}
@ -978,14 +977,14 @@ public class DefaultIndicesResolverTests extends ESTestCase {
public void testMissingDateMathExpressionIgnoreUnavailable() {
SearchRequest request = new SearchRequest("<foobar-{now/M}>");
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("<foobar-{now/M}>");
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("<foobar-{now/M}>");
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("<datetime-{now/M}>")};
when(rolesStore.role("role")).thenReturn(Role.builder("role").add(IndexPrivilege.ALL, authorizedIndices).build());
GetAliasesRequest request = new GetAliasesRequest("<datetime-{now/M}>").indices("foo", "foofoo");
Set<String> indices = defaultIndicesResolver.resolve(user, GetAliasesAction.NAME, request, metaData);
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"<datetime-{now/M}>", "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<Role> 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<String> 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]);
}
}