Added caching to allowed indices matcher
In order to prevent too many automata constructions (which can be expensive) all the time, the automatas are now cached per action/privilege (since there are limited number of those, we don't expect a cache explosion). Closes elastic/elasticsearch#125 Original commit: elastic/x-pack-elasticsearch@27a4e1fdbe
This commit is contained in:
parent
f2aca1e9bc
commit
5b3ae0c4d9
|
@ -9,6 +9,10 @@ import org.elasticsearch.action.CompositeIndicesRequest;
|
||||||
import org.elasticsearch.action.IndicesRequest;
|
import org.elasticsearch.action.IndicesRequest;
|
||||||
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.cache.Cache;
|
||||||
|
import org.elasticsearch.common.cache.CacheBuilder;
|
||||||
|
import org.elasticsearch.common.cache.CacheLoader;
|
||||||
|
import org.elasticsearch.common.cache.LoadingCache;
|
||||||
import org.elasticsearch.common.collect.ImmutableList;
|
import org.elasticsearch.common.collect.ImmutableList;
|
||||||
import org.elasticsearch.shield.User;
|
import org.elasticsearch.shield.User;
|
||||||
import org.elasticsearch.shield.authz.indicesresolver.DefaultIndicesResolver;
|
import org.elasticsearch.shield.authz.indicesresolver.DefaultIndicesResolver;
|
||||||
|
@ -144,6 +148,34 @@ public interface Permission {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final LoadingCache<String, Predicate<String>> allowedIndicesMatchersForAction = CacheBuilder.newBuilder()
|
||||||
|
.build(new CacheLoader<String, Predicate<String>>() {
|
||||||
|
@Override
|
||||||
|
public Predicate<String> load(String action) throws Exception {
|
||||||
|
ImmutableList.Builder<String> indices = ImmutableList.builder();
|
||||||
|
for (Group group : groups) {
|
||||||
|
if (group.actionMatcher.apply(action)) {
|
||||||
|
indices.add(group.indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new AutomatonPredicate(Automatons.patterns(indices.build()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private final LoadingCache<Privilege.Index, Predicate<String>> allowedIndicesMatchersForPrivilege = CacheBuilder.newBuilder()
|
||||||
|
.build(new CacheLoader<Privilege.Index, Predicate<String>>() {
|
||||||
|
@Override
|
||||||
|
public Predicate<String> load(Privilege.Index privilege) throws Exception {
|
||||||
|
ImmutableList.Builder<String> indices = ImmutableList.builder();
|
||||||
|
for (Group group : groups) {
|
||||||
|
if (group.privilege.implies(privilege)) {
|
||||||
|
indices.add(group.indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new AutomatonPredicate(Automatons.patterns(indices.build()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
private final IndicesResolver[] indicesResolvers;
|
private final IndicesResolver[] indicesResolvers;
|
||||||
private final Group[] groups;
|
private final Group[] groups;
|
||||||
|
|
||||||
|
@ -152,7 +184,6 @@ public interface Permission {
|
||||||
this.groups = new Group[0];
|
this.groups = new Group[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Indices(AuthorizationService authzService, Collection<Group> groups) {
|
public Indices(AuthorizationService authzService, Collection<Group> groups) {
|
||||||
this.groups = groups.toArray(new Group[groups.size()]);
|
this.groups = groups.toArray(new Group[groups.size()]);
|
||||||
this.indicesResolvers = new IndicesResolver[] {
|
this.indicesResolvers = new IndicesResolver[] {
|
||||||
|
@ -170,13 +201,7 @@ public interface Permission {
|
||||||
* has the given privilege for.
|
* has the given privilege for.
|
||||||
*/
|
*/
|
||||||
public Predicate<String> allowedIndicesMatcher(Privilege.Index privilege) {
|
public Predicate<String> allowedIndicesMatcher(Privilege.Index privilege) {
|
||||||
ImmutableList.Builder<String> indices = ImmutableList.builder();
|
return allowedIndicesMatchersForPrivilege.getUnchecked(privilege);
|
||||||
for (Group group : groups) {
|
|
||||||
if (group.privilege.implies(privilege)) {
|
|
||||||
indices.add(group.indices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new AutomatonPredicate(Automatons.patterns(indices.build()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,13 +209,7 @@ public interface Permission {
|
||||||
* has the privilege for executing the given action on.
|
* has the privilege for executing the given action on.
|
||||||
*/
|
*/
|
||||||
public Predicate<String> allowedIndicesMatcher(String action) {
|
public Predicate<String> allowedIndicesMatcher(String action) {
|
||||||
ImmutableList.Builder<String> indices = ImmutableList.builder();
|
return allowedIndicesMatchersForAction.getUnchecked(action);
|
||||||
for (Group group : groups) {
|
|
||||||
if (group.actionMatcher.apply(action)) {
|
|
||||||
indices.add(group.indices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new AutomatonPredicate(Automatons.patterns(indices.build()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @SuppressWarnings("unchecked")
|
@Override @SuppressWarnings("unchecked")
|
||||||
|
|
|
@ -47,6 +47,23 @@ public abstract class Privilege<P extends Privilege<P>> {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Privilege privilege = (Privilege) o;
|
||||||
|
|
||||||
|
if (name != null ? !name.equals(privilege.name) : privilege.name != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name != null ? name.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Predicate<String> predicate();
|
public abstract Predicate<String> predicate();
|
||||||
|
|
||||||
public abstract boolean implies(P other);
|
public abstract boolean implies(P other);
|
||||||
|
|
|
@ -36,11 +36,25 @@ public class PermissionTests extends ElasticsearchTestCase {
|
||||||
testAllowedIndicesMatcher(permission.indices().allowedIndicesMatcher(GET));
|
testAllowedIndicesMatcher(permission.indices().allowedIndicesMatcher(GET));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllowedIndicesMatcher_Privilege_Caching() throws Exception {
|
||||||
|
Predicate<String> matcher1 = permission.indices().allowedIndicesMatcher(GET.plus(SEARCH).plus(WRITE));
|
||||||
|
Predicate<String> matcher2 = permission.indices().allowedIndicesMatcher(GET.plus(SEARCH).plus(WRITE));
|
||||||
|
assertThat(matcher1, is(matcher2));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAllowedIndicesMatcher_Action() throws Exception {
|
public void testAllowedIndicesMatcher_Action() throws Exception {
|
||||||
testAllowedIndicesMatcher(permission.indices().allowedIndicesMatcher(GetAction.NAME));
|
testAllowedIndicesMatcher(permission.indices().allowedIndicesMatcher(GetAction.NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllowedIndicesMatcher_Action_Caching() throws Exception {
|
||||||
|
Predicate<String> matcher1 = permission.indices().allowedIndicesMatcher(GetAction.NAME);
|
||||||
|
Predicate<String> matcher2 = permission.indices().allowedIndicesMatcher(GetAction.NAME);
|
||||||
|
assertThat(matcher1, is(matcher2));
|
||||||
|
}
|
||||||
|
|
||||||
private void testAllowedIndicesMatcher(Predicate<String> indicesMatcher) {
|
private void testAllowedIndicesMatcher(Predicate<String> indicesMatcher) {
|
||||||
assertThat(indicesMatcher.apply("test_123"), is(true));
|
assertThat(indicesMatcher.apply("test_123"), is(true));
|
||||||
assertThat(indicesMatcher.apply("foobar"), is(true));
|
assertThat(indicesMatcher.apply("foobar"), is(true));
|
||||||
|
|
Loading…
Reference in New Issue