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.cluster.metadata.MetaData;
|
||||
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.shield.User;
|
||||
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 Group[] groups;
|
||||
|
||||
|
@ -152,7 +184,6 @@ public interface Permission {
|
|||
this.groups = new Group[0];
|
||||
}
|
||||
|
||||
|
||||
public Indices(AuthorizationService authzService, Collection<Group> groups) {
|
||||
this.groups = groups.toArray(new Group[groups.size()]);
|
||||
this.indicesResolvers = new IndicesResolver[] {
|
||||
|
@ -170,13 +201,7 @@ public interface Permission {
|
|||
* has the given privilege for.
|
||||
*/
|
||||
public Predicate<String> allowedIndicesMatcher(Privilege.Index privilege) {
|
||||
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()));
|
||||
return allowedIndicesMatchersForPrivilege.getUnchecked(privilege);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,13 +209,7 @@ public interface Permission {
|
|||
* has the privilege for executing the given action on.
|
||||
*/
|
||||
public Predicate<String> allowedIndicesMatcher(String action) {
|
||||
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()));
|
||||
return allowedIndicesMatchersForAction.getUnchecked(action);
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
|
|
|
@ -47,6 +47,23 @@ public abstract class Privilege<P extends Privilege<P>> {
|
|||
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 boolean implies(P other);
|
||||
|
|
|
@ -36,11 +36,25 @@ public class PermissionTests extends ElasticsearchTestCase {
|
|||
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
|
||||
public void testAllowedIndicesMatcher_Action() throws Exception {
|
||||
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) {
|
||||
assertThat(indicesMatcher.apply("test_123"), is(true));
|
||||
assertThat(indicesMatcher.apply("foobar"), is(true));
|
||||
|
|
Loading…
Reference in New Issue