Fixed a bug in Cluster privileges where resolve failed for template APIs

We now moved from the logic of checking `indices:` and `cluster:` prefixes to determine whether an action is an indices or a cluster action... instead we use the index/cluster privielge `all` privilege to determine that (which is more accurate in the context of shield, as it enables us to move actions between the two categories while keeping their logical name intact)

Also updated the docs to reflect that template related actions are infact cluster actions.

Original commit: elastic/x-pack-elasticsearch@8027334105
This commit is contained in:
uboness 2014-10-27 18:59:41 +01:00
parent 647e545c79
commit c7e927734c
5 changed files with 85 additions and 12 deletions

View File

@ -46,9 +46,6 @@ public interface Permission {
static class Global implements Permission {
final static Predicate<String> clusterActionMatcher = Privilege.Cluster.ALL.predicate();
final static Predicate<String> indicesActionMatcher = Privilege.Index.ALL.predicate();
private final Cluster cluster;
private final Indices indices;
@ -70,10 +67,10 @@ public interface Permission {
}
public boolean check(User user, String action, TransportRequest request, MetaData metaData) {
if (clusterActionMatcher.apply(action)) {
if (Privilege.Cluster.ACTION_MATCHER.apply(action)) {
return cluster != null && cluster.check(user, action, request, metaData);
}
if (indicesActionMatcher.apply(action)) {
if (Privilege.Index.ACTION_MATCHER.apply(action)) {
return indices != null && indices.check(user, action, request, metaData);
}
return false;

View File

@ -117,6 +117,8 @@ public abstract class Privilege<P extends Privilege<P>> {
NONE, ALL, MANAGE, CREATE_INDEX, MONITOR, DATA_ACCESS, CRUD, READ, SEARCH, GET, INDEX, DELETE, WRITE, BENCHMARK
};
public static final Predicate<String> ACTION_MATCHER = Privilege.Index.ALL.predicate();
static Index[] values() {
return values;
}
@ -180,7 +182,7 @@ public abstract class Privilege<P extends Privilege<P>> {
private static Index resolve(String name) {
name = name.toLowerCase(Locale.ROOT);
if (name.startsWith("indices:")) {
if (ACTION_MATCHER.apply(name)) {
return action(name);
}
for (Index index : values) {
@ -190,7 +192,7 @@ public abstract class Privilege<P extends Privilege<P>> {
}
throw new ElasticsearchIllegalArgumentException("Unknown index privilege [" + name + "]. A privilege must either " +
"on of the predefined fixed indices privileges [" + Strings.arrayToCommaDelimitedString(values) +
"] or a pattern over one of the available index actions (the pattern must begin with \"indices:\" prefix)");
"] or a pattern over one of the available index actions");
}
}
@ -201,6 +203,8 @@ public abstract class Privilege<P extends Privilege<P>> {
public static final Cluster ALL = new Cluster(Name.ALL, "cluster:*", "indices:admin/template/*");
public static final Cluster MONITOR = new Cluster("monitor", "cluster:monitor/*");
final static Predicate<String> ACTION_MATCHER = Privilege.Cluster.ALL.predicate();
private static final Cluster[] values = new Cluster[] { NONE, ALL, MONITOR };
static Cluster[] values() {
@ -233,9 +237,7 @@ public abstract class Privilege<P extends Privilege<P>> {
@Override
protected Cluster create(Name name, Automaton automaton) {
if (name == Name.NONE) {
return NONE;
}
return new Cluster(name, automaton);
}
@ -259,7 +261,7 @@ public abstract class Privilege<P extends Privilege<P>> {
private static Cluster resolve(String name) {
name = name.toLowerCase(Locale.ROOT);
if (name.startsWith("cluster:")) {
if (ACTION_MATCHER.apply(name)) {
return action(name);
}
for (Cluster cluster : values) {
@ -269,7 +271,7 @@ public abstract class Privilege<P extends Privilege<P>> {
}
throw new ElasticsearchIllegalArgumentException("Unknown cluster privilege [" + name + "]. A privilege must either " +
"on of the predefined fixed cluster privileges [" + Strings.arrayToCommaDelimitedString(values) +
"] or a pattern over one of the available cluster actions (the pattern must begin with \"cluster:\" prefix)");
"] or a pattern over one of the available cluster actions");
}
}

View File

@ -72,6 +72,25 @@ public class PrivilegeTests extends ElasticsearchTestCase {
assertThat(cluster, is(cluster2));
}
@Test
public void testCluster_TemplateActions() throws Exception {
Privilege.Name name = new Privilege.Name("indices:admin/template/delete");
Privilege.Cluster cluster = Privilege.Cluster.get(name);
assertThat(cluster, notNullValue());
assertThat(cluster.predicate().apply("indices:admin/template/delete"), is(true));
name = new Privilege.Name("indices:admin/template/get");
cluster = Privilege.Cluster.get(name);
assertThat(cluster, notNullValue());
assertThat(cluster.predicate().apply("indices:admin/template/get"), is(true));
name = new Privilege.Name("indices:admin/template/put");
cluster = Privilege.Cluster.get(name);
assertThat(cluster, notNullValue());
assertThat(cluster.predicate().apply("indices:admin/template/put"), is(true));
}
@Test
public void testCluster_InvalidNaem() throws Exception {
thrown.expect(ElasticsearchIllegalArgumentException.class);

View File

@ -7,6 +7,7 @@ package org.elasticsearch.shield.authz.store;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.base.Charsets;
import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
@ -94,6 +95,24 @@ public class FileRolesStoreTests extends ElasticsearchTestCase {
assertThat(group.privilege().isAlias(Privilege.Index.union(Privilege.Index.READ, Privilege.Index.WRITE)), is(true));
}
/**
* This test is mainly to make sure we can read the default roles.yml config
*/
@Test
public void testDefaultRolesFile() throws Exception {
Path path = Paths.get(getClass().getResource("default_roles.yml").toURI());
Map<String, Permission.Global> roles = FileRolesStore.parseFile(path, logger, mock(AuthorizationService.class));
assertThat(roles, notNullValue());
assertThat(roles.size(), is(6));
assertThat(roles, hasKey("admin"));
assertThat(roles, hasKey("power_user"));
assertThat(roles, hasKey("user"));
assertThat(roles, hasKey("kibana3"));
assertThat(roles, hasKey("kibana4"));
assertThat(roles, hasKey("logstash"));
}
@Test
public void testAutoReload() throws Exception {
ThreadPool threadPool = null;

View File

@ -0,0 +1,36 @@
admin:
cluster: all
indices:
'*': all
# monitoring cluster privileges
# All operations on all indices
power_user:
cluster: monitor
indices:
'*': all
# Only operations on indices
user:
indices:
'*': read
# The required role for kibana 3 users
kibana3:
cluster: cluster:monitor/nodes/info
indices:
'*': indices:data/read/search, indices:data/read/get, indices:admin/get
'kibana-int': indices:data/read/get, indices:data/read/search, indices:data/write/delete, indices:data/write/index, create_index
# The required role for kibana 4 users
kibana4:
cluster: cluster:monitor/nodes/info
indices:
'*': indices:data/read/search, indices:data/read/get, indices:admin/get
'.kibana': indices:data/read/get, indices:data/read/search, indices:data/write/delete, indices:data/write/index, create_index
# The required role for logstash users
logstash:
cluster: indices:admin/template/get, indices:admin/template/put
indices:
'logstash-*': indices:data/write/bulk, indices:data/write/delete, indices:data/write/update, create_index