special case IndicesExistsRequest to make sure index not found is never thrown while resolving indices

Like es core does in TransportIndicesExistsAction, we should only consider expandWildcardsOpen and expandWildcardsClosed out of the indices options passed in with IndicesExistsRequest. ignore_unavailable and allow_no_indices should always be considered both true, to prevent the request from throwing exception as it is supposed to return true or false, no exceptions.

Original commit: elastic/x-pack-elasticsearch@daa274b3fd
This commit is contained in:
javanna 2016-09-30 16:12:27 +02:00 committed by Luca Cavanna
parent d27c4bee82
commit c6edec254a
4 changed files with 56 additions and 10 deletions

View File

@ -10,6 +10,7 @@ import org.elasticsearch.action.CompositeIndicesRequest;
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.support.IndicesOptions;
import org.elasticsearch.cluster.metadata.AliasOrIndex;
@ -98,12 +99,20 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv
|| indicesRequest.indicesOptions().expandWildcardsClosed();
List<String> authorizedIndicesAndAliases = authzService.authorizedIndicesAndAliases(user, action);
IndicesOptions indicesOptions = indicesRequest.indicesOptions();
if (indicesRequest instanceof IndicesExistsRequest) {
//indices exists api should never throw exception, make sure that ignore_unavailable and allow_no_indices are true
//we have to mimic what TransportIndicesExistsAction#checkBlock does in es core
indicesOptions = IndicesOptions.fromOptions(true, true,
indicesOptions.expandWildcardsOpen(), indicesOptions.expandWildcardsClosed());
}
List<String> replacedIndices = new ArrayList<>();
// check for all and return list of authorized indices
if (IndexNameExpressionResolver.isAllIndices(indicesList(indicesRequest.indices()))) {
if (replaceWildcards) {
for (String authorizedIndex : authorizedIndicesAndAliases) {
if (isIndexVisible(authorizedIndex, indicesRequest.indicesOptions(), metaData)) {
if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) {
replacedIndices.add(authorizedIndex);
}
}
@ -112,15 +121,15 @@ public class DefaultIndicesAndAliasesResolver implements IndicesAndAliasesResolv
// we honour allow_no_indices like es core does.
} else {
replacedIndices = replaceWildcardsWithAuthorizedIndices(indicesRequest.indices(),
indicesRequest.indicesOptions(), metaData, authorizedIndicesAndAliases, replaceWildcards);
if (indicesRequest.indicesOptions().ignoreUnavailable()) {
indicesOptions, metaData, authorizedIndicesAndAliases, replaceWildcards);
if (indicesOptions.ignoreUnavailable()) {
//out of all the explicit names (expanded from wildcards and original ones that were left untouched)
//remove all the ones that the current user is not authorized for and ignore them
replacedIndices = replacedIndices.stream().filter(authorizedIndicesAndAliases::contains).collect(Collectors.toList());
}
}
if (replacedIndices.isEmpty()) {
if (indicesRequest.indicesOptions().allowNoIndices()) {
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.

View File

@ -17,6 +17,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
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.GetIndexRequest;
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
import org.elasticsearch.action.admin.indices.recovery.RecoveryRequest;
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsAction;
@ -293,7 +294,7 @@ public class AuthorizationServiceTests extends ESTestCase {
}
public void testAuthorizeIndicesFailures() {
TransportRequest request = new IndicesExistsRequest("b");
TransportRequest request = new GetIndexRequest().indices("b");
ClusterState state = mock(ClusterState.class);
User user = new User("test user", "a_all");
when(rolesStore.role("a_all")).thenReturn(Role.builder("a_all").add(IndexPrivilege.ALL, "a").build());
@ -386,7 +387,7 @@ public class AuthorizationServiceTests extends ESTestCase {
}
public void testDenialForAnonymousUser() {
TransportRequest request = new IndicesExistsRequest("b");
TransportRequest request = new GetIndexRequest().indices("b");
ClusterState state = mock(ClusterState.class);
Settings settings = Settings.builder().put(AnonymousUser.ROLES_SETTING.getKey(), "a_all").build();
final AnonymousUser anonymousUser = new AnonymousUser(settings);
@ -411,7 +412,7 @@ public class AuthorizationServiceTests extends ESTestCase {
}
public void testDenialForAnonymousUserAuthorizationExceptionDisabled() {
TransportRequest request = new IndicesExistsRequest("b");
TransportRequest request = new GetIndexRequest().indices("b");
ClusterState state = mock(ClusterState.class);
Settings settings = Settings.builder()
.put(AnonymousUser.ROLES_SETTING.getKey(), "a_all")
@ -472,8 +473,8 @@ public class AuthorizationServiceTests extends ESTestCase {
}
public void testRunAsRequestWithRunAsUserWithoutPermission() {
TransportRequest request = new IndicesExistsRequest("a");
User user = new User("test user", new String[] { "can run as" }, new User("run as me", new String[] { "b" }));
TransportRequest request = new GetIndexRequest().indices("a");
User user = new User("test user", new String[] { "can run as" }, new User("run as me", "b"));
assertThat(user.runAs(), is(notNullValue()));
when(rolesStore.role("can run as")).thenReturn(Role
.builder("can run as")
@ -507,7 +508,7 @@ public class AuthorizationServiceTests extends ESTestCase {
}
public void testRunAsRequestWithValidPermissions() {
TransportRequest request = new IndicesExistsRequest("b");
TransportRequest request = new GetIndexRequest().indices("b");
User user = new User("test user", new String[] { "can run as" }, new User("run as me", new String[] { "b" }));
assertThat(user.runAs(), is(notNullValue()));
when(rolesStore.role("can run as")).thenReturn(Role

View File

@ -14,6 +14,8 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
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.get.MultiGetAction;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.search.MultiSearchAction;
@ -1020,6 +1022,23 @@ public class DefaultIndicesResolverTests extends ESTestCase {
assertThat(request.indices(), arrayContainingInAnyOrder(expectedIndices));
}
public void testIndicesExists() {
//verify that the ignore_unavailable and allow_no_indices get replaced like es core does, to make sure that
//indices exists api never throws exception due to missing indices, but only returns false instead.
{
IndicesExistsRequest request = new IndicesExistsRequest();
assertNoIndices(request, defaultIndicesResolver.resolve(userNoIndices, IndicesExistsAction.NAME, request, metaData));
}
{
IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist");
assertNoIndices(request, defaultIndicesResolver.resolve(user, IndicesExistsAction.NAME, request, metaData));
}
{
IndicesExistsRequest request = new IndicesExistsRequest("does_not_exist_*");
assertNoIndices(request, defaultIndicesResolver.resolve(user, IndicesExistsAction.NAME, request, metaData));
}
}
public void testXPackUserHasAccessToSecurityIndex() {
SearchRequest request = new SearchRequest();
Set<String> indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, SearchAction.NAME, request, metaData);

View File

@ -191,10 +191,27 @@ public class IndicesAndAliasesResolverIntegrationTests extends SecurityIntegTest
assertReturnedIndices(searchResponse, "test10");
}
public void testMissingDateMath() {
expectThrows(IndexNotFoundException.class, () -> client().prepareSearch("<logstash-{now/M}>").get());
}
public void testIndicesExists() {
createIndices("test1", "test2", "test3");
assertEquals(true, client().admin().indices().prepareExists("*").get().isExists());
assertEquals(true, client().admin().indices().prepareExists("_all").get().isExists());
assertEquals(true, client().admin().indices().prepareExists("test1", "test2").get().isExists());
assertEquals(true, client().admin().indices().prepareExists("test*").get().isExists());
assertEquals(false, client().admin().indices().prepareExists("does_not_exist").get().isExists());
assertEquals(false, client().admin().indices().prepareExists("does_not_exist*").get().isExists());
}
public void testMultiSearchUnauthorizedIndex() {
//index1 is not authorized, the whole request fails due to that
createIndices("test1", "test2", "test3", "index1");