Changed search and get privileges

- separated `get` privilege from `search`. This should make it simpler for users to only allow search (and not get) when working with filtered aliases
- added multi search under the `search` privilege
- added the multi get under the `get` privilege

Original commit: elastic/x-pack-elasticsearch@6fafb08a2c
This commit is contained in:
uboness 2015-01-22 20:13:27 +01:00
parent a25d603b93
commit dd4a66bd6c
4 changed files with 102 additions and 33 deletions

View File

@ -12,6 +12,8 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.get.MultiGetAction;
import org.elasticsearch.action.search.MultiSearchAction;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.suggest.SuggestAction;
import org.elasticsearch.common.Strings;
@ -115,8 +117,8 @@ 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 + "*", SuggestAction.NAME + "*");
public static final Index GET = new Index("get", GetAction.NAME + "*");
public static final Index SEARCH = new Index("search", SearchAction.NAME + "*", MultiSearchAction.NAME + "*", SuggestAction.NAME + "*");
public static final Index GET = new Index("get", GetAction.NAME + "*", MultiGetAction.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*");

View File

@ -5,8 +5,10 @@
*/
package org.elasticsearch.integration;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.suggest.SuggestBuilders;
@ -16,6 +18,7 @@ import org.elasticsearch.shield.authz.AuthorizationException;
import org.elasticsearch.test.ShieldIntegrationTest;
import org.junit.Test;
import static org.elasticsearch.client.Requests.searchRequest;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
@ -24,15 +27,11 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@ClusterScope(scope = Scope.SUITE)
public class SearchPermissionsTests extends ShieldIntegrationTest {
public class SearchGetAndSuggestPermissionsTests 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" +
@ -40,23 +39,28 @@ public class SearchPermissionsTests extends ShieldIntegrationTest {
"\n" +
"get_role:\n" +
" indices:\n" +
" 'a': get\n";
" 'a': get\n" +
"\n" +
"suggest_role:\n" +
" indices:\n" +
" 'a': suggest\n";
}
@Override
protected String configUsers() {
return super.configUsers() +
"suggest_user:{plain}passwd\n" +
"search_user:{plain}passwd\n" +
"get_user:{plain}passwd\n";
"get_user:{plain}passwd\n" +
"suggest_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";
"get_role:get_user\n" +
"suggest_role:suggest_user\n";
}
/**
@ -98,7 +102,7 @@ public class SearchPermissionsTests extends ShieldIntegrationTest {
}
/**
* testing both "search" and "get" privileges can execute the get API
* testing that "search" privilege cannot execute the get API
*/
@Test
public void testGetAPI() throws Exception {
@ -112,29 +116,75 @@ public class SearchPermissionsTests extends ShieldIntegrationTest {
Client client = internalCluster().transportClient();
GetResponse getResponse = client.prepareGet("a", "type", indexResponse.getId())
try {
client.prepareGet("a", "type", indexResponse.getId())
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
.get();
fail("a user with only search privilege should not be authorized for a get request");
} catch (AuthorizationException ae) {
// expected
logger.error("could not get document", ae);
}
}
/**
* testing that "get" privilege can execute the mget API, and "search" privilege cannot execute mget
*/
@Test
public void testMultiGetAPI() throws Exception {
IndexResponse indexResponse = index("a", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
MultiGetResponse response = client.prepareMultiGet().add("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()));
assertNotNull(response);
assertThat(response.getResponses().length, is(1));
assertThat(response.getResponses()[0].getId(), equalTo(indexResponse.getId()));
try {
client.prepareSearch("a")
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd"))
client.prepareMultiGet().add("a", "type", indexResponse.getId())
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
.get();
fail("a user with only a get privilege cannot execute search");
} catch (AuthorizationException e) {
logger.error("failed to search", e);
fail("a user with only a search privilege should not be able to execute the mget API");
} catch (AuthorizationException ae) {
// expected
logger.error("could not mget documents", ae);
}
}
/**
* testing that "search" privilege can execute the msearch API
*/
@Test
public void testMultiSearchAPI() throws Exception {
IndexResponse indexResponse = index("a", "type", jsonBuilder()
.startObject()
.field("name", "value")
.endObject());
assertThat(indexResponse.isCreated(), is(true));
refresh();
Client client = internalCluster().transportClient();
MultiSearchResponse response = client.prepareMultiSearch().add(searchRequest("a").types("type"))
.putHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd"))
.get();
assertNotNull(response);
assertThat(response.getResponses().length, is(1));
SearchResponse first = response.getResponses()[0].getResponse();
assertNotNull(first);
assertNoFailures(first);
}
private static String userHeader(String username, String password) {
return UsernamePasswordToken.basicAuthHeaderValue(username, SecuredStringTests.build(password));
}

View File

@ -42,11 +42,12 @@ public class PermissionTests extends ElasticsearchTestCase {
assertThat(matcher1, is(matcher2));
}
// "baz_*foo", "/fool.*bar/"
private void testAllowedIndicesMatcher(Predicate<String> indicesMatcher) {
assertThat(indicesMatcher.apply("test_123"), is(true));
assertThat(indicesMatcher.apply("foobar"), is(true));
assertThat(indicesMatcher.apply("fool"), is(true));
assertThat(indicesMatcher.apply("foobar"), is(false));
assertThat(indicesMatcher.apply("fool"), is(false));
assertThat(indicesMatcher.apply("fool2bar"), is(true));
assertThat(indicesMatcher.apply("baz_foo"), is(true));
assertThat(indicesMatcher.apply("barbapapa"), is(false));
}

View File

@ -7,6 +7,8 @@ package org.elasticsearch.shield.authz;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.get.MultiGetAction;
import org.elasticsearch.action.search.MultiSearchAction;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.suggest.SuggestAction;
import org.elasticsearch.common.base.Predicate;
@ -185,9 +187,23 @@ public class PrivilegeTests extends ElasticsearchTestCase {
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(MultiSearchAction.NAME), is(true));
assertThat(predicate.apply(MultiSearchAction.NAME + "/whatever"), is(true));
assertThat(predicate.apply(SuggestAction.NAME), is(true));
assertThat(predicate.apply(SuggestAction.NAME + "/whatever"), is(true));
assertThat(predicate.apply(GetAction.NAME), is(false));
assertThat(predicate.apply(GetAction.NAME + "/whatever"), is(false));
assertThat(predicate.apply(MultiGetAction.NAME), is(false));
assertThat(predicate.apply(MultiGetAction.NAME + "/whatever"), is(false));
}
@Test
public void testGetPrivilege() throws Exception {
Predicate<String> predicate = Privilege.Index.GET.predicate();
assertThat(predicate.apply(GetAction.NAME), is(true));
assertThat(predicate.apply(GetAction.NAME + "/whatever"), is(true));
assertThat(predicate.apply(MultiGetAction.NAME), is(true));
assertThat(predicate.apply(MultiGetAction.NAME + "/whatever"), is(true));
}
}