shield: add support for new privilege naming

This commit adds support for the privilege naming defined in elastic/elasticsearch#1342 and removes the
support for the privileges that were deprecated in 2.3. This change also includes
updates to the documentation to account for the new roles format.

Original commit: elastic/x-pack-elasticsearch@98e9afd409
This commit is contained in:
jaymode 2016-03-08 14:20:54 -05:00
parent cbc37bcabf
commit a22539aca0
18 changed files with 167 additions and 444 deletions

View File

@ -53,7 +53,8 @@ public class ShieldCachePermissionIT extends ShieldIntegTestCase {
return super.configRoles()
+ "\nread_one_idx:\n"
+ " indices:\n"
+ " 'data': READ\n";
+ " 'data':\n"
+ " - read\n";
}
@Override

View File

@ -13,13 +13,13 @@ minimal:
indices:
- names: source
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh
- names: dest
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh
@ -28,7 +28,7 @@ minimal:
readonly:
indices:
- names: '*'
privileges: [ search ]
privileges: [ read ]
# Write operations on destination index, none on source index
dest_only:
@ -41,7 +41,7 @@ can_not_see_hidden_docs:
indices:
- names: source
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh
@ -52,7 +52,7 @@ can_not_see_hidden_docs:
hidden: true
- names: dest
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh
@ -62,7 +62,7 @@ can_not_see_hidden_fields:
indices:
- names: source
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh
@ -71,7 +71,7 @@ can_not_see_hidden_fields:
- bar
- names: dest
privileges:
- search
- read
- write
- create_index
- indices:admin/refresh

View File

@ -26,101 +26,51 @@ user:
# Defines the required permissions for transport clients
transport_client:
cluster:
- cluster:monitor/nodes/liveness
#uncomment the following for sniffing
#- cluster:monitor/state
# The required permissions for kibana 4 users.
kibana4:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
indices:
- names: '*'
privileges:
- indices:admin/mappings/fields/get
- indices:admin/validate/query
- indices:data/read/search
- indices:data/read/msearch
- indices:data/read/field_stats
- indices:admin/get
- names: '.kibana'
privileges:
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
- transport_client
# The required permissions for the kibana 4 server
kibana4_server:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
- monitor
indices:
- names: '.kibana'
privileges:
- indices:admin/create
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
- all
# The required role for logstash users
logstash:
cluster:
- indices:admin/template/get
- indices:admin/template/put
- manage_index_templates
indices:
- names: 'logstash-*'
privileges:
- indices:data/write/bulk
- indices:data/write/delete
- indices:data/write/update
- indices:data/read/search
- indices:data/read/scroll
- write
- read
- create_index
# Monitoring user role. Assign to monitoring users.
# Marvel user role. Assign to marvel users.
monitoring_user:
indices:
- names: '.monitoring-*'
privileges:
- read
- names:
- '.marvel-es-*'
- '.monitoring-*'
privileges: [ "read" ]
- names: '.kibana'
privileges:
- indices:admin/exists
- indices:admin/mappings/fields/get
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- view_index_metadata
- read
# Monitoring remote agent role. Assign to the agent user on the remote monitoring cluster
# to which the monitoring agent will export all its data
# Marvel remote agent role. Assign to the agent user on the remote marvel cluster
# to which the marvel agent will export all its data
remote_monitoring_agent:
cluster:
- indices:admin/template/put
- indices:admin/template/get
cluster: [ "manage_index_templates" ]
indices:
- names: '.monitoring-*'
privileges:
- all
- names:
- '.marvel-es-*'
- '.monitoring-*'
privileges: [ "all" ]
# Allows all operations required to manage ingest pipelines
ingest_admin:
cluster:
- manage_pipeline
- manage_pipeline

View File

@ -6,8 +6,10 @@
package org.elasticsearch.shield.authz.privilege;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.BasicAutomata;
import org.elasticsearch.common.Strings;
import org.elasticsearch.shield.action.realm.ClearRealmCacheAction;
import org.elasticsearch.shield.action.role.ClearRolesCacheAction;
import org.elasticsearch.shield.support.Automatons;
import java.util.Locale;
import java.util.Set;
@ -15,16 +17,35 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Predicate;
import static org.elasticsearch.shield.support.Automatons.minusAndDeterminize;
import static org.elasticsearch.shield.support.Automatons.patterns;
/**
*
*/
public class ClusterPrivilege extends AbstractAutomatonPrivilege<ClusterPrivilege> {
public static final ClusterPrivilege NONE = new ClusterPrivilege(Name.NONE, BasicAutomata.makeEmpty());
public static final ClusterPrivilege ALL = new ClusterPrivilege(Name.ALL, "cluster:*", "indices:admin/template/*");
public static final ClusterPrivilege MONITOR = new ClusterPrivilege("monitor", "cluster:monitor/*");
public static final ClusterPrivilege MANAGE_SHIELD = new ClusterPrivilege("manage_shield", "cluster:admin/shield/*");
public static final ClusterPrivilege MANAGE_PIPELINE = new ClusterPrivilege("manage_pipeline", "cluster:admin/ingest/pipeline/*");
// shared automatons
private static final Automaton MANAGE_USER_AUTOMATON = patterns("cluster:admin/shield/user/*", ClearRolesCacheAction.NAME);
private static final Automaton MANAGE_ROLE_AUTOMATON = patterns("cluster:admin/shield/role/*", ClearRealmCacheAction.NAME);
private static final Automaton MANAGE_SECURITY_AUTOMATON = patterns("cluster:admin/shield/*");
private static final Automaton MONITOR_AUTOMATON = patterns("cluster:monitor/*");
private static final Automaton ALL_CLUSTER_AUTOMATON = patterns("cluster:*", "indices:admin/template/*");
private static final Automaton MANAGE_AUTOMATON = minusAndDeterminize(ALL_CLUSTER_AUTOMATON, MANAGE_SECURITY_AUTOMATON);
private static final Automaton TRANSPORT_CLIENT_AUTOMATON = patterns("cluster:monitor/nodes/liveness", "cluster:monitor/state");
private static final Automaton MANAGE_IDX_TEMPLATE_AUTOMATON = patterns("indices:admin/template/*");
public static final ClusterPrivilege NONE = new ClusterPrivilege(Name.NONE, Automatons.EMPTY);
public static final ClusterPrivilege ALL = new ClusterPrivilege(Name.ALL, ALL_CLUSTER_AUTOMATON);
public static final ClusterPrivilege MONITOR = new ClusterPrivilege("monitor", MONITOR_AUTOMATON);
public static final ClusterPrivilege MANAGE = new ClusterPrivilege("manage", MANAGE_AUTOMATON);
public static final ClusterPrivilege MANAGE_IDX_TEMPLATES =
new ClusterPrivilege("manage_index_templates", MANAGE_IDX_TEMPLATE_AUTOMATON);
public static final ClusterPrivilege TRANSPORT_CLIENT = new ClusterPrivilege("transport_client", TRANSPORT_CLIENT_AUTOMATON);
public static final ClusterPrivilege MANAGE_USERS = new ClusterPrivilege("manage_users", MANAGE_USER_AUTOMATON);
public static final ClusterPrivilege MANAGE_ROLES = new ClusterPrivilege("manage_roles", MANAGE_ROLE_AUTOMATON);
public static final ClusterPrivilege MANAGE_SECURITY = new ClusterPrivilege("manage_security", MANAGE_SECURITY_AUTOMATON);
public static final ClusterPrivilege MANAGE_PIPELINE = new ClusterPrivilege("manage_pipeline", "cluster:admin/ingest/pipeline/*");
public final static Predicate<String> ACTION_MATCHER = ClusterPrivilege.ALL.predicate();
@ -34,7 +55,12 @@ public class ClusterPrivilege extends AbstractAutomatonPrivilege<ClusterPrivileg
values.add(NONE);
values.add(ALL);
values.add(MONITOR);
values.add(MANAGE_SHIELD);
values.add(MANAGE);
values.add(MANAGE_IDX_TEMPLATES);
values.add(TRANSPORT_CLIENT);
values.add(MANAGE_USERS);
values.add(MANAGE_ROLES);
values.add(MANAGE_SECURITY);
values.add(MANAGE_PIPELINE);
}
@ -48,8 +74,8 @@ public class ClusterPrivilege extends AbstractAutomatonPrivilege<ClusterPrivileg
super(name, patterns);
}
private ClusterPrivilege(Name name, String... patterns) {
super(name, patterns);
private ClusterPrivilege(String name, Automaton automaton) {
super(new Name(name), automaton);
}
private ClusterPrivilege(Name name, Automaton automaton) {

View File

@ -6,14 +6,21 @@
package org.elasticsearch.shield.authz.privilege;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.BasicAutomata;
import org.elasticsearch.action.admin.cluster.shards.ClusterSearchShardsAction;
import org.elasticsearch.action.admin.indices.alias.exists.AliasesExistAction;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
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.action.admin.indices.delete.DeleteIndexAction;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsAction;
import org.elasticsearch.action.admin.indices.exists.types.TypesExistsAction;
import org.elasticsearch.action.admin.indices.get.GetIndexAction;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsAction;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsAction;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsAction;
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryAction;
import org.elasticsearch.common.Strings;
import org.elasticsearch.shield.support.Automatons;
import java.util.Locale;
import java.util.Set;
@ -21,29 +28,41 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Predicate;
import static org.elasticsearch.shield.support.Automatons.patterns;
import static org.elasticsearch.shield.support.Automatons.unionAndDeterminize;
/**
*
*/
public class IndexPrivilege extends AbstractAutomatonPrivilege<IndexPrivilege> {
public static final IndexPrivilege NONE = new IndexPrivilege(Name.NONE, BasicAutomata.makeEmpty());
public static final IndexPrivilege ALL = new IndexPrivilege(Name.ALL, "indices:*");
public static final IndexPrivilege MANAGE = new IndexPrivilege("manage", "indices:monitor/*", "indices:admin/*");
public static final IndexPrivilege CREATE_INDEX = new IndexPrivilege("create_index", CreateIndexAction.NAME);
public static final IndexPrivilege MANAGE_ALIASES = new IndexPrivilege("manage_aliases", "indices:admin/aliases*");
public static final IndexPrivilege MONITOR = new IndexPrivilege("monitor", "indices:monitor/*");
public static final IndexPrivilege DATA_ACCESS = new IndexPrivilege("data_access", "indices:data/*", "indices:admin/mapping/put");
public static final IndexPrivilege CRUD =
new IndexPrivilege("crud", "indices:data/write/*", "indices:data/read/*", "indices:admin/mapping/put");
public static final IndexPrivilege READ = new IndexPrivilege("read", "indices:data/read/*");
public static final IndexPrivilege SEARCH =
new IndexPrivilege("search", SearchAction.NAME + "*", MultiSearchAction.NAME + "*", SuggestAction.NAME + "*");
public static final IndexPrivilege GET = new IndexPrivilege("get", GetAction.NAME + "*", MultiGetAction.NAME + "*");
public static final IndexPrivilege SUGGEST = new IndexPrivilege("suggest", SuggestAction.NAME + "*");
public static final IndexPrivilege INDEX =
new IndexPrivilege("index", "indices:data/write/index*", "indices:data/write/update*", "indices:admin/mapping/put");
public static final IndexPrivilege DELETE = new IndexPrivilege("delete", "indices:data/write/delete*");
public static final IndexPrivilege WRITE = new IndexPrivilege("write", "indices:data/write/*", "indices:admin/mapping/put");
private static final Automaton ALL_AUTOMATON = patterns("indices:*");
private static final Automaton READ_AUTOMATON = patterns("indices:data/read/*");
private static final Automaton CREATE_AUTOMATON = patterns("indices:data/write/index*", PutMappingAction.NAME);
private static final Automaton INDEX_AUTOMATON =
patterns("indices:data/write/index*", "indices:data/write/update*", PutMappingAction.NAME);
private static final Automaton DELETE_AUTOMATON = patterns("indices:data/write/delete*");
private static final Automaton WRITE_AUTOMATON = patterns("indices:data/write/*", PutMappingAction.NAME);
private static final Automaton MONITOR_AUTOMATON = patterns("indices:monitor/*");
private static final Automaton MANAGE_AUTOMATON = unionAndDeterminize(MONITOR_AUTOMATON, patterns("indices:admin/*"));
private static final Automaton CREATE_INDEX_AUTOMATON = patterns(CreateIndexAction.NAME);
private static final Automaton DELETE_INDEX_AUTOMATON = patterns(DeleteIndexAction.NAME);
private static final Automaton VIEW_METADATA_AUTOMATON = patterns(GetAliasesAction.NAME, AliasesExistAction.NAME,
GetIndexAction.NAME, IndicesExistsAction.NAME, GetFieldMappingsAction.NAME, GetMappingsAction.NAME,
ClusterSearchShardsAction.NAME, TypesExistsAction.NAME, ValidateQueryAction.NAME, GetSettingsAction.NAME);
public static final IndexPrivilege NONE = new IndexPrivilege(Name.NONE, Automatons.EMPTY);
public static final IndexPrivilege ALL = new IndexPrivilege(Name.ALL, ALL_AUTOMATON);
public static final IndexPrivilege READ = new IndexPrivilege("read", READ_AUTOMATON);
public static final IndexPrivilege CREATE = new IndexPrivilege("create", CREATE_AUTOMATON);
public static final IndexPrivilege INDEX = new IndexPrivilege("index", INDEX_AUTOMATON);
public static final IndexPrivilege DELETE = new IndexPrivilege("delete", DELETE_AUTOMATON);
public static final IndexPrivilege WRITE = new IndexPrivilege("write", WRITE_AUTOMATON);
public static final IndexPrivilege MONITOR = new IndexPrivilege("monitor", MONITOR_AUTOMATON);
public static final IndexPrivilege MANAGE = new IndexPrivilege("manage", MANAGE_AUTOMATON);
public static final IndexPrivilege DELETE_INDEX = new IndexPrivilege("delete_index", DELETE_INDEX_AUTOMATON);
public static final IndexPrivilege CREATE_INDEX = new IndexPrivilege("create_index", CREATE_INDEX_AUTOMATON);
public static final IndexPrivilege VIEW_METADATA = new IndexPrivilege("view_index_metadata", VIEW_METADATA_AUTOMATON);
private static final Set<IndexPrivilege> values = new CopyOnWriteArraySet<>();
@ -52,17 +71,14 @@ public class IndexPrivilege extends AbstractAutomatonPrivilege<IndexPrivilege> {
values.add(ALL);
values.add(MANAGE);
values.add(CREATE_INDEX);
values.add(MANAGE_ALIASES);
values.add(MONITOR);
values.add(DATA_ACCESS);
values.add(CRUD);
values.add(READ);
values.add(SEARCH);
values.add(GET);
values.add(SUGGEST);
values.add(INDEX);
values.add(DELETE);
values.add(WRITE);
values.add(CREATE);
values.add(DELETE_INDEX);
values.add(VIEW_METADATA);
}
public static final Predicate<String> ACTION_MATCHER = ALL.predicate();
@ -78,8 +94,8 @@ public class IndexPrivilege extends AbstractAutomatonPrivilege<IndexPrivilege> {
super(name, patterns);
}
private IndexPrivilege(Name name, String... patterns) {
super(name, patterns);
private IndexPrivilege(String name, Automaton automaton) {
super(new Name(name), automaton);
}
private IndexPrivilege(Name name, Automaton automaton) {

View File

@ -24,6 +24,8 @@ import static dk.brics.automaton.MinimizationOperations.minimize;
*/
public final class Automatons {
public static final Automaton EMPTY = BasicAutomata.makeEmpty();
static final char WILDCARD_STRING = '*'; // String equality with support for wildcards
static final char WILDCARD_CHAR = '?'; // Char equality with support for wildcards
static final char WILDCARD_ESCAPE = '\\'; // Escape character

View File

@ -63,7 +63,8 @@ public class DocumentLevelSecurityRandomTests extends ShieldIntegTestCase {
builder.append(" cluster: [ all ]\n");
builder.append(" indices:\n");
builder.append(" - names: '*'\n");
builder.append(" privileges: [ ALL ]\n");
builder.append(" privileges:\n");
builder.append(" - all\n");
builder.append(" query: \n");
builder.append(" term: \n");
builder.append(" field1: value").append(i).append('\n');

View File

@ -73,10 +73,12 @@ public class DocumentLevelSecurityTests extends ShieldIntegTestCase {
protected String configRoles() {
return super.configRoles() +
"\nrole1:\n" +
" cluster: [ all ]\n" +
" cluster:\n" +
" - all\n" +
" indices:\n" +
" - names: '*'\n" +
" privileges: [ ALL ]\n" +
" privileges:\n" +
" - all\n" +
" query: \n" +
" term: \n" +
" field1: value1\n" +

View File

@ -86,10 +86,12 @@ public class FieldLevelSecurityRandomTests extends ShieldIntegTestCase {
" privileges: [ ALL ]\n" +
" fields:\n" +roleFields.toString() +
"role2:\n" +
" cluster: [ all ]\n" +
" cluster:\n" +
" - all\n" +
" indices:\n" +
" - names: test\n" +
" privileges: [ ALL ]\n" +
" privileges:\n" +
" - all\n" +
" fields:\n" +
" - field1\n" +
"role3:\n" +

View File

@ -1,199 +0,0 @@
/*
* 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.ElasticsearchSecurityException;
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;
import org.elasticsearch.shield.authc.support.Hasher;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.authc.support.SecuredStringTests;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.test.ShieldIntegTestCase;
import java.util.Map;
import static java.util.Collections.singletonMap;
import static org.elasticsearch.client.Requests.searchRequest;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.ShieldTestsUtils.assertAuthorizationException;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
public class SearchGetAndSuggestPermissionsTests extends ShieldIntegTestCase {
protected static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString("passwd".toCharArray())));
@Override
protected String configRoles() {
return super.configRoles() + "\n" +
"\n" +
"search_role:\n" +
" indices:\n" +
" - names: 'a'\n" +
" privileges: [ search ]\n" +
"\n" +
"get_role:\n" +
" indices:\n" +
" - names: 'a'\n" +
" privileges: [ get ]\n" +
"\n" +
"suggest_role:\n" +
" indices:\n" +
" - names: 'a'\n" +
" privileges: [ suggest ]\n";
}
@Override
protected String configUsers() {
return super.configUsers() +
"search_user:" + USERS_PASSWD_HASHED + "\n" +
"get_user:" + USERS_PASSWD_HASHED + "\n" +
"suggest_user:" + USERS_PASSWD_HASHED + "\n";
}
@Override
protected String configUsersRoles() {
return super.configUsersRoles() +
"search_role:search_user\n" +
"get_role:get_user\n" +
"suggest_role:suggest_user\n";
}
/**
* testing both "search" and "suggest" privileges can execute the suggest API
*/
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();
Map<String, String> headers = singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd"));
SuggestResponse suggestResponse = client.filterWithHeader(headers)
.prepareSuggest("a")
.addSuggestion(randomAsciiOfLengthBetween(3,7), SuggestBuilders.termSuggestion("name").text("val")).get();
assertNoFailures(suggestResponse);
assertThat(suggestResponse.getSuggest().size(), is(1));
suggestResponse = client
.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
.prepareSuggest("a")
.addSuggestion(randomAsciiOfLengthBetween(3, 7), SuggestBuilders.termSuggestion("name").text("val")).get();
assertNoFailures(suggestResponse);
assertThat(suggestResponse.getSuggest().size(), is(1));
try {
client.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("suggest_user", "passwd")))
.prepareSearch("a")
.get();
fail("a user with only a suggest privilege cannot execute search");
} catch (ElasticsearchSecurityException e) {
logger.error("failed to search", e);
// expected
}
}
/**
* testing that "search" privilege cannot execute the get API
*/
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();
try {
client.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
.prepareGet("a", "type", indexResponse.getId())
.get();
fail("a user with only search privilege should not be authorized for a get request");
} catch (ElasticsearchSecurityException e) {
// expected
assertAuthorizationException(e);
logger.error("could not get document", e);
}
}
/**
* testing that "get" privilege can execute the mget API, and "search" privilege cannot execute mget
*/
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
.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("get_user", "passwd")))
.prepareMultiGet().add("a", "type", indexResponse.getId())
.get();
assertNotNull(response);
assertThat(response.getResponses().length, is(1));
assertThat(response.getResponses()[0].getId(), equalTo(indexResponse.getId()));
try {
client.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
.prepareMultiGet().add("a", "type", indexResponse.getId())
.get();
fail("a user with only a search privilege should not be able to execute the mget API");
} catch (ElasticsearchSecurityException e) {
// expected
assertAuthorizationException(e);
logger.error("could not mget documents", e);
}
}
/**
* testing that "search" privilege can execute the msearch API
*/
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
.filterWithHeader(singletonMap(UsernamePasswordToken.BASIC_AUTH_HEADER, userHeader("search_user", "passwd")))
.prepareMultiSearch().add(searchRequest("a").types("type"))
.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

@ -60,30 +60,30 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
" indices:\n" +
" - names: '*'\n" +
" privileges: [ create_index ]\n" +
//role that has create index and managa aliases on test_*, not enough to manage aliases outside of test_* namespace
//role that has create index and manage_aliases on test_*, not enough to manage_aliases aliases outside of test_* namespace
"create_test_aliases_test:\n" +
" indices:\n" +
" - names: 'test_*'\n" +
" privileges: [ 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
" privileges: [ create_index, 'indices:admin/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" +
" - names: 'test_*'\n" +
" privileges: [ create_index ]\n" +
" - names: 'alias_*'\n" +
" privileges: [ manage_aliases ]\n" +
" privileges: [ 'indices:admin/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" +
" - names: 'test_*'\n" +
" privileges: [ create_index ]\n" +
" - names: [ 'alias_*', 'test_*' ]\n" +
" privileges: [ manage_aliases ]\n" +
" privileges: [ 'indices:admin/aliases*' ]\n" +
//role that has manage_aliases only on both test_* and alias_*
"aliases_only:\n" +
" indices:\n" +
" - names: [ 'alias_*', 'test_*']\n" +
" privileges: [ manage_aliases ]\n";
" privileges: [ 'indices:admin/aliases*' ]\n";
}
@Before
@ -368,7 +368,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
assertAcked(client.admin().indices().prepareCreate("test_1"));
try {
//fails: user doesn't have manage aliases on test_1
//fails: user doesn't have manage_aliases aliases on test_1
client.admin().indices().prepareAliases().addAlias("test_1", "test_alias").get();
fail("add alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
} catch(ElasticsearchSecurityException e) {
@ -377,7 +377,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
}
try {
//fails: user doesn't have manage aliases on test_1
//fails: user doesn't have manage_aliases aliases on test_1
client.admin().indices().prepareAliases().addAlias("test_1", "alias_1").get();
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
} catch(ElasticsearchSecurityException e) {
@ -386,7 +386,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
}
try {
//fails: user doesn't have manage aliases on test_*, no matching indices to replace wildcards
//fails: user doesn't have manage_aliases aliases on test_*, no matching indices to replace wildcards
client.admin().indices().prepareAliases().addAlias("test_*", "alias_1").get();
fail("add alias should have failed due to missing manage_aliases privileges on test_1");
} catch(IndexNotFoundException e) {
@ -465,7 +465,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
assertAcked(client.admin().indices().prepareCreate("test_1"));
try {
//fails: user doesn't have manage aliases on test_1, nor test_alias
//fails: user doesn't have manage_aliases aliases on test_1, nor test_alias
client.admin().indices().prepareGetAliases().setAliases("test_alias").setIndices("test_1").get();
fail("get alias should have failed due to missing manage_aliases privileges on test_alias and test_1");
} catch(ElasticsearchSecurityException e) {
@ -474,7 +474,7 @@ public class IndexAliasesTests extends ShieldIntegTestCase {
}
try {
//fails: user doesn't have manage aliases on test_*, no matching indices to replace wildcards
//fails: user doesn't have manage_aliases aliases on test_*, no matching indices to replace wildcards
client.admin().indices().prepareGetAliases().setIndices("test_*").setAliases("test_alias").get();
fail("get alias should have failed due to missing manage_aliases privileges on test_*");
} catch(IndexNotFoundException e) {

View File

@ -302,7 +302,7 @@ public class InternalAuthorizationServiceTests extends ESTestCase {
User user = new User("test user", "a_star", "b");
ClusterState state = mock(ClusterState.class);
when(rolesStore.role("a_star")).thenReturn(Role.builder("a_star").add(IndexPrivilege.ALL, "a*").build());
when(rolesStore.role("b")).thenReturn(Role.builder("a_star").add(IndexPrivilege.SEARCH, "b").build());
when(rolesStore.role("b")).thenReturn(Role.builder("a_star").add(IndexPrivilege.READ, "b").build());
when(clusterService.state()).thenReturn(state);
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
when(state.metaData()).thenReturn(MetaData.builder()

View File

@ -18,7 +18,6 @@ import java.util.function.Predicate;
import static org.elasticsearch.shield.authz.privilege.IndexPrivilege.MONITOR;
import static org.elasticsearch.shield.authz.privilege.IndexPrivilege.READ;
import static org.elasticsearch.shield.authz.privilege.IndexPrivilege.SEARCH;
import static org.elasticsearch.shield.authz.privilege.IndexPrivilege.union;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@ -33,7 +32,7 @@ public class PermissionTests extends ESTestCase {
@Before
public void init() {
Role.Builder builder = Role.builder("test");
builder.add(union(SEARCH, MONITOR), "test_*", "/foo.*/");
builder.add(union(MONITOR), "test_*", "/foo.*/");
builder.add(union(READ), "baz_*foo", "/fool.*bar/");
builder.add(union(MONITOR), "/bar.*/");
permission = builder.build();

View File

@ -5,15 +5,10 @@
*/
package org.elasticsearch.shield.authz.privilege;
import org.elasticsearch.action.get.GetAction;
import org.elasticsearch.action.get.MultiGetAction;
import org.elasticsearch.action.ingest.DeletePipelineAction;
import org.elasticsearch.action.ingest.GetPipelineAction;
import org.elasticsearch.action.ingest.PutPipelineAction;
import org.elasticsearch.action.ingest.SimulatePipelineAction;
import org.elasticsearch.action.search.MultiSearchAction;
import org.elasticsearch.action.search.SearchAction;
import org.elasticsearch.action.suggest.SuggestAction;
import org.elasticsearch.shield.support.AutomatonPredicate;
import org.elasticsearch.shield.support.Automatons;
import org.elasticsearch.test.ESTestCase;
@ -262,27 +257,4 @@ public class PrivilegeTests extends ESTestCase {
assertThat(predicate.test("indices:admin/mapping/put"), is(false));
assertThat(predicate.test("indices:admin/mapping/whatever"), is(false));
}
public void testSearchPrivilege() throws Exception {
Predicate<String> predicate = IndexPrivilege.SEARCH.predicate();
assertThat(predicate.test(SearchAction.NAME), is(true));
assertThat(predicate.test(SearchAction.NAME + "/whatever"), is(true));
assertThat(predicate.test(MultiSearchAction.NAME), is(true));
assertThat(predicate.test(MultiSearchAction.NAME + "/whatever"), is(true));
assertThat(predicate.test(SuggestAction.NAME), is(true));
assertThat(predicate.test(SuggestAction.NAME + "/whatever"), is(true));
assertThat(predicate.test(GetAction.NAME), is(false));
assertThat(predicate.test(GetAction.NAME + "/whatever"), is(false));
assertThat(predicate.test(MultiGetAction.NAME), is(false));
assertThat(predicate.test(MultiGetAction.NAME + "/whatever"), is(false));
}
public void testGetPrivilege() throws Exception {
Predicate<String> predicate = IndexPrivilege.GET.predicate();
assertThat(predicate.test(GetAction.NAME), is(true));
assertThat(predicate.test(GetAction.NAME + "/whatever"), is(true));
assertThat(predicate.test(MultiGetAction.NAME), is(true));
assertThat(predicate.test(MultiGetAction.NAME + "/whatever"), is(true));
}
}

View File

@ -82,7 +82,8 @@ public class FileRolesStoreTests extends ESTestCase {
assertThat(group.indices().length, is(1));
assertThat(group.indices()[0], equalTo("idx3"));
assertThat(group.privilege(), notNullValue());
assertThat(group.privilege(), is(IndexPrivilege.CRUD));
assertThat(group.privilege().implies(IndexPrivilege.READ), is(true));
assertThat(group.privilege().implies(IndexPrivilege.WRITE),is(true));
role = roles.get("role1.ab");
assertThat(role, notNullValue());
@ -228,21 +229,21 @@ public class FileRolesStoreTests extends ESTestCase {
* This test is mainly to make sure we can read the default roles.yml config
*/
public void testDefaultRolesFile() throws Exception {
// TODO we should add the config dir to the resources so we don't copy this stuff around...
Path path = getDataPath("default_roles.yml");
Map<String, Role> roles = FileRolesStore.parseFile(path, logger, Settings.EMPTY);
assertThat(roles, notNullValue());
assertThat(roles.size(), is(10));
assertThat(roles.size(), is(9));
assertThat(roles, hasKey("admin"));
assertThat(roles, hasKey("power_user"));
assertThat(roles, hasKey("user"));
assertThat(roles, hasKey("kibana4"));
assertThat(roles, hasKey("transport_client"));
assertThat(roles, hasKey("kibana4_server"));
assertThat(roles, hasKey("logstash"));
assertThat(roles, hasKey("monitoring_user"));
assertThat(roles, hasKey("remote_monitoring_agent"));
assertThat(roles, hasKey("ingest_admin"));
assertThat(roles, hasKey("transport_client"));
}
public void testAutoReload() throws Exception {

View File

@ -71,8 +71,7 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ
" privileges: [ ALL ]\n" +
DEFAULT_TRANSPORT_CLIENT_ROLE + ":\n" +
" cluster:\n" +
" - cluster:monitor/nodes/info\n" +
" - cluster:monitor/state";
" - transport_client";
private final Path parentFolder;
private final String subfolderPrefix;

View File

@ -26,101 +26,51 @@ user:
# Defines the required permissions for transport clients
transport_client:
cluster:
- cluster:monitor/nodes/liveness
#uncomment the following for sniffing
#- cluster:monitor/state
# The required permissions for kibana 4 users.
kibana4:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
indices:
- names: '*'
privileges:
- indices:admin/mappings/fields/get
- indices:admin/validate/query
- indices:data/read/search
- indices:data/read/msearch
- indices:data/read/field_stats
- indices:admin/get
- names: '.kibana'
privileges:
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
- transport_client
# The required permissions for the kibana 4 server
kibana4_server:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
- monitor
indices:
- names: '.kibana'
privileges:
- indices:admin/create
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
- all
# The required role for logstash users
logstash:
cluster:
- indices:admin/template/get
- indices:admin/template/put
- manage_index_templates
indices:
- names: 'logstash-*'
privileges:
- indices:data/write/bulk
- indices:data/write/delete
- indices:data/write/update
- indices:data/read/search
- indices:data/read/scroll
- write
- read
- create_index
# Monitoring user role. Assign to monitoring users.
# Marvel user role. Assign to marvel users.
monitoring_user:
indices:
- names: '.monitoring-*'
privileges:
- read
- names:
- '.marvel-es-*'
- '.monitoring-*'
privileges: [ "read" ]
- names: '.kibana'
privileges:
- indices:admin/exists
- indices:admin/mappings/fields/get
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- view_index_metadata
- read
# Monitoring remote agent role. Assign to the agent user on the remote monitoring cluster
# to which the monitoring agent will export all its data
# Marvel remote agent role. Assign to the agent user on the remote marvel cluster
# to which the marvel agent will export all its data
remote_monitoring_agent:
cluster:
- indices:admin/template/put
- indices:admin/template/get
cluster: [ "manage_index_templates" ]
indices:
- names: '.monitoring-*'
privileges:
- all
- names:
- '.marvel-es-*'
- '.monitoring-*'
privileges: [ "all" ]
# Allows all operations required to manage ingest pipelines
ingest_admin:
cluster:
- manage_pipeline
- manage_pipeline

View File

@ -9,7 +9,8 @@ role1:
- READ
- names: idx3
privileges:
- CRUD
- READ
- WRITE
role1.ab:
cluster: