diff --git a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java index 91f160ff690..2924f2295c0 100644 --- a/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java +++ b/elasticsearch/src/main/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java @@ -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 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 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. diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 1f0cd9b8156..b1ef5772d22 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -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 diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java index a75e8a013e8..86f9cd92cb2 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/DefaultIndicesResolverTests.java @@ -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 indices = defaultIndicesResolver.resolve(XPackUser.INSTANCE, SearchAction.NAME, request, metaData); diff --git a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java index ec6a76ee60c..59daa8c8e77 100644 --- a/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java +++ b/elasticsearch/src/test/java/org/elasticsearch/xpack/security/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java @@ -191,10 +191,27 @@ public class IndicesAndAliasesResolverIntegrationTests extends SecurityIntegTest assertReturnedIndices(searchResponse, "test10"); } + public void testMissingDateMath() { expectThrows(IndexNotFoundException.class, () -> client().prepareSearch("").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");