Indices resolution: special treatment for IndicesAliasesRequest

IndicesAliasesRequest needs to be authorized against both indices and aliases. That means that the following request

curl -XPOST 'http://localhost:9200/_aliases' -d '
{
"actions" : [
{ "add" : { "index" : "test1", "alias" : "alias1" } }
]
}'

requires now indices:admin/aliases privileges for both test1 and alias1.

Added manage_aliases shortcut privilege that points to indices:admin/aliases.

Also, IndicesAliasesRequest used to not support replacing its indices (request doesn't implement IndicesRequest.Replaceable in es core). That can be worked around as well through the special treatment that we are introducing in shield for this specific request. Given that it is a composite action, every single operation has now its wildcards replaced with authorized indices (supported among aliases as well in case of remove operations). If any of the operation ends up relating to no indices after wildcards expansion, the whole request fails.

The DefaultIndicesResolver#explodeWildcards method, which used to expand wildcards as es core would do it, is not needed anymore, as all of the requests that support wildcards have now their indices properly replaced.

Added also special authorization pass for create index, if the request body contains aliases. The index can only be created if the current user has permission to create the index and to create the aliases that are part of the same request.

Closes elastic/elasticsearch#112
Closes elastic/elasticsearch#557
Closes elastic/elasticsearch#529

Original commit: elastic/x-pack-elasticsearch@d7201e8a8b
This commit is contained in:
Luca Cavanna 2015-01-09 11:04:22 +01:00
parent 16c7cfa50f
commit 02682ff4ec
8 changed files with 723 additions and 82 deletions

View File

@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.action.admin.indices.create;
import org.elasticsearch.action.admin.indices.alias.Alias;
import java.util.Set;
/*
* Helper needed to retrieve aliases from a CreateIndexRequest, as the corresponding getter has package private visibility
* TODO Remove this class as soon as es core 1.5.0 is out
*/
public final class CreateIndexRequestHelper {
private CreateIndexRequestHelper() {
}
public static Set<Alias> aliases(CreateIndexRequest createIndexRequest) {
return createIndexRequest.aliases();
}
}

View File

@ -10,11 +10,15 @@ import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
import org.elasticsearch.action.search.ClearScrollAction; import org.elasticsearch.action.search.ClearScrollAction;
import org.elasticsearch.action.search.SearchScrollAction; import org.elasticsearch.action.search.SearchScrollAction;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestHelper;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.base.Predicate; import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.common.base.Predicates; import org.elasticsearch.common.base.Predicates;
import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.collect.Sets;
import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -145,22 +149,44 @@ public class InternalAuthorizationService extends AbstractComponent implements A
assert !indexNames.isEmpty() || request instanceof AnalyzeRequest assert !indexNames.isEmpty() || request instanceof AnalyzeRequest
: "no indices request other than the analyze api has optional indices thus the resolved indices must not be empty"; : "no indices request other than the analyze api has optional indices thus the resolved indices must not be empty";
if (!authorizeIndices(action, indexNames, permission.indices())) {
throw denial(user, action, request);
}
//if we are creating an index we need to authorize potential aliases created at the same time
if (Privilege.Index.CREATE_INDEX.predicate().apply(action)) {
assert request instanceof CreateIndexRequest;
Set<Alias> aliases = CreateIndexRequestHelper.aliases((CreateIndexRequest) request);
if (!aliases.isEmpty()) {
Set<String> aliasesAndIndices = Sets.newHashSet(indexNames);
for (Alias alias : aliases) {
aliasesAndIndices.add(alias.name());
}
if (!authorizeIndices("indices:admin/aliases", aliasesAndIndices, permission.indices())) {
throw denial(user, "indices:admin/aliases", request);
}
}
}
grant(user, action, request);
}
private boolean authorizeIndices(String action, Set<String> requestIndices, Permission.Indices permission) {
// now... every index that is associated with the request, must be granted // now... every index that is associated with the request, must be granted
// by at least one indices permission group // by at least one indices permission group
for (String index : indexNames) { for (String index : requestIndices) {
boolean granted = false; boolean granted = false;
for (Permission.Indices.Group group : permission.indices()) { for (Permission.Indices.Group group : permission) {
if (group.check(action, index)) { if (group.check(action, index)) {
granted = true; granted = true;
break; break;
} }
} }
if (!granted) { if (!granted) {
throw denial(user, action, request); return false;
} }
} }
return true;
grant(user, action, request);
} }
private Permission.Global permission(User user) { private Permission.Global permission(User user) {

View File

@ -108,6 +108,7 @@ public abstract class Privilege<P extends Privilege<P>> {
public static final Index ALL = new Index(Name.ALL, "indices:*"); public static final Index ALL = new Index(Name.ALL, "indices:*");
public static final Index MANAGE = new Index("manage", "indices:monitor/*", "indices:admin/*"); public static final Index MANAGE = new Index("manage", "indices:monitor/*", "indices:admin/*");
public static final Index CREATE_INDEX = new Index("create_index", "indices:admin/create"); public static final Index CREATE_INDEX = new Index("create_index", "indices:admin/create");
public static final Index MANAGE_ALIASES = new Index("manage_aliases", "indices:admin/aliases");
public static final Index MONITOR = new Index("monitor", "indices:monitor/*"); public static final Index MONITOR = new Index("monitor", "indices:monitor/*");
public static final Index DATA_ACCESS = new Index("data_access", "indices:data/*"); public static final Index DATA_ACCESS = new Index("data_access", "indices:data/*");
public static final Index CRUD = new Index("crud", "indices:data/write/*", "indices:data/read/*"); public static final Index CRUD = new Index("crud", "indices:data/write/*", "indices:data/read/*");
@ -119,7 +120,7 @@ public abstract class Privilege<P extends Privilege<P>> {
public static final Index WRITE = new Index("write", "indices:data/write/*"); public static final Index WRITE = new Index("write", "indices:data/write/*");
private static final Index[] values = new Index[] { private static final Index[] values = new Index[] {
NONE, ALL, MANAGE, CREATE_INDEX, MONITOR, DATA_ACCESS, CRUD, READ, SEARCH, GET, INDEX, DELETE, WRITE NONE, ALL, MANAGE, CREATE_INDEX, MANAGE_ALIASES, MONITOR, DATA_ACCESS, CRUD, READ, SEARCH, GET, INDEX, DELETE, WRITE
}; };
public static final Predicate<String> ACTION_MATCHER = Privilege.Index.ALL.predicate(); public static final Predicate<String> ACTION_MATCHER = Privilege.Index.ALL.predicate();

View File

@ -9,10 +9,11 @@ import org.elasticsearch.action.CompositeIndicesRequest;
import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.cluster.metadata.AliasAction;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.collect.*;
import org.elasticsearch.common.collect.Sets; import org.elasticsearch.common.hppc.ObjectLookupContainer;
import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.index.Index; import org.elasticsearch.index.Index;
import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.indices.IndexMissingException;
@ -65,56 +66,86 @@ public class DefaultIndicesResolver implements IndicesResolver<TransportRequest>
if (indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed()) { if (indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed()) {
if (indicesRequest instanceof IndicesRequest.Replaceable) { if (indicesRequest instanceof IndicesRequest.Replaceable) {
ImmutableList<String> authorizedIndices = authzService.authorizedIndicesAndAliases(user, action); ImmutableList<String> authorizedIndices = authzService.authorizedIndicesAndAliases(user, action);
List<String> indices = replaceWildcardsWithAuthorizedIndices(indicesRequest, metaData, authorizedIndices); List<String> indices = replaceWildcardsWithAuthorizedIndices(indicesRequest.indices(), indicesRequest.indicesOptions(), metaData, authorizedIndices);
//ignore the IndicesOptions#allowNoIndices and just throw exception if the wildcards expansion to authorized
//indices resulted in no indices. This is important as we always need to replace wildcards for security reason,
//to make sure that the operation is executed on the indices that we authorized it to execute on.
//If we can't replace because we got an empty set, we can only throw exception.
//Downside of this is that a single item exception is going to make fail the composite request that holds it as a whole.
if (indices == null || indices.isEmpty()) {
if (MetaData.isAllIndices(indicesRequest.indices())) {
throw new IndexMissingException(new Index(MetaData.ALL));
}
throw new IndexMissingException(new Index(Arrays.toString(indicesRequest.indices())));
}
((IndicesRequest.Replaceable) indicesRequest).indices(indices.toArray(new String[indices.size()])); ((IndicesRequest.Replaceable) indicesRequest).indices(indices.toArray(new String[indices.size()]));
return Sets.newHashSet(indices); return Sets.newHashSet(indices);
} }
if (containsWildcards(indicesRequest)) { assert indicesRequest instanceof IndicesAliasesRequest || !containsWildcards(indicesRequest) :
//used for requests that support wildcards but don't allow to replace their indices (e.g. IndicesAliasesRequest) "IndicesAliasesRequest is the only external request known to support wildcards that doesn't support replacing its indices";
//potentially insecure as cluster state may change hence we may end up resolving to different indices on different nodes
assert indicesRequest instanceof IndicesAliasesRequest
: "IndicesAliasesRequest is the only request known to support wildcards that doesn't support replacing its indices";
return Sets.newHashSet(explodeWildcards(indicesRequest, metaData));
}
//NOTE: shard level requests do support wildcards (as they hold the original indices options) but don't support replacing their indices. //NOTE: shard level requests do support wildcards (as they hold the original indices options) but don't support replacing their indices.
//That is fine though because they never contain wildcards, as they get replaced as part of the authorization of their //That is fine though because they never contain wildcards, as they get replaced as part of the authorization of their
//corresponding parent request on the coordinating node. Hence wildcards don't get replaced nor exploded for shard level requests. //corresponding parent request on the coordinating node. Hence wildcards don't need to get replaced nor exploded for shard level requests.
} }
if (indicesRequest instanceof IndicesAliasesRequest) {
//special treatment for IndicesAliasesRequest since we need to extract indices from indices() as well as aliases()
//Also, we need to replace wildcards in both with authorized indices and/or aliases (IndicesAliasesRequest doesn't implement Replaceable)
IndicesAliasesRequest request = (IndicesAliasesRequest) indicesRequest;
ImmutableList<String> authorizedIndices = authzService.authorizedIndicesAndAliases(user, action);
Set<String> finalIndices = Sets.newHashSet();
List<String> authorizedAliases = null;
for (IndicesAliasesRequest.AliasActions aliasActions : request.getAliasActions()) {
//replace indices with authorized ones if needed
if (indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed()) {
//Note: the indices that the alias operation maps to might end up containing aliases, since authorized indices can also be aliases.
//This is fine as es core resolves them to concrete indices anyway before executing the actual operation.
//Also es core already allows to specify aliases among indices, they will just be resolved (alias to alias is not supported).
//e.g. index: foo* gets resolved in core to anything that matches the expression, aliases included, hence their corresponding indices.
List<String> indices = replaceWildcardsWithAuthorizedIndices(aliasActions.indices(), indicesRequest.indicesOptions(), metaData, authorizedIndices);
aliasActions.indices(indices.toArray(new String[indices.size()]));
}
Collections.addAll(finalIndices, aliasActions.indices());
//replace aliases with authorized ones if needed
if (aliasActions.actionType() == AliasAction.Type.REMOVE) {
//lazily initialize a list of all the authorized aliases (filtering concrete indices out)
if (authorizedAliases == null) {
authorizedAliases = Lists.newArrayList();
ObjectLookupContainer<String> existingAliases = metaData.aliases().keys();
for (String authorizedIndex : authorizedIndices) {
if (existingAliases.contains(authorizedIndex)) {
authorizedAliases.add(authorizedIndex);
}
}
}
List<String> finalAliases = Lists.newArrayList();
for (String aliasPattern : aliasActions.aliases()) {
if (aliasPattern.equals(MetaData.ALL)) {
finalAliases.addAll(authorizedAliases);
} else if (Regex.isSimpleMatchPattern(aliasPattern)) {
for (String authorizedAlias : authorizedAliases) {
if (Regex.simpleMatch(aliasPattern, authorizedAlias)) {
finalAliases.add(authorizedAlias);
}
}
} else {
finalAliases.add(aliasPattern);
}
}
//throw exception if the wildcards expansion to authorized aliases resulted in no indices.
// This is important as we always need to replace wildcards for security reason,
//to make sure that the operation is executed on the aliases that we authorized it to execute on.
//If we can't replace because we got an empty set, we can only throw exception.
if (finalAliases.isEmpty()) {
throw new IndexMissingException(new Index(Arrays.toString(aliasActions.aliases())));
}
aliasActions.aliases(finalAliases.toArray(new String[finalAliases.size()]));
}
Collections.addAll(finalIndices, aliasActions.aliases());
}
return finalIndices;
}
return Sets.newHashSet(indicesRequest.indices()); return Sets.newHashSet(indicesRequest.indices());
} }
/*
* Explodes wildcards based on default core behaviour. Used for IndicesAliasesRequest only as it doesn't support
* replacing its indices. It will go away once that gets fixed.
*/
private String[] explodeWildcards(IndicesRequest indicesRequest, MetaData metaData) {
//note that "_all" will map to concrete indices only, as the same happens in core
//which is different from "*" as the latter expands to all indices and aliases
if (MetaData.isAllIndices(indicesRequest.indices())) {
if (indicesRequest.indicesOptions().expandWildcardsOpen() && indicesRequest.indicesOptions().expandWildcardsClosed()) {
return metaData.concreteAllIndices();
}
if (indicesRequest.indicesOptions().expandWildcardsOpen()) {
return metaData.concreteAllOpenIndices();
}
return metaData.concreteAllClosedIndices();
}
return metaData.convertFromWildcards(indicesRequest.indices(), indicesRequest.indicesOptions());
}
private boolean containsWildcards(IndicesRequest indicesRequest) { private boolean containsWildcards(IndicesRequest indicesRequest) {
if (MetaData.isAllIndices(indicesRequest.indices())) { if (MetaData.isAllIndices(indicesRequest.indices())) {
return true; return true;
@ -127,22 +158,22 @@ public class DefaultIndicesResolver implements IndicesResolver<TransportRequest>
return false; return false;
} }
private List<String> replaceWildcardsWithAuthorizedIndices(IndicesRequest indicesRequest, MetaData metaData, List<String> authorizedIndices) { private List<String> replaceWildcardsWithAuthorizedIndices(String[] indices, IndicesOptions indicesOptions, MetaData metaData, List<String> authorizedIndices) {
if (MetaData.isAllIndices(indicesRequest.indices())) { if (MetaData.isAllIndices(indices)) {
List<String> visibleIndices = new ArrayList<>(); List<String> visibleIndices = new ArrayList<>();
for (String authorizedIndex : authorizedIndices) { for (String authorizedIndex : authorizedIndices) {
if (isIndexVisible(authorizedIndex, indicesRequest.indicesOptions(), metaData)) { if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) {
visibleIndices.add(authorizedIndex); visibleIndices.add(authorizedIndex);
} }
} }
return visibleIndices; return throwExceptionIfNoIndicesWereResolved(indices, visibleIndices);
} }
//the order matters when it comes to + and - (see MetaData#convertFromWildcards) //the order matters when it comes to + and - (see MetaData#convertFromWildcards)
List<String> finalIndices = new ArrayList<>(); List<String> finalIndices = new ArrayList<>();
for (int i = 0; i < indicesRequest.indices().length; i++) { for (int i = 0; i < indices.length; i++) {
String index = indicesRequest.indices()[i]; String index = indices[i];
String aliasOrIndex; String aliasOrIndex;
boolean minus = false; boolean minus = false;
if (index.charAt(0) == '+') { if (index.charAt(0) == '+') {
@ -152,7 +183,7 @@ public class DefaultIndicesResolver implements IndicesResolver<TransportRequest>
//mimic the MetaData#convertFromWilcards behaviour with "-index" syntax //mimic the MetaData#convertFromWilcards behaviour with "-index" syntax
//but instead of adding all the indices, add only the ones that the user is authorized for //but instead of adding all the indices, add only the ones that the user is authorized for
for (String authorizedIndex : authorizedIndices) { for (String authorizedIndex : authorizedIndices) {
if (isIndexVisible(authorizedIndex, indicesRequest.indicesOptions(), metaData)) { if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) {
finalIndices.add(authorizedIndex); finalIndices.add(authorizedIndex);
} }
} }
@ -169,7 +200,7 @@ public class DefaultIndicesResolver implements IndicesResolver<TransportRequest>
if (minus) { if (minus) {
finalIndices.remove(authorizedIndex); finalIndices.remove(authorizedIndex);
} else { } else {
if (isIndexVisible(authorizedIndex, indicesRequest.indicesOptions(), metaData)) { if (isIndexVisible(authorizedIndex, indicesOptions, metaData)) {
finalIndices.add(authorizedIndex); finalIndices.add(authorizedIndex);
} }
} }
@ -188,7 +219,22 @@ public class DefaultIndicesResolver implements IndicesResolver<TransportRequest>
} }
} }
return finalIndices; return throwExceptionIfNoIndicesWereResolved(indices, finalIndices);
}
private List<String> throwExceptionIfNoIndicesWereResolved(String[] originalIndices, List<String> resolvedIndices) {
//ignore the IndicesOptions#allowNoIndices and just throw exception if the wildcards expansion to authorized
//indices resulted in no indices. This is important as we always need to replace wildcards for security reason,
//to make sure that the operation is executed on the indices that we authorized it to execute on.
//If we can't replace because we got an empty set, we can only throw exception.
//Downside of this is that a single item exception is going to make fail the composite request that holds it as a whole.
if (resolvedIndices == null || resolvedIndices.isEmpty()) {
if (MetaData.isAllIndices(originalIndices)) {
throw new IndexMissingException(new Index(MetaData.ALL));
}
throw new IndexMissingException(new Index(Arrays.toString(originalIndices)));
}
return resolvedIndices;
} }
private static boolean isIndexVisible(String index, IndicesOptions indicesOptions, MetaData metaData) { private static boolean isIndexVisible(String index, IndicesOptions indicesOptions, MetaData metaData) {

View File

@ -41,5 +41,10 @@ public class VersionCompatibilityTests extends ElasticsearchTestCase {
* see https://github.com/elasticsearch/elasticsearch/pull/9134 {@link org.elasticsearch.shield.transport.netty.SecuredMessageChannelHandler} * see https://github.com/elasticsearch/elasticsearch/pull/9134 {@link org.elasticsearch.shield.transport.netty.SecuredMessageChannelHandler}
*/ */
assertThat("Cleanup SecuredMessageChannelHandler class and remove needless code, fixed in es core 1.5", Version.CURRENT.onOrBefore(Version.V_1_4_2), is(true)); assertThat("Cleanup SecuredMessageChannelHandler class and remove needless code, fixed in es core 1.5", Version.CURRENT.onOrBefore(Version.V_1_4_2), is(true));
/**
* see https://github.com/elasticsearch/elasticsearch/pull/9273 {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequestHelper}
*/
assertThat("Remove CreateIndexRequestHelper class, fixed in es core 1.5", Version.CURRENT.onOrBefore(Version.V_1_4_2), is(true));
} }
} }

View File

@ -0,0 +1,371 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.shield.authz;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.test.ShieldIntegrationTest;
import org.junit.Test;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.BASIC_AUTH_HEADER;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.CoreMatchers.containsString;
@ClusterScope(scope = Scope.SUITE)
public class IndexAliasesTests extends ShieldIntegrationTest {
@Override
protected String configUsers() {
return super.configUsers() +
"create_only:{plain}test123\n" +
"create_test_aliases_test:{plain}test123\n" +
"create_test_aliases_alias:{plain}test123\n" +
"create_test_aliases_test_alias:{plain}test123\n" +
"aliases_only:{plain}test123\n";
}
@Override
protected String configUsersRoles() {
return super.configUsersRoles() +
"create_only:create_only\n" +
"create_test_aliases_test:create_test_aliases_test\n" +
"create_test_aliases_alias:create_test_aliases_alias\n" +
"create_test_aliases_test_alias:create_test_aliases_test_alias\n" +
"aliases_only:aliases_only\n";
}
@Override
protected String configRoles() {
return super.configRoles() + "\n" +
//role that has create index only privileges
"create_only:\n" +
" indices:\n" +
" '*': create_index\n" +
//role that has create index and managa aliases on test_*, not enough to manage aliases outside of test_* namespace
"create_test_aliases_test:\n" +
" indices:\n" +
" 'test_*': create_index,manage_aliases\n" +
//role that has create index on test_* and manage aliases on alias_*, can't create aliases pointing to test_* though
"create_test_aliases_alias:\n" +
" indices:\n" +
" 'test_*': create_index\n" +
" 'alias_*': manage_aliases\n" +
//role that has create index on test_* and manage_aliases on both alias_* and test_*
"create_test_aliases_test_alias:\n" +
" indices:\n" +
" 'test_*': create_index\n" +
" 'alias_*,test_*': manage_aliases\n" +
//role that has manage_aliases only on both test_* and alias_*
"aliases_only:\n" +
" indices:\n" +
" 'alias_*,test_*': manage_aliases\n";
}
@Test
public void testCreateIndexThenAliasesCreateOnlyPermission() {
//user has create permission only: allows to create indices, manage_aliases is required to add/remove aliases
assertAcked(client().admin().indices().prepareCreate("test_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))));
try {
client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
}
try {
client().admin().indices().prepareAliases().addAlias("test_*", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[test_*]"));
}
}
@Test
public void testCreateIndexAndAliasesCreateOnlyPermission() {
//user has create permission only: allows to create indices, manage_aliases is required to add aliases although they are part of the same create index request
try {
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_2"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("create index should have failed due to missing manage_aliases privileges");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
}
}
@Test
public void testDeleteAliasesCreateOnlyPermission() {
//user has create permission only: allows to create indices, manage_aliases is required to add/remove aliases
try {
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_only]"));
}
try {
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_*")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[alias_*"));
}
try {
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_only", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[_all]"));
}
}
@Test
public void testCreateIndexThenAliasesCreateAndAliasesPermission() {
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
assertAcked(client().admin().indices().prepareCreate("test_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareAliases().addAlias("test_*", "test_alias_2")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
try {
//fails: user doesn't have manage_aliases on alias_1
client().admin().indices().prepareAliases().addAlias("test_1", "alias_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges on alias_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
}
}
@Test
public void testCreateIndexAndAliasesCreateAndAliasesPermission() {
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
try {
//fails: user doesn't have manage_aliases on alias_1
client().admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_2"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
fail("create index should have failed due to missing manage_aliases privileges on alias_2");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
}
}
@Test
public void testDeleteAliasesCreateAndAliasesPermission() {
//user has create and manage_aliases permission on test_*. manage_aliases is required to add/remove aliases on both aliases and indices
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias_1")).addAlias(new Alias("test_alias_2"))
.addAlias(new Alias("test_alias_3")).addAlias(new Alias("test_alias_4"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_*", "test_alias_2")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
//ok: user has manage_aliases on test_*
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))));
try {
//fails: all aliases have been deleted, no existing aliases match test_alias_*
client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias_*")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to no existing matching aliases to expand test_alias_* to");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[test_alias_*]"));
}
try {
//fails: all aliases have been deleted, no existing aliases match _all
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to no existing matching aliases to expand _all to");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[_all]"));
}
try {
//fails: user doesn't have manage_aliases on alias_1
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges on alias_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test]"));
}
}
@Test
public void testCreateIndexThenAliasesCreateAndAliasesPermission2() {
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
assertAcked(client().admin().indices().prepareCreate("test_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))));
try {
//fails: user doesn't have manage aliases on test_1
client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
try {
//fails: user doesn't have manage aliases on test_1
client().admin().indices().prepareAliases().addAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
try {
//fails: user doesn't have manage aliases on test_*, no matching indices to replace wildcards
client().admin().indices().prepareAliases().addAlias("test_*", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[test_*]"));
}
}
@Test
public void testCreateIndexAndAliasesCreateAndAliasesPermission2() {
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
try {
//fails: user doesn't have manage_aliases on test_1, create index is rejected as a whole
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("create index should have failed due to missing manage_aliases privileges on test_1 and test_alias");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
try {
//fails: user doesn't have manage_aliases on test_*, create index is rejected as a whole
client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("create index should have failed due to missing manage_aliases privileges on test_1 and test_alias");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
}
@Test
public void testDeleteAliasesCreateAndAliasesPermission2() {
//user has create permission on test_* and manage_aliases permission on alias_*. manage_aliases is required to add/remove aliases on both aliases and indices
try {
//fails: user doesn't have manage_aliases on test_1
client().admin().indices().prepareAliases().removeAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
try {
//fails: user doesn't have manage_aliases on test_1
client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges on test_1");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_alias]"));
}
try {
//fails: user doesn't have manage_aliases on test_*, wildcards can't get replaced
client().admin().indices().prepareAliases().removeAlias("test_*", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_alias", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges on test_*");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[test_*]"));
}
}
@Test
public void testCreateIndexThenAliasesCreateAndAliasesPermission3() {
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
assertAcked(client().admin().indices().prepareCreate("test_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
assertAcked(client().admin().indices().prepareAliases().addAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
assertAcked(client().admin().indices().prepareAliases().addAlias("test_*", "alias_2")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
}
@Test
public void testCreateIndexAndAliasesCreateAndAliasesPermission3() {
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
assertAcked(client().admin().indices().prepareCreate("test_2").addAlias(new Alias("test_alias_2")).addAlias(new Alias("alias_2"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
}
@Test
public void testDeleteAliasesCreateAndAliasesPermission3() {
//user has create permission on test_* and manage_aliases permission on test_*,alias_*. All good.
assertAcked(client().admin().indices().prepareCreate("test_1").addAlias(new Alias("test_alias")).addAlias(new Alias("alias_1"))
.addAlias(new Alias("alias_2")).addAlias(new Alias("alias_3"))
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
try {
//fails: user doesn't have manage_aliases privilege on non_authorized
client().admin().indices().prepareAliases().removeAlias("test_1", "non_authorized").removeAlias("test_1", "test_alias")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to missing manage_aliases privileges on non_authorized");
} catch(AuthorizationException e) {
assertThat(e.getMessage(), containsString("action [indices:admin/aliases] is unauthorized for user [create_test_aliases_test_alias]"));
}
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_1", "alias_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
assertAcked(client().admin().indices().prepareAliases().removeAlias("test_*", "_all")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))));
try {
//fails: all aliases have been deleted, _all can't be resolved to any existing authorized aliases
client().admin().indices().prepareAliases().removeAlias("test_1", "_all")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("create_test_aliases_test_alias", new SecuredString("test123".toCharArray()))).get();
fail("remove alias should have failed due to no existing aliases matching _all");
} catch(IndexMissingException e) {
assertThat(e.getMessage(), containsString("[_all]"));
}
}
@Test(expected = AuthorizationException.class)
public void testCreateIndexAliasesOnlyPermission() {
client().admin().indices().prepareCreate("test_1")
.putHeader(BASIC_AUTH_HEADER, basicAuthHeaderValue("aliases_only", new SecuredString("test123".toCharArray()))).get();
}
}

View File

@ -91,7 +91,7 @@ public class PrivilegeTests extends ElasticsearchTestCase {
} }
@Test @Test
public void testCluster_InvalidNaem() throws Exception { public void testCluster_InvalidName() throws Exception {
thrown.expect(ElasticsearchIllegalArgumentException.class); thrown.expect(ElasticsearchIllegalArgumentException.class);
Privilege.Name actionName = new Privilege.Name("foobar"); Privilege.Name actionName = new Privilege.Name("foobar");
Privilege.Cluster.get(actionName); Privilege.Cluster.get(actionName);

View File

@ -19,6 +19,7 @@ import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Requests; import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.metadata.AliasAction;
import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
@ -33,8 +34,7 @@ import org.junit.Test;
import java.util.Set; import java.util.Set;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.arrayContaining;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -70,6 +70,7 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
when(authzService.authorizedIndicesAndAliases(user, DeleteIndexAction.NAME)).thenReturn(ImmutableList.copyOf(authorizedIndices)); when(authzService.authorizedIndicesAndAliases(user, DeleteIndexAction.NAME)).thenReturn(ImmutableList.copyOf(authorizedIndices));
when(authzService.authorizedIndicesAndAliases(user, DeleteByQueryAction.NAME)).thenReturn(ImmutableList.copyOf(authorizedIndices)); when(authzService.authorizedIndicesAndAliases(user, DeleteByQueryAction.NAME)).thenReturn(ImmutableList.copyOf(authorizedIndices));
userNoIndices = new User.Simple("test", "test"); userNoIndices = new User.Simple("test", "test");
when(authzService.authorizedIndicesAndAliases(userNoIndices, IndicesAliasesAction.NAME)).thenReturn(ImmutableList.<String>of());
when(authzService.authorizedIndicesAndAliases(userNoIndices, SearchAction.NAME)).thenReturn(ImmutableList.<String>of()); when(authzService.authorizedIndicesAndAliases(userNoIndices, SearchAction.NAME)).thenReturn(ImmutableList.<String>of());
when(authzService.authorizedIndicesAndAliases(userNoIndices, MultiSearchAction.NAME)).thenReturn(ImmutableList.<String>of()); when(authzService.authorizedIndicesAndAliases(userNoIndices, MultiSearchAction.NAME)).thenReturn(ImmutableList.<String>of());
@ -84,7 +85,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -96,7 +96,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -108,7 +107,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -120,7 +118,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -132,7 +129,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"}; String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -144,7 +140,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"}; String[] replacedIndices = new String[]{"barbaz", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -156,7 +151,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar"}; String[] replacedIndices = new String[]{"bar"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -168,7 +162,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "bar-closed"}; String[] replacedIndices = new String[]{"bar", "bar-closed"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -180,7 +173,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "barbaz"}; String[] replacedIndices = new String[]{"bar", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -192,7 +184,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"}; String[] replacedIndices = new String[]{"bar", "bar-closed", "barbaz"};
assertThat(indices.size(), equalTo(replacedIndices.length)); assertThat(indices.size(), equalTo(replacedIndices.length));
assertThat(indices, hasItems(replacedIndices)); assertThat(indices, hasItems(replacedIndices));
assertThat(request.indices().length, equalTo(replacedIndices.length));
assertThat(request.indices(), arrayContaining(replacedIndices)); assertThat(request.indices(), arrayContaining(replacedIndices));
} }
@ -238,27 +229,206 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
} }
@Test @Test
public void testResolveAllIndicesRequestNonReplaceable() { public void testResolveIndicesAliasesRequest() {
IndicesAliasesRequest request = new IndicesAliasesRequest(); IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias", "_all"); request.addAlias("alias1", "foo", "foofoo");
request.addAlias("alias2", "foo", "foobar");
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//we do expand _all (to concrete indices only!) but we don't replace them with authorized indices //the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"foofoo", "foo", "foobar", "bar", "bar2"}; String[] expectedIndices = new String[]{"alias1", "alias2", "foo", "foofoo", "foobar"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices(), equalTo(new String[]{"_all"})); assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
} }
@Test @Test
public void testResolveWildcardsIndicesRequestNonReplaceable() { public void testResolveIndicesAliasesRequestExistingAlias() {
IndicesAliasesRequest request = new IndicesAliasesRequest(); IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias", "*"); request.addAlias("alias1", "foo", "foofoo");
request.addAlias("foofoobar", "foo", "foobar");
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData); Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//we do explode wildcards but we don't replace them with authorized indices //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[]{"foofoobar", "foobar", "barbaz", "foo", "foofoo", "bar", "bar2"}; String[] expectedIndices = new String[]{"alias1", "foofoobar", "foo", "foofoo", "foobar"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices(), equalTo(new String[]{"*"})); assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foo", "foobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
}
@Test
public void testResolveIndicesAliasesRequestMissingIndex() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "foo", "foofoo");
request.addAlias("alias2", "missing");
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//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));
assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
}
@Test
public void testResolveWildcardsIndicesAliasesRequest() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "foo*");
request.addAlias("alias2", "bar*");
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//the union of all resolved indices and aliases gets returned, based on indices and aliases that user is authorized for
String[] expectedIndices = new String[]{"alias1", "alias2", "foofoo", "foofoobar", "bar"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
//wildcards get replaced on each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
}
@Test(expected = IndexMissingException.class)
public void testResolveWildcardsIndicesAliasesRequestNoMatchingIndices() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "foo*");
request.addAlias("alias2", "bar*");
request.addAlias("alias3", "non_matching_*");
//if a single operation contains wildcards and ends up being resolved to no indices, it makes the whole request fail
defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
}
@Test
public void testResolveAllIndicesAliasesRequest() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "_all");
request.addAlias("alias2", "_all");
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//the union of all resolved indices and aliases gets returned
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo", "alias1", "alias2"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
String[] replacedIndices = new String[]{"bar", "foofoobar", "foofoo"};
//_all gets replaced with all indices that user is authorized for, on each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContaining(replacedIndices));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("alias1"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining(replacedIndices));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("alias2"));
}
@Test(expected = IndexMissingException.class)
public void testResolveAllIndicesAliasesRequestNoAuthorizedIndices() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "_all");
//current user is not authorized for any index, _all resolves to no indices, the request fails
defaultIndicesResolver.resolve(userNoIndices, IndicesAliasesAction.NAME, request, metaData);
}
@Test(expected = IndexMissingException.class)
public void testResolveWildcardsIndicesAliasesRequestNoAuthorizedIndices() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAlias("alias1", "foo*");
//current user is not authorized for any index, foo* resolves to no indices, the request fails
defaultIndicesResolver.resolve(userNoIndices, IndicesAliasesAction.NAME, request, metaData);
}
@Test
public void testResolveIndicesAliasesRequestDeleteActions() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("foo", "foofoobar"));
request.addAliasAction(AliasAction.newRemoveAliasAction("foofoo", "barbaz"));
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//the union of all indices and aliases gets returned
String[] expectedIndices = new String[]{"foo", "foofoobar", "foofoo", "barbaz"};
assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("foofoo"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz"));
}
@Test
public void testResolveIndicesAliasesRequestDeleteActionsMissingIndex() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("foo", "foofoobar"));
request.addAliasAction(AliasAction.newRemoveAliasAction("missing_index", "missing_alias"));
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//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));
assertThat(indices, hasItems(expectedIndices));
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("missing_index"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("missing_alias"));
}
@Test
public void testResolveWildcardsIndicesAliasesRequestDeleteActions() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("foo*", "foofoobar"));
request.addAliasAction(AliasAction.newRemoveAliasAction("bar*", "barbaz"));
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//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));
assertThat(indices, hasItems(expectedIndices));
//wildcards get replaced within each single action
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("barbaz"));
}
@Test
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActions() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("*", "foo*"));
request.addAliasAction(AliasAction.newRemoveAliasAction("*bar", "foo*"));
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//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));
//alias foofoobar on both sides, that's fine, es core would do the same, same as above
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("bar", "foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar", "foofoobar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
}
@Test(expected = IndexMissingException.class)
public void testResolveAliasesWildcardsIndicesAliasesRequestDeleteActionsNoAuthorizedIndices() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("foo*", "foo*"));
//no authorized aliases match bar*, hence this action fails and makes the whole request fail
request.addAliasAction(AliasAction.newRemoveAliasAction("*bar", "bar*"));
defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
}
@Test
public void testResolveWildcardsIndicesAliasesRequestAddAndDeleteActions() {
IndicesAliasesRequest request = new IndicesAliasesRequest();
request.addAliasAction(AliasAction.newRemoveAliasAction("foo*", "foofoobar"));
request.addAliasAction(AliasAction.newAddAliasAction("bar*", "foofoobar"));
Set<String> indices = defaultIndicesResolver.resolve(user, IndicesAliasesAction.NAME, request, metaData);
//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));
//every single action has its indices replaced with matching (authorized) ones
assertThat(request.getAliasActions().get(0).indices(), arrayContaining("foofoobar", "foofoo"));
assertThat(request.getAliasActions().get(0).aliases(), arrayContaining("foofoobar"));
assertThat(request.getAliasActions().get(1).indices(), arrayContaining("bar"));
assertThat(request.getAliasActions().get(1).aliases(), arrayContaining("foofoobar"));
} }
//msearch is a CompositeIndicesRequest whose items (SearchRequests) implement IndicesRequest.Replaceable, wildcards will get replaced //msearch is a CompositeIndicesRequest whose items (SearchRequests) implement IndicesRequest.Replaceable, wildcards will get replaced
@ -379,7 +549,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"}; String[] expectedIndices = new String[]{"bar", "bar-closed", "foofoobar", "foofoo", "foofoo-closed"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices().length, equalTo(expectedIndices.length));
assertThat(request.indices(), arrayContaining(expectedIndices)); assertThat(request.indices(), arrayContaining(expectedIndices));
} }
@ -390,7 +559,6 @@ public class DefaultIndicesResolverTests extends ElasticsearchTestCase {
String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo"}; String[] expectedIndices = new String[]{"bar", "foofoobar", "foofoo"};
assertThat(indices.size(), equalTo(expectedIndices.length)); assertThat(indices.size(), equalTo(expectedIndices.length));
assertThat(indices, hasItems(expectedIndices)); assertThat(indices, hasItems(expectedIndices));
assertThat(request.indices().length, equalTo(expectedIndices.length));
assertThat(request.indices(), arrayContaining(expectedIndices)); assertThat(request.indices(), arrayContaining(expectedIndices));
} }