Adds SUGGEST index privilege

The `suggest` action was also added to the `SEARCH` privilege as one can execute suggestions under the `_search` API as well.

 Closes elastic/elasticsearch#24

Original commit: elastic/x-pack-elasticsearch@672809e199
This commit is contained in:
uboness 2015-01-22 16:49:11 +01:00
parent 97f229f667
commit a25d603b93
4 changed files with 159 additions and 3 deletions

View File

@ -13,6 +13,7 @@ import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.suggest.SuggestAction;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.common.cache.CacheBuilder;
@ -114,14 +115,15 @@ public abstract class Privilege<P extends Privilege<P>> {
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 READ = new Index("read", "indices:data/read/*");
public static final Index SEARCH = new Index("search", SearchAction.NAME + "*", GetAction.NAME + "*");
public static final Index SEARCH = new Index("search", SearchAction.NAME + "*", GetAction.NAME + "*", SuggestAction.NAME + "*");
public static final Index GET = new Index("get", GetAction.NAME + "*");
public static final Index SUGGEST = new Index("suggest", SuggestAction.NAME + "*");
public static final Index INDEX = new Index("index", "indices:data/write/index*", "indices:data/write/update");
public static final Index DELETE = new Index("delete", "indices:data/write/delete*");
public static final Index WRITE = new Index("write", "indices:data/write/*");
private static final Index[] values = new Index[] {
NONE, ALL, MANAGE, CREATE_INDEX, MANAGE_ALIASES, MONITOR, DATA_ACCESS, CRUD, READ, SEARCH, GET, INDEX, DELETE, WRITE
NONE, ALL, MANAGE, CREATE_INDEX, MANAGE_ALIASES, MONITOR, DATA_ACCESS, CRUD, READ, SEARCH, GET, SUGGEST, INDEX, DELETE, WRITE
};
public static final Predicate<String> ACTION_MATCHER = Privilege.Index.ALL.predicate();

View File

@ -8,7 +8,6 @@ package org.elasticsearch.shield.signature;
import org.apache.commons.codec.binary.Base64;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.base.Charsets;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;

View File

@ -0,0 +1,141 @@
/*
* 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.integration;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.shield.authc.support.SecuredStringTests;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.shield.authz.AuthorizationException;
import org.elasticsearch.test.ShieldIntegrationTest;
import org.junit.Test;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@ClusterScope(scope = Scope.SUITE)
public class SearchPermissionsTests extends ShieldIntegrationTest {
@Override
protected String configRoles() {
return super.configRoles() + "\n" +
"\n" +
"suggest_role:\n" +
" indices:\n" +
" 'a': suggest\n" +
"\n" +
"search_role:\n" +
" indices:\n" +
" 'a': search\n" +
"\n" +
"get_role:\n" +
" indices:\n" +
" 'a': get\n";
}
@Override
protected String configUsers() {
return super.configUsers() +
"suggest_user:{plain}passwd\n" +
"search_user:{plain}passwd\n" +
"get_user:{plain}passwd\n";
}
@Override
protected String configUsersRoles() {
return super.configUsersRoles() +
"suggest_role:suggest_user\n" +
"search_role:search_user\n" +
"get_role:get_user";
}
/**
* testing both "search" and "suggest" privileges can execute the suggest API
*/
@Test
public void testSuggestAPI() throws Exception {
IndexResponse indexResponse = index("a", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
SuggestResponse suggestResponse = client.prepareSuggest("a")
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd"))
.addSuggestion(SuggestBuilders.termSuggestion("name").field("name").text("val")).get();
assertNoFailures(suggestResponse);
assertThat(suggestResponse.getSuggest().size(), is(1));
suggestResponse = client.prepareSuggest("a")
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
.addSuggestion(SuggestBuilders.termSuggestion("name").field("name").text("val")).get();
assertNoFailures(suggestResponse);
assertThat(suggestResponse.getSuggest().size(), is(1));
try {
client.prepareSearch("a")
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd"))
.get();
fail("a user with only a suggest privilege cannot execute search");
} catch (AuthorizationException e) {
logger.error("failed to search", e);
// expected
}
}
/**
* testing both "search" and "get" privileges can execute the get API
*/
@Test
public void testGetAPI() throws Exception {
IndexResponse indexResponse = index("a", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
GetResponse getResponse = client.prepareGet("a", "type", indexResponse.getId())
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd"))
.get();
assertNotNull(getResponse);
assertThat(getResponse.getId(), equalTo(indexResponse.getId()));
getResponse = client.prepareGet("a", "type", indexResponse.getId())
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
.get();
assertNotNull(getResponse);
assertThat(getResponse.getId(), equalTo(indexResponse.getId()));
try {
client.prepareSearch("a")
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd"))
.get();
fail("a user with only a get privilege cannot execute search");
} catch (AuthorizationException e) {
logger.error("failed to search", e);
// expected
}
}
private static String userHeader(String username, String password) {
return UsernamePasswordToken.basicAuthHeaderValue(username, SecuredStringTests.build(password));
}
}

View File

@ -6,6 +6,9 @@
package org.elasticsearch.shield.authz;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.suggest.SuggestAction;
import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.shield.support.AutomatonPredicate;
import org.elasticsearch.shield.support.Automatons;
@ -176,4 +179,15 @@ public class PrivilegeTests extends ElasticsearchTestCase {
assertThat(predicate.apply("cluster:whatever"), is(false));
assertThat(predicate.apply("whatever"), is(false));
}
@Test
public void testSearchPrivilege() throws Exception {
Predicate<String> predicate = Privilege.Index.SEARCH.predicate();
assertThat(predicate.apply(SearchAction.NAME), is(true));
assertThat(predicate.apply(SearchAction.NAME + "/whatever"), is(true));
assertThat(predicate.apply(GetAction.NAME), is(true));
assertThat(predicate.apply(GetAction.NAME + "/whatever"), is(true));
assertThat(predicate.apply(SuggestAction.NAME), is(true));
assertThat(predicate.apply(SuggestAction.NAME + "/whatever"), is(true));
}
}