[Security] Don't apply local restrictions on remote cluster search (elastic/x-pack-elasticsearch#1609)

This change removes all local security checks against remote cluster names.
Any user is allowed to attempt a cross-cluster search, and it is the responsibility of the remote cluster to authorise the search (or not).

This includes support for remote searches even if you have _no_ local search privileges.

Original commit: elastic/x-pack-elasticsearch@1620c3a8fa
This commit is contained in:
Tim Vernum 2017-06-26 12:30:31 +10:00 committed by GitHub
parent 872badccb4
commit a73be456ec
4 changed files with 470 additions and 230 deletions

View File

@ -5,6 +5,13 @@
*/
package org.elasticsearch.xpack.security.authz;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.CompositeIndicesRequest;
@ -22,7 +29,6 @@ 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.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.component.AbstractComponent;
@ -44,6 +50,7 @@ import org.elasticsearch.xpack.security.authc.Authentication;
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authc.esnative.NativeRealm;
import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm;
import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver.ResolvedIndices;
import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl;
import org.elasticsearch.xpack.security.authz.permission.ClusterPermission;
import org.elasticsearch.xpack.security.authz.permission.FieldPermissionsCache;
@ -58,13 +65,6 @@ import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import static org.elasticsearch.xpack.security.Security.setting;
import static org.elasticsearch.xpack.security.support.Exceptions.authorizationError;
@ -250,24 +250,37 @@ public class AuthorizationService extends AbstractComponent {
}
}
if (permission.indices().check(action) == false) {
final boolean allowsRemoteIndices = request instanceof IndicesRequest
&& IndicesAndAliasesResolver.allowsRemoteIndices((IndicesRequest) request);
// If this request does not allow remote indices
// then the user must have permission to perform this action on at least 1 local index
if (allowsRemoteIndices == false && permission.indices().check(action) == false) {
throw denial(authentication, action, request);
}
MetaData metaData = clusterService.state().metaData();
AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData);
Set<String> indexNames = resolveIndexNames(authentication, action, request, metaData, authorizedIndices);
assert !indexNames.isEmpty() : "every indices request needs to have its indices set thus the resolved indices must not be empty";
final MetaData metaData = clusterService.state().metaData();
final AuthorizedIndices authorizedIndices = new AuthorizedIndices(authentication.getUser(), permission, action, metaData);
final ResolvedIndices resolvedIndices = resolveIndexNames(authentication, action, request, metaData, authorizedIndices);
assert !resolvedIndices.isEmpty()
: "every indices request needs to have its indices set thus the resolved indices must not be empty";
// If this request does reference any remote indices
// then the user must have permission to perform this action on at least 1 local index
if (resolvedIndices.getRemote().isEmpty() && permission.indices().check(action) == false) {
throw denial(authentication, action, request);
}
//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(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER)) {
if (resolvedIndices.isNoIndicesPlaceholder()) {
setIndicesAccessControl(IndicesAccessControl.ALLOW_NO_INDICES);
grant(authentication, action, request);
return;
}
IndicesAccessControl indicesAccessControl = permission.authorize(action, indexNames, metaData, fieldPermissionsCache);
final Set<String> localIndices = new HashSet<>(resolvedIndices.getLocal());
IndicesAccessControl indicesAccessControl = permission.authorize(action, localIndices, metaData, fieldPermissionsCache);
if (!indicesAccessControl.isGranted()) {
throw denial(authentication, action, request);
} else if (indicesAccessControl.getIndexPermissions(SecurityLifecycleService.SECURITY_INDEX_NAME) != null
@ -289,7 +302,7 @@ public class AuthorizationService extends AbstractComponent {
assert request instanceof CreateIndexRequest;
Set<Alias> aliases = ((CreateIndexRequest) request).aliases();
if (!aliases.isEmpty()) {
Set<String> aliasesAndIndices = Sets.newHashSet(indexNames);
Set<String> aliasesAndIndices = Sets.newHashSet(localIndices);
for (Alias alias : aliases) {
aliasesAndIndices.add(alias.name());
}
@ -305,8 +318,8 @@ public class AuthorizationService extends AbstractComponent {
grant(authentication, action, originalRequest);
}
private Set<String> resolveIndexNames(Authentication authentication, String action, TransportRequest request, MetaData metaData,
AuthorizedIndices authorizedIndices) {
private ResolvedIndices resolveIndexNames(Authentication authentication, String action, TransportRequest request, MetaData metaData,
AuthorizedIndices authorizedIndices) {
try {
return indicesAndAliasesResolver.resolve(request, metaData, authorizedIndices);
} catch (Exception e) {

View File

@ -5,28 +5,6 @@
*/
package org.elasticsearch.xpack.security.authz;
import org.elasticsearch.action.AliasesRequest;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.metadata.AliasOrIndex;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.transport.TransportRequest;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
@ -39,13 +17,34 @@ import java.util.SortedMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
import org.elasticsearch.action.AliasesRequest;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.metadata.AliasOrIndex;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.transport.TransportRequest;
public class IndicesAndAliasesResolver {
//placeholder used in the security plugin to indicate that the request is authorized knowing that it will yield an empty response
public static final String NO_INDEX_PLACEHOLDER = "-*";
private static final Set<String> NO_INDEX_PLACEHOLDER_SET = Collections.singleton(NO_INDEX_PLACEHOLDER);
private static final ResolvedIndices NO_INDEX_PLACEHOLDER_RESOLVED = ResolvedIndices.local(NO_INDEX_PLACEHOLDER);
//`*,-*` what we replace indices with if we need Elasticsearch to return empty responses without throwing exception
private static final String[] NO_INDICES_ARRAY = new String[] {"*", "-*"};
private static final String[] NO_INDICES_ARRAY = new String[] { "*", "-*" };
static final List<String> NO_INDICES_LIST = Arrays.asList(NO_INDICES_ARRAY);
private final IndexNameExpressionResolver nameExpressionResolver;
@ -56,12 +55,41 @@ public class IndicesAndAliasesResolver {
this.remoteClusterResolver = new RemoteClusterResolver(settings, clusterService.getClusterSettings());
}
public Set<String> resolve(TransportRequest request, MetaData metaData, AuthorizedIndices authorizedIndices) {
/**
* Resolves, and if necessary updates, the list of index names in the provided <code>request</code> in accordance with the user's
* <code>authorizedIndices</code>.
* <p>
* Wildcards are expanded at this phase to ensure that all security and execution decisions are made against a fixed set of index names
* that is consistent and does not change during the life of the request.
* </p>
* <p>
* If the provided <code>request</code> is of a type that {@link #allowsRemoteIndices(IndicesRequest) allows remote indices},
* then the index names will be categorized into those that refer to {@link ResolvedIndices#getLocal() local indices}, and those that
* refer to {@link ResolvedIndices#getRemote() remote indices}. This categorization follows the standard
* {@link RemoteClusterAware#buildRemoteIndexName(String, String) remote index-name format} and also respects the currently defined
* {@link RemoteClusterAware#getRemoteClusterNames() remote clusters}.
* </p><br>
* Thus an index name <em>N</em> will considered to be <em>remote</em> if-and-only-if all of the following are true
* <ul>
* <li><code>request</code> supports remote indices</li>
* <li>
* <em>N</em> is in the format <i>cluster</i><code>:</code><i>index</i>.
* It is allowable for <i>cluster</i> and <i>index</i> to contain wildcards, but the separator (<code>:</code>) must be explicit.
* </li>
* <li><i>cluster</i> matches one or more remote cluster names that are registered within this cluster.</li>
* </ul>
* In which case, any wildcards in the <i>cluster</i> portion of the name will be expanded and the resulting remote-index-name(s) will
* be added to the <em>remote</em> index list.
* <br>
* Otherwise, <em>N</em> will be added to the <em>local</em> index list.
*/
public ResolvedIndices resolve(TransportRequest request, MetaData metaData, AuthorizedIndices authorizedIndices) {
if (request instanceof IndicesAliasesRequest) {
Set<String> indices = new HashSet<>();
ResolvedIndices indices = ResolvedIndices.empty();
IndicesAliasesRequest indicesAliasesRequest = (IndicesAliasesRequest) request;
for (IndicesRequest indicesRequest : indicesAliasesRequest.getAliasActions()) {
indices.addAll(resolveIndicesAndAliases(indicesRequest, metaData, authorizedIndices));
indices = ResolvedIndices.add(indices, resolveIndicesAndAliases(indicesRequest, metaData, authorizedIndices));
}
return indices;
}
@ -73,9 +101,10 @@ public class IndicesAndAliasesResolver {
return resolveIndicesAndAliases((IndicesRequest) request, metaData, authorizedIndices);
}
private Set<String> resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData metaData, AuthorizedIndices authorizedIndices) {
private ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData metaData,
AuthorizedIndices authorizedIndices) {
boolean indicesReplacedWithNoIndices = false;
final Set<String> indices;
final ResolvedIndices indices;
if (indicesRequest instanceof PutMappingRequest && ((PutMappingRequest) indicesRequest).getConcreteIndex() != null) {
/*
* This is a special case since PutMappingRequests from dynamic mapping updates have a concrete index
@ -84,7 +113,7 @@ public class IndicesAndAliasesResolver {
*/
assert indicesRequest.indices() == null || indicesRequest.indices().length == 0
: "indices are: " + Arrays.toString(indicesRequest.indices()); // Arrays.toString() can handle null values - all good
return Collections.singleton(((PutMappingRequest) indicesRequest).getConcreteIndex().getName());
return ResolvedIndices.local(((PutMappingRequest) indicesRequest).getConcreteIndex().getName());
} else if (indicesRequest instanceof IndicesRequest.Replaceable) {
IndicesRequest.Replaceable replaceable = (IndicesRequest.Replaceable) indicesRequest;
final boolean replaceWildcards = indicesRequest.indicesOptions().expandWildcardsOpen()
@ -97,49 +126,48 @@ public class IndicesAndAliasesResolver {
indicesOptions.expandWildcardsOpen(), indicesOptions.expandWildcardsClosed());
}
List<String> replacedIndices = new ArrayList<>();
ResolvedIndices result = ResolvedIndices.empty();
// check for all and return list of authorized indices
if (IndexNameExpressionResolver.isAllIndices(indicesList(indicesRequest.indices()))) {
if (replaceWildcards) {
for (String authorizedIndex : authorizedIndices.get()) {
if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) {
replacedIndices.add(authorizedIndex);
result = ResolvedIndices.add(result, ResolvedIndices.local(authorizedIndex));
}
}
}
// if we cannot replace wildcards the indices list stays empty. Same if there are no authorized indices.
// we honour allow_no_indices like es core does.
} else {
String[] localIndexNames = indicesRequest.indices();
List<String> remoteIndices = Collections.emptyList();
final ResolvedIndices split;
if (allowsRemoteIndices(indicesRequest)) {
final Tuple<List<String>, List<String>> split = remoteClusterResolver.splitLocalAndRemoteIndexNames(localIndexNames);
localIndexNames = split.v1().toArray(new String[split.v1().size()]);
remoteIndices = split.v2();
split = remoteClusterResolver.splitLocalAndRemoteIndexNames(indicesRequest.indices());
} else {
split = ResolvedIndices.local(indicesRequest.indices());
}
replacedIndices = replaceWildcardsWithAuthorizedIndices(localIndexNames, indicesOptions, metaData, authorizedIndices.get(),
replaceWildcards);
List<String> replaced = replaceWildcardsWithAuthorizedIndices(split.getLocal(), 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(authorizedIndices.get()::contains).collect(Collectors.toList());
replaced = replaced.stream().filter(authorizedIndices.get()::contains).collect(Collectors.toList());
}
replacedIndices.addAll(remoteIndices);
result = new ResolvedIndices(new ArrayList<>(replaced), split.getRemote());
}
if (replacedIndices.isEmpty()) {
if (result.isEmpty()) {
if (indicesOptions.allowNoIndices()) {
//this is how we tell es core to return an empty response, we can let the request through being sure
//that the '-*' wildcard expression will be resolved to no indices. We can't let empty indices through
//as that would be resolved to _all by es core.
replaceable.indices(NO_INDICES_ARRAY);
indicesReplacedWithNoIndices = true;
indices = NO_INDEX_PLACEHOLDER_SET;
indices = NO_INDEX_PLACEHOLDER_RESOLVED;
} else {
throw new IndexNotFoundException(Arrays.toString(indicesRequest.indices()));
}
} else {
replaceable.indices(replacedIndices.toArray(new String[replacedIndices.size()]));
indices = new HashSet<>(replacedIndices);
replaceable.indices(result.toArray());
indices = result;
}
} else {
if (containsWildcards(indicesRequest)) {
@ -157,7 +185,7 @@ public class IndicesAndAliasesResolver {
for (String name : indicesRequest.indices()) {
resolvedNames.add(nameExpressionResolver.resolveDateMathExpression(name));
}
indices = new HashSet<>(resolvedNames);
indices = new ResolvedIndices(resolvedNames, new ArrayList<>());
}
if (indicesRequest instanceof AliasesRequest) {
@ -178,14 +206,14 @@ public class IndicesAndAliasesResolver {
//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 {
Collections.addAll(indices, aliasesRequest.aliases());
return ResolvedIndices.add(indices, ResolvedIndices.local(aliasesRequest.aliases()));
}
}
return Collections.unmodifiableSet(indices);
return indices;
}
private static boolean allowsRemoteIndices(IndicesRequest indicesRequest) {
return indicesRequest instanceof SearchRequest || indicesRequest instanceof FieldCapabilitiesRequest;
public static boolean allowsRemoteIndices(IndicesRequest request) {
return request instanceof SearchRequest || request instanceof FieldCapabilitiesRequest;
}
private List<String> loadAuthorizedAliases(List<String> authorizedIndices, MetaData metaData) {
@ -249,7 +277,7 @@ public class IndicesAndAliasesResolver {
}
//TODO Investigate reusing code from vanilla es to resolve index names and wildcards
private List<String> replaceWildcardsWithAuthorizedIndices(String[] indices, IndicesOptions indicesOptions, MetaData metaData,
private List<String> replaceWildcardsWithAuthorizedIndices(Iterable<String> indices, IndicesOptions indicesOptions, MetaData metaData,
List<String> authorizedIndices, boolean replaceWildcards) {
//the order matters when it comes to exclusions
List<String> finalIndices = new ArrayList<>();
@ -374,13 +402,101 @@ public class IndicesAndAliasesResolver {
}
}
Tuple<List<String>, List<String>> splitLocalAndRemoteIndexNames(String ... indices) {
ResolvedIndices splitLocalAndRemoteIndexNames(String... indices) {
final Map<String, List<String>> map = super.groupClusterIndices(indices, exists -> false);
final List<String> local = map.remove(LOCAL_CLUSTER_GROUP_KEY);
final List<String> remote = map.entrySet().stream()
.flatMap(e -> e.getValue().stream().map(v -> e.getKey() + REMOTE_CLUSTER_INDEX_SEPARATOR + v))
.collect(Collectors.toList());
return new Tuple<>(local == null ? Collections.emptyList() : local, remote);
return new ResolvedIndices(local == null ? Collections.emptyList() : local, remote);
}
}
/**
* Stores a collection of index names separated into "local" and "remote".
* This allows the resolution and categorization to take place exactly once per-request.
*/
public static class ResolvedIndices {
private final List<String> local;
private final List<String> remote;
ResolvedIndices(List<String> local, List<String> remote) {
this.local = local;
this.remote = remote;
}
/**
* Constructs a new instance of this class where both the {@link #getLocal() local} and {@link #getRemote() remote} index lists
* are empty.
*/
private static ResolvedIndices empty() {
return new ResolvedIndices(Collections.emptyList(), Collections.emptyList());
}
/**
* Constructs a new instance of this class where both the {@link #getLocal() local} index list is populated with <code>names</code>
* and the {@link #getRemote() remote} index list is empty.
*/
private static ResolvedIndices local(String... names) {
return new ResolvedIndices(Arrays.asList(names), Collections.emptyList());
}
/**
* Returns the collection of index names that have been stored as "local" indices.
* This is a <code>List</code> because order may be important. For example <code>[ "a*" , "-a1" ]</code> is interpreted differently
* to <code>[ "-a1", "a*" ]</code>. As a consequence, this list <em>may contain duplicates</em>.
*/
public List<String> getLocal() {
return Collections.unmodifiableList(local);
}
/**
* Returns the collection of index names that have been stored as "remote" indices.
*/
public List<String> getRemote() {
return Collections.unmodifiableList(remote);
}
/**
* @return <code>true</code> if both the {@link #getLocal() local} and {@link #getRemote() remote} index lists are empty.
*/
public boolean isEmpty() {
return local.isEmpty() && remote.isEmpty();
}
/**
* @return <code>true</code> if the {@link #getRemote() remote} index lists is empty, and the local index list contains the
* {@link IndicesAndAliasesResolver#NO_INDEX_PLACEHOLDER no-index-placeholder} and nothing else.
*/
public boolean isNoIndicesPlaceholder() {
return remote.isEmpty() && local.size() == 1 && local.contains(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER);
}
private String[] toArray() {
final String[] array = new String[local.size() + remote.size()];
int i = 0;
for (String index : local) {
array[i++] = index;
}
for (String index : remote) {
array[i++] = index;
}
return array;
}
/**
* Returns a new <code>ResolvedIndices</code> contains the {@link #getLocal() local} and {@link #getRemote() remote}
* index lists from <code>b</code> appended to the corresponding lists in <code>a</code>.
*/
private static ResolvedIndices add(ResolvedIndices a, ResolvedIndices b) {
List<String> local = new ArrayList<>(a.local.size() + b.local.size());
local.addAll(a.local);
local.addAll(b.local);
List<String> remote = new ArrayList<>(a.remote.size() + b.remote.size());
remote.addAll(a.remote);
remote.addAll(b.remote);
return new ResolvedIndices(local, remote);
}
}

View File

@ -5,6 +5,14 @@
*/
package org.elasticsearch.xpack.security.authz;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
@ -20,6 +28,8 @@ import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsAction;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexAction;
@ -74,6 +84,7 @@ import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.index.IndexNotFoundException;
@ -113,14 +124,6 @@ import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.junit.Before;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationException;
import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException;
import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs;
@ -154,13 +157,16 @@ public class AuthorizationServiceTests extends ESTestCase {
public void setup() {
rolesStore = mock(CompositeRolesStore.class);
clusterService = mock(ClusterService.class);
final ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
final Settings settings = Settings.builder()
.put("search.remote.other_cluster.seeds", "localhost:9999")
.build();
final ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
when(clusterService.getClusterSettings()).thenReturn(clusterSettings);
auditTrail = mock(AuditTrailService.class);
threadContext = new ThreadContext(Settings.EMPTY);
threadContext = new ThreadContext(settings);
threadPool = mock(ThreadPool.class);
when(threadPool.getThreadContext()).thenReturn(threadContext);
final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(settings);
doAnswer((i) -> {
ActionListener<Role> callback =
(ActionListener<Role>) i.getArguments()[2];
@ -182,8 +188,8 @@ public class AuthorizationServiceTests extends ESTestCase {
}
return Void.TYPE;
}).when(rolesStore).roles(any(Set.class), any(FieldPermissionsCache.class), any(ActionListener.class));
authorizationService = new AuthorizationService(Settings.EMPTY, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(Settings.EMPTY));
authorizationService = new AuthorizationService(settings, rolesStore, clusterService,
auditTrail, new DefaultAuthenticationFailureHandler(), threadPool, new AnonymousUser(settings));
}
private void authorize(Authentication authentication, String action, TransportRequest request) {
@ -246,6 +252,65 @@ public class AuthorizationServiceTests extends ESTestCase {
verifyNoMoreInteractions(auditTrail);
}
public void testUserWithNoRolesCanPerformRemoteSearch() {
SearchRequest request = new SearchRequest();
request.indices("other_cluster:index1", "*_cluster:index2", "other_cluster:other_*");
User user = new User("test user");
mockEmptyMetaData();
authorize(createAuthentication(user), SearchAction.NAME, request);
verify(auditTrail).accessGranted(user, SearchAction.NAME, request);
verifyNoMoreInteractions(auditTrail);
}
/**
* This test mimics {@link #testUserWithNoRolesCanPerformRemoteSearch()} except that
* while the referenced index _looks_ like a remote index, the remote cluster name has not
* been defined, so it is actually a local index and access should be denied
*/
public void testUserWithNoRolesCannotPerformLocalSearch() {
SearchRequest request = new SearchRequest();
request.indices("no_such_cluster:index");
User user = new User("test user");
mockEmptyMetaData();
assertThrowsAuthorizationException(
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
SearchAction.NAME, "test user");
verify(auditTrail).accessDenied(user, SearchAction.NAME, request);
verifyNoMoreInteractions(auditTrail);
}
/**
* This test mimics {@link #testUserWithNoRolesCannotPerformLocalSearch()} but includes
* both local and remote indices, including wildcards
*/
public void testUserWithNoRolesCanPerformMultiClusterSearch() {
SearchRequest request = new SearchRequest();
request.indices("local_index", "wildcard_*", "other_cluster:remote_index", "*:foo?");
User user = new User("test user");
mockEmptyMetaData();
assertThrowsAuthorizationException(
() -> authorize(createAuthentication(user), SearchAction.NAME, request),
SearchAction.NAME, "test user");
verify(auditTrail).accessDenied(user, SearchAction.NAME, request);
verifyNoMoreInteractions(auditTrail);
}
/**
* Verifies that the behaviour tested in {@link #testUserWithNoRolesCanPerformRemoteSearch}
* does not work for requests that are not remote-index-capable.
*/
public void testRemoteIndicesOnlyWorkWithApplicableRequestTypes() {
DeleteIndexRequest request = new DeleteIndexRequest();
request.indices("other_cluster:index1", "other_cluster:index2");
User user = new User("test user");
mockEmptyMetaData();
assertThrowsAuthorizationException(
() -> authorize(createAuthentication(user), DeleteIndexAction.NAME, request),
DeleteIndexAction.NAME, "test user");
verify(auditTrail).accessDenied(user, DeleteIndexAction.NAME, request);
verifyNoMoreInteractions(auditTrail);
}
public void testUnknownRoleCausesDenial() {
TransportRequest request = new SearchRequest();
User user = new User("test user", "non-existent-role");

View File

@ -5,6 +5,13 @@
*/
package org.elasticsearch.xpack.security.authz;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.IndicesRequest;
@ -51,6 +58,7 @@ import org.elasticsearch.transport.TransportRequest;
import org.elasticsearch.xpack.security.SecurityLifecycleService;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler;
import org.elasticsearch.xpack.security.authz.IndicesAndAliasesResolver.ResolvedIndices;
import org.elasticsearch.xpack.security.authz.RoleDescriptor.IndicesPrivileges;
import org.elasticsearch.xpack.security.authz.permission.FieldPermissionsCache;
import org.elasticsearch.xpack.security.authz.permission.Role;
@ -62,16 +70,11 @@ import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.user.XPackUser;
import org.junit.Before;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
@ -179,7 +182,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
//aliases with names starting with '-' or '+' can be created up to version 5.x and can be around in 6.x
ShardSearchTransportRequest request = mock(ShardSearchTransportRequest.class);
when(request.indices()).thenReturn(new String[]{"-index10", "-index20", "+index30"});
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME))
.getLocal();
String[] expectedIndices = new String[]{"-index10", "-index20", "+index30"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
@ -189,7 +193,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
ShardSearchTransportRequest request = mock(ShardSearchTransportRequest.class);
when(request.indices()).thenReturn(new String[]{"index*"});
IllegalStateException illegalStateException = expectThrows(IllegalStateException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME))
.getLocal());
assertEquals("There are no external requests known to support wildcards that don't support replacing their indices",
illegalStateException.getMessage());
}
@ -206,14 +211,16 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
}
}
IllegalStateException illegalStateException = expectThrows(IllegalStateException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME))
.getLocal());
assertEquals("There are no external requests known to support wildcards that don't support replacing their indices",
illegalStateException.getMessage());
}
public void testExplicitDashIndices() {
SearchRequest request = new SearchRequest("-index10", "-index20");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-index10", "-index20"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -228,7 +235,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
} else {
request = new SearchRequest("*", "--index20");
}
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-index10", "-index11", "-index21"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -238,7 +246,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testExplicitMixedWildcardDashIndices() {
SearchRequest request = new SearchRequest("-index21", "-does_not_exist", "-index1*", "--index11");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-index10", "-index21", "-does_not_exist"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -249,7 +258,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testDashIndicesNoExpandWildcard() {
SearchRequest request = new SearchRequest("-index1*", "--index11");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), false, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-index1*", "--index11"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -260,7 +270,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testDashIndicesMinus() {
SearchRequest request = new SearchRequest("-index10", "-index11", "--index11", "-index20");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean()));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-index10", "-index11", "--index11", "-index20"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -272,13 +283,13 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
SearchRequest request = new SearchRequest("+bar");
request.indicesOptions(IndicesOptions.fromOptions(true, false, randomBoolean(), randomBoolean()));
expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)));
}
public void testDashNotExistingIndex() {
SearchRequest request = new SearchRequest("-does_not_exist");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean()));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userDashIndices, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(userDashIndices, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"-does_not_exist"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -289,7 +300,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveEmptyIndicesExpandWilcardsOpenAndClosed() {
SearchRequest request = new SearchRequest();
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -300,7 +311,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveEmptyIndicesExpandWilcardsOpen() {
SearchRequest request = new SearchRequest();
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -311,7 +322,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveAllExpandWilcardsOpenAndClosed() {
SearchRequest request = new SearchRequest("_all");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -322,7 +333,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveAllExpandWilcardsOpen() {
SearchRequest request = new SearchRequest("_all");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -333,7 +344,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsStrictExpand() {
SearchRequest request = new SearchRequest("barbaz", "foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -344,7 +355,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsExpandOpenAndClosedIgnoreUnavailable() {
SearchRequest request = new SearchRequest("barbaz", "foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -355,7 +366,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsStrictExpandOpen() {
SearchRequest request = new SearchRequest("barbaz", "foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -366,7 +377,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsLenientExpandOpen() {
SearchRequest request = new SearchRequest("barbaz", "foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -377,7 +388,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsMinusExpandWilcardsOpen() {
SearchRequest request = new SearchRequest("*", "-foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -388,7 +399,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsMinusExpandWilcardsOpenAndClosed() {
SearchRequest request = new SearchRequest("*", "-foofoo*");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "bar-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -399,7 +410,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsExclusionsExpandWilcardsOpenStrict() {
SearchRequest request = new SearchRequest("*", "-foofoo*", "barbaz", "foob*");
request.indicesOptions(IndicesOptions.fromOptions(false, true, true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -410,7 +421,7 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -421,7 +432,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsExclusionExpandWilcardsOpenAndClosedStrict() {
SearchRequest request = new SearchRequest("*", "-foofoo*", "barbaz");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -432,7 +443,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveWildcardsExclusionExpandWilcardsOpenAndClosedIgnoreUnavailable() {
SearchRequest request = new SearchRequest("*", "-foofoo*", "barbaz");
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, true));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar", "bar-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -443,21 +454,21 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveNonMatchingIndicesAllowNoIndices() {
SearchRequest request = new SearchRequest("missing*");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
assertNoIndices(request, resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
() -> resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"missing", "bar", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -468,7 +479,7 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] replacedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(request.indices().length, equalTo(replacedIndices.length));
@ -479,22 +490,22 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveNoAuthorizedIndicesAllowNoIndices() {
SearchRequest request = new SearchRequest();
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
assertNoIndices(request, defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(userNoIndices, SearchAction.NAME)));
assertNoIndices(request, resolveIndices(request,
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(request, metaData, buildAuthorizedIndices(userNoIndices, SearchAction.NAME)));
() -> resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"bar", "missing"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -505,7 +516,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveMissingIndexIgnoreUnavailable() {
SearchRequest request = new SearchRequest("bar*", "missing");
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(request.indices().length, equalTo(expectedIndices.length));
@ -516,7 +527,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveNonMatchingIndicesAndExplicit() {
SearchRequest request = new SearchRequest("missing*", "bar");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"bar"};
assertThat(indices.toArray(new String[indices.size()]), equalTo(expectedIndices));
assertThat(request.indices(), equalTo(expectedIndices));
@ -525,7 +536,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveNoExpandStrict() {
SearchRequest request = new SearchRequest("missing*");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), false, false));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
String[] expectedIndices = new String[]{"missing*"};
assertThat(indices.toArray(new String[indices.size()]), equalTo(expectedIndices));
assertThat(request.indices(), equalTo(expectedIndices));
@ -534,43 +545,47 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testResolveNoExpandIgnoreUnavailable() {
SearchRequest request = new SearchRequest("missing*");
request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false));
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
assertNoIndices(request, resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)));
}
public void testSearchWithRemoteIndex() {
SearchRequest request = new SearchRequest("remote:indexName");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()));
final Set<String> resolved = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
assertThat(resolved, containsInAnyOrder("remote:indexName"));
final ResolvedIndices resolved = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME));
assertThat(resolved.getLocal(), emptyIterable());
assertThat(resolved.getRemote(), containsInAnyOrder("remote:indexName"));
assertThat(request.indices(), arrayContaining("remote:indexName"));
}
public void testSearchWithRemoteAndLocalIndices() {
SearchRequest request = new SearchRequest("remote:indexName", "bar", "bar2");
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), randomBoolean(), randomBoolean()));
final Set<String> resolved = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
assertThat(resolved, containsInAnyOrder("remote:indexName", "bar"));
final ResolvedIndices resolved = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME));
assertThat(resolved.getLocal(), containsInAnyOrder("bar"));
assertThat(resolved.getRemote(), containsInAnyOrder("remote:indexName"));
assertThat(request.indices(), arrayContainingInAnyOrder("remote:indexName", "bar"));
}
public void testSearchWithRemoteAndLocalWildcards() {
SearchRequest request = new SearchRequest("*:foo", "r*:bar*", "remote:baz*", "bar*", "foofoo");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false));
final Set<String> resolved = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
final String[] expectedIndices = { "remote:foo", "other_remote:foo", "remote:bar*", "remote:baz*", "bar", "foofoo" };
assertThat(resolved, containsInAnyOrder(expectedIndices));
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, SearchAction.NAME);
final ResolvedIndices resolved = resolveIndices(request, authorizedIndices);
assertThat(resolved.getRemote(), containsInAnyOrder("remote:foo", "other_remote:foo", "remote:bar*", "remote:baz*"));
assertThat(resolved.getLocal(), containsInAnyOrder("bar", "foofoo"));
assertThat(request.indices(),
arrayContainingInAnyOrder("remote:foo", "other_remote:foo", "remote:bar*", "remote:baz*", "bar", "foofoo"));
}
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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)).getLocal();
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
@ -581,11 +596,11 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)).getLocal();
//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));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContainingInAnyOrder("foo", "foobar"));
@ -596,7 +611,8 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)).getLocal();
//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));
@ -611,7 +627,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasActions.add().alias("foo-alias").index("foo*"));
request.addAliasAction(AliasActions.add().alias("alias2").index("bar*"));
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)).getLocal();
//the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for
String[] expectedIndices = new String[]{"foo-alias", "alias2", "foofoo", "bar"};
assertThat(indices.size(), equalTo(expectedIndices.length));
@ -630,18 +647,18 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
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
expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)));
() -> resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "foofoo", "alias1", "alias2"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
String[] replacedIndices = new String[]{"bar", "foofoo"};
//_all gets replaced with all indices that user is authorized for, on each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder(replacedIndices));
@ -654,23 +671,24 @@ public class IndicesAndAliasesResolverTests 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
expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve(
request, metaData, buildAuthorizedIndices(userNoIndices, IndicesAliasesAction.NAME)));
expectThrows(IndexNotFoundException.class, () ->
resolveIndices(request, 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
expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve(
request, metaData, buildAuthorizedIndices(userNoIndices, IndicesAliasesAction.NAME)));
expectThrows(IndexNotFoundException.class, () -> resolveIndices(
request, 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"};
assertThat(indices.size(), equalTo(expectedIndices.length));
@ -685,7 +703,8 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -700,7 +719,8 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -716,13 +736,13 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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)
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
@ -734,13 +754,13 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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)
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo", "explicit"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("bar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
@ -753,19 +773,19 @@ public class IndicesAndAliasesResolverTests 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*"));
expectThrows(IndexNotFoundException.class, () -> defaultIndicesResolver.resolve(
request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME)));
expectThrows(IndexNotFoundException.class, () -> resolveIndices(
request, 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(request, metaData, buildAuthorizedIndices(user, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//every single action has its indices replaced with matching (authorized) ones
assertThat(request.getAliasActions().get(0).indices(), arrayContainingInAnyOrder("foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContainingInAnyOrder("foofoobar"));
@ -776,7 +796,8 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"alias1", "foo", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length));
@ -788,7 +809,8 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
String[] expectedIndices = new String[]{"alias1", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
@ -801,7 +823,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, randomBoolean()));
request.indices("missing");
request.aliases("alias2");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -816,7 +839,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indices("missing");
request.aliases("alias2");
IndexNotFoundException exception = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)).getLocal());
assertEquals("no such index", exception.getMessage());
}
@ -825,7 +848,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean()));
request.indices("missing");
request.aliases("alias2");
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
assertNoIndices(request, resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
}
public void testGetAliasesRequestMissingIndexStrict() {
@ -833,7 +856,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean()));
request.indices("missing");
request.aliases("alias2");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
String[] expectedIndices = new String[]{"alias2", "missing"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
@ -846,7 +870,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, true));
request.aliases("alias1");
request.indices("foo*");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -861,7 +886,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), true, false));
request.aliases("alias1");
request.indices("foo*");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -876,7 +902,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(true, randomBoolean(), true, false));
request.aliases("alias1");
request.indices("foo*", "bar", "missing");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -892,7 +919,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.aliases("alias3");
request.indices("non_matching_*");
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)).getLocal());
assertEquals("no such index", e.getMessage());
}
@ -901,7 +928,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
request.aliases("alias3");
request.indices("non_matching_*");
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
assertNoIndices(request, resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
}
public void testResolveAllGetAliasesRequest() {
@ -911,7 +938,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indices("_all");
}
request.aliases("alias1");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
@ -931,7 +959,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indices("_all");
}
request.aliases("alias1");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo", "alias1"};
assertThat(indices.size(), equalTo(expectedIndices.length));
@ -947,8 +976,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
request.aliases("alias1");
request.indices("_all");
assertNoIndices(request, defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
assertNoIndices(request, resolveIndices(request,
buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
}
public void testAllGetAliasesRequestNoAuthorizedIndicesDisallowNoIndices() {
@ -957,7 +986,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.aliases("alias1");
request.indices("_all");
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
assertEquals("no such index", e.getMessage());
}
@ -966,8 +995,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.aliases("alias1");
request.indices("foo*");
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), true, true, randomBoolean()));
assertNoIndices(request, defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
assertNoIndices(request, resolveIndices(request,
buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
}
public void testWildcardsGetAliasesRequestNoAuthorizedIndicesDisallowNoIndices() {
@ -977,7 +1006,7 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
assertEquals("no such index", e.getMessage());
}
@ -989,11 +1018,11 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
if (randomBoolean()) {
request.indices("_all");
}
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
@ -1004,11 +1033,11 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
if (randomBoolean()) {
request.indices("_all");
}
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "explicit"));
@ -1019,11 +1048,11 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
if (randomBoolean()) {
request.indices("_all");
}
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//_all gets replaced with all indices that user is authorized for
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar", "foofoobar"));
@ -1033,13 +1062,13 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
GetAliasesRequest request = new GetAliasesRequest();
request.indices("*bar");
request.aliases("foo*");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, GetAliasesAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
//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)
String[] expectedIndices = new String[]{"bar", "foofoobar"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertSameValues(indices, expectedIndices);
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
assertThat(request.indices(), arrayContainingInAnyOrder("bar", "foofoobar"));
assertThat(request.aliases(), arrayContainingInAnyOrder("foofoobar"));
@ -1051,7 +1080,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
request.aliases("bar*");
request.indices("*bar");
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)));
assertEquals("no such index", e.getMessage());
}
@ -1063,7 +1092,7 @@ public class IndicesAndAliasesResolverTests 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(request, metaData, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(userNoIndices, GetAliasesAction.NAME)));
assertEquals("no such index", e.getMessage());
}
@ -1077,8 +1106,11 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
new Tuple<>(new SearchRequest("remote:foo").indicesOptions(options), SearchAction.NAME),
new Tuple<>(new FieldCapabilitiesRequest().indices("remote:foo").indicesOptions(options), FieldCapabilitiesAction.NAME)
);
final Set<String> resolved = defaultIndicesResolver.resolve(tuple.v1(), metaData, buildAuthorizedIndices(user, tuple.v2()));
assertThat(resolved, containsInAnyOrder("remote:foo"));
final TransportRequest request = tuple.v1();
ResolvedIndices resolved = resolveIndices(request, buildAuthorizedIndices(user, tuple.v2()));
assertThat(resolved.getRemote(), containsInAnyOrder("remote:foo"));
assertThat(resolved.getLocal(), emptyIterable());
assertThat(((IndicesRequest) request).indices(), arrayContaining("remote:foo"));
}
/**
@ -1092,7 +1124,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
new Tuple<>(new PutMappingRequest("remote:foo").indicesOptions(options), PutMappingAction.NAME)
);
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(tuple.v1(), metaData, buildAuthorizedIndices(user, tuple.v2())));
() -> resolveIndices(tuple.v1(), buildAuthorizedIndices(user, tuple.v2())).getLocal());
assertEquals("no such index", e.getMessage());
}
@ -1103,21 +1135,22 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
new Tuple<>(new DeleteIndexRequest("*:*").indicesOptions(options), DeleteIndexAction.NAME),
new Tuple<>(new PutMappingRequest("*:*").indicesOptions(options), PutMappingAction.NAME)
);
final Set<String> resolved = defaultIndicesResolver.resolve(tuple.v1(), metaData, buildAuthorizedIndices(user, tuple.v2()));
final ResolvedIndices resolved = resolveIndices(tuple.v1(), buildAuthorizedIndices(user, tuple.v2()));
assertNoIndices((IndicesRequest.Replaceable) tuple.v1(), resolved);
}
public void testCompositeIndicesRequestIsNotSupported() {
TransportRequest request = randomFrom(new MultiSearchRequest(), new MultiGetRequest(),
new MultiTermVectorsRequest(), new BulkRequest());
expectThrows(IllegalStateException.class, () -> defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(user, MultiSearchAction.NAME)));
expectThrows(IllegalStateException.class, () -> resolveIndices(request,
buildAuthorizedIndices(user, MultiSearchAction.NAME)));
}
public void testResolveAdminAction() {
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(user, DeleteIndexAction.NAME);
{
RefreshRequest request = new RefreshRequest("*");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, DeleteIndexAction.NAME));
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
@ -1125,7 +1158,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
}
{
DeleteIndexRequest request = new DeleteIndexRequest("*");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, DeleteIndexAction.NAME));
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
@ -1138,35 +1171,35 @@ public class IndicesAndAliasesResolverTests 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(request,
metaData, buildAuthorizedIndices(userNoIndices, IndicesExistsAction.NAME)));
assertNoIndices(request, resolveIndices(request,
buildAuthorizedIndices(userNoIndices, IndicesExistsAction.NAME)));
}
{
IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist");
assertNoIndices(request, defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(user, IndicesExistsAction.NAME)));
assertNoIndices(request, resolveIndices(request,
buildAuthorizedIndices(user, IndicesExistsAction.NAME)));
}
{
IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist_*");
assertNoIndices(request, defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(user, IndicesExistsAction.NAME)));
assertNoIndices(request, resolveIndices(request,
buildAuthorizedIndices(user, IndicesExistsAction.NAME)));
}
}
public void testXPackUserHasAccessToSecurityIndex() {
SearchRequest request = new SearchRequest();
{
Set<String> indices = defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME));
}
{
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest();
aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SecurityLifecycleService.SECURITY_INDEX_NAME));
Set<String> indices = defaultIndicesResolver.resolve(aliasesRequest,
metaData, buildAuthorizedIndices(XPackUser.INSTANCE, IndicesAliasesAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME));
}
}
@ -1178,16 +1211,16 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
{
SearchRequest request = new SearchRequest();
Set<String> indices = defaultIndicesResolver.resolve(request,
metaData, buildAuthorizedIndices(allAccessUser, SearchAction.NAME));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityLifecycleService.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));
final AuthorizedIndices authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityLifecycleService.SECURITY_INDEX_NAME)));
}
}
@ -1195,14 +1228,14 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testUnauthorizedDateMathExpressionIgnoreUnavailable() {
SearchRequest request = new SearchRequest("<datetime-{now/M}>");
request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean()));
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
assertNoIndices(request, resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)));
assertEquals("no such index" , e.getMessage());
}
@ -1210,7 +1243,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
SearchRequest request = new SearchRequest("<datetime-{now/M}>");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean()));
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)));
assertEquals("no such index" , e.getMessage());
}
@ -1227,7 +1260,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
final boolean expandIndicesOpen = Regex.isSimpleMatchPattern(pattern) ? true : randomBoolean();
request.indicesOptions(IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), expandIndicesOpen, randomBoolean()));
}
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME));
List<String> indices = resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)).getLocal();
assertThat(indices.size(), equalTo(1));
assertThat(request.indices()[0], equalTo(dateTimeIndex));
}
@ -1235,14 +1268,14 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
public void testMissingDateMathExpressionIgnoreUnavailable() {
SearchRequest request = new SearchRequest("<foobar-{now/M}>");
request.indicesOptions(IndicesOptions.fromOptions(true, true, randomBoolean(), randomBoolean()));
assertNoIndices(request, defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
assertNoIndices(request, resolveIndices(request, 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(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)));
assertEquals("no such index" , e.getMessage());
}
@ -1250,7 +1283,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
SearchRequest request = new SearchRequest("<foobar-{now/M}>");
request.indicesOptions(IndicesOptions.fromOptions(false, randomBoolean(), randomBoolean(), randomBoolean()));
IndexNotFoundException e = expectThrows(IndexNotFoundException.class,
() -> defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, SearchAction.NAME)));
() -> resolveIndices(request, buildAuthorizedIndices(user, SearchAction.NAME)));
assertEquals("no such index" , e.getMessage());
}
@ -1261,7 +1294,8 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
roleMap.put("role", new RoleDescriptor("role", null,
new IndicesPrivileges[] { IndicesPrivileges.builder().indices(authorizedIndices).privileges("all").build() }, null));
GetAliasesRequest request = new GetAliasesRequest("<datetime-{now/M}>").indices("foo", "foofoo");
Set<String> indices = defaultIndicesResolver.resolve(request, metaData, buildAuthorizedIndices(user, GetAliasesAction.NAME));
List<String> indices =
resolveIndices(request, buildAuthorizedIndices(user, GetAliasesAction.NAME)).getLocal();
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"<datetime-{now/M}>", "foo", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length));
@ -1272,6 +1306,7 @@ public class IndicesAndAliasesResolverTests 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) {
PlainActionFuture<Role> rolesListener = new PlainActionFuture<>();
authzService.roles(user, rolesListener);
@ -1284,9 +1319,20 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0));
}
private static void assertNoIndices(IndicesRequest.Replaceable request, Set<String> resolvedIndices) {
assertEquals(1, resolvedIndices.size());
assertEquals(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER, resolvedIndices.iterator().next());
private ResolvedIndices resolveIndices(TransportRequest request, AuthorizedIndices authorizedIndices) {
return defaultIndicesResolver.resolve(request, this.metaData, authorizedIndices);
}
private static void assertNoIndices(IndicesRequest.Replaceable request, ResolvedIndices resolvedIndices) {
final List<String> localIndices = resolvedIndices.getLocal();
assertEquals(1, localIndices.size());
assertEquals(IndicesAndAliasesResolver.NO_INDEX_PLACEHOLDER, localIndices.iterator().next());
assertEquals(IndicesAndAliasesResolver.NO_INDICES_LIST, Arrays.asList(request.indices()));
assertEquals(0, resolvedIndices.getRemote().size());
}
private void assertSameValues(List<String> indices, String[] expectedIndices) {
assertThat(indices.stream().distinct().count(), equalTo((long)expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
}
}