From f040d895b3808fae8f206134d98156d3752eea65 Mon Sep 17 00:00:00 2001 From: uboness Date: Wed, 20 Aug 2014 08:53:34 -0700 Subject: [PATCH] Added the notion of IndicesResolver A strategy for extracting the related indices from a request. The default strategy relies on the request to either be `IndicesRequest` or `CompositeIndicesRequest`. But depending on the request type, there might be other strategies as well. For example, `GetIndexTemplatesRequest` only holds the template name and therefore requires a different strategy where the template is looked up in the cluster metadata and the indices are resolved from there. This also cleans up the Permission class and makes sure that the indices are resolved once per request (and not once per configured group permission) Original commit: elastic/x-pack-elasticsearch@95192ccdff34f0f650a5799e6a1eacc22cacb1ec --- .../shield/authz/Permission.java | 67 +++++++------------ .../DefaultIndicesResolver.java | 66 ++++++++++++++++++ .../indicesresolver/IndicesResolver.java | 22 ++++++ 3 files changed, 112 insertions(+), 43 deletions(-) create mode 100644 src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolver.java create mode 100644 src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesResolver.java diff --git a/src/main/java/org/elasticsearch/shield/authz/Permission.java b/src/main/java/org/elasticsearch/shield/authz/Permission.java index 4bb540e27a2..b0f1d57f3f8 100644 --- a/src/main/java/org/elasticsearch/shield/authz/Permission.java +++ b/src/main/java/org/elasticsearch/shield/authz/Permission.java @@ -5,16 +5,18 @@ */ package org.elasticsearch.shield.authz; -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.collect.ImmutableList; +import org.elasticsearch.shield.authz.indicesresolver.DefaultIndicesResolver; +import org.elasticsearch.shield.authz.indicesresolver.IndicesResolver; import org.elasticsearch.shield.support.AutomatonPredicate; import org.elasticsearch.shield.support.Automatons; import org.elasticsearch.transport.TransportRequest; import java.util.Collection; +import java.util.Collections; +import java.util.Set; /** * Represents a permission in the system. There are 3 types of permissions: @@ -136,6 +138,11 @@ public interface Permission { } }; + public static IndicesResolver[] indicesResolvers = new IndicesResolver[] { + // add special resolvers here + new DefaultIndicesResolver() + }; + private Group[] groups; public Indices(Collection groups) { @@ -178,21 +185,25 @@ public interface Permission { return new AutomatonPredicate(Automatons.patterns(indices.build())); } - @Override + @Override @SuppressWarnings("unchecked") public boolean check(String action, TransportRequest request, MetaData metaData) { - boolean isIndicesRequest = request instanceof CompositeIndicesRequest || request instanceof IndicesRequest; - if (!isIndicesRequest) { - return false; + Set indices = Collections.emptySet(); + for (IndicesResolver resolver : indicesResolvers) { + if (resolver.requestType().isInstance(request)) { + indices = resolver.resolve(request, metaData); + break; + } } - for (Group group : groups) { - if (group.check(action, request, metaData)) { + + for (int i = 0; i < groups.length; i++) { + if (groups[i].check(action, indices)) { return true; } } return false; } - public static class Group implements Permission { + public static class Group { private final Privilege.Index privilege; private final Predicate actionMatcher; @@ -215,52 +226,22 @@ public interface Permission { return indices; } - @Override - public boolean check(String action, TransportRequest request, MetaData metaData) { - - assert request instanceof IndicesRequest || request instanceof CompositeIndicesRequest : - "the only requests passing the action matcher should be IndicesRequests"; + public boolean check(String action, Set indices) { if (!actionMatcher.apply(action)) { return false; } - if (request instanceof CompositeIndicesRequest) { - CompositeIndicesRequest compositeIndicesRequest = (CompositeIndicesRequest) request; - for (IndicesRequest indicesRequest : compositeIndicesRequest.subRequests()) { - for (String index : explodeWildcards(indicesRequest, metaData)) { - if (!indexNameMatcher.apply(index)) { - return false; - } - } - } - } else { - for (String index : explodeWildcards((IndicesRequest) request, metaData)) { - if (!indexNameMatcher.apply(index)) { - return false; - } + for (String index : indices) { + if (!indexNameMatcher.apply(index)) { + return false; } } return true; } - private String[] explodeWildcards(IndicesRequest indicesRequest, MetaData metaData) { - if (indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed()) { - if (MetaData.isAllIndices(indicesRequest.indices())) { - if (indicesRequest.indicesOptions().expandWildcardsOpen() && indicesRequest.indicesOptions().expandWildcardsClosed()) { - return metaData.concreteAllIndices(); - } - if (indicesRequest.indicesOptions().expandWildcardsOpen()) { - return metaData.concreteAllOpenIndices(); - } - return metaData.concreteAllClosedIndices(); - } - return metaData.convertFromWildcards(indicesRequest.indices(), indicesRequest.indicesOptions()); - } - return indicesRequest.indices(); - } } } diff --git a/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolver.java b/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolver.java new file mode 100644 index 00000000000..af6d1f16acc --- /dev/null +++ b/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolver.java @@ -0,0 +1,66 @@ +/* + * 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.shield.authz.indicesresolver; + +import org.elasticsearch.action.CompositeIndicesRequest; +import org.elasticsearch.action.IndicesRequest; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.collect.Sets; +import org.elasticsearch.transport.TransportRequest; + +import java.util.Collections; +import java.util.Set; + +/** +* +*/ +public class DefaultIndicesResolver implements IndicesResolver { + + @Override + public Class requestType() { + return TransportRequest.class; + } + + @Override + public Set resolve(TransportRequest request, MetaData metaData) { + + boolean isIndicesRequest = request instanceof CompositeIndicesRequest || request instanceof IndicesRequest; + assert isIndicesRequest : "the only requests passing the action matcher should be IndicesRequests"; + + // if for some reason we are missing an action... just for safety we'll reject + if (!isIndicesRequest) { + return Collections.emptySet(); + } + + if (request instanceof CompositeIndicesRequest) { + Set indices = Sets.newHashSet(); + CompositeIndicesRequest compositeIndicesRequest = (CompositeIndicesRequest) request; + for (IndicesRequest indicesRequest : compositeIndicesRequest.subRequests()) { + Collections.addAll(indices, explodeWildcards(indicesRequest, metaData)); + } + return indices; + } + + return Sets.newHashSet(explodeWildcards((IndicesRequest) request, metaData)); + } + + private String[] explodeWildcards(IndicesRequest indicesRequest, MetaData metaData) { + if (indicesRequest.indicesOptions().expandWildcardsOpen() || indicesRequest.indicesOptions().expandWildcardsClosed()) { + if (MetaData.isAllIndices(indicesRequest.indices())) { + if (indicesRequest.indicesOptions().expandWildcardsOpen() && indicesRequest.indicesOptions().expandWildcardsClosed()) { + return metaData.concreteAllIndices(); + } + if (indicesRequest.indicesOptions().expandWildcardsOpen()) { + return metaData.concreteAllOpenIndices(); + } + return metaData.concreteAllClosedIndices(); + + } + return metaData.convertFromWildcards(indicesRequest.indices(), indicesRequest.indicesOptions()); + } + return indicesRequest.indices(); + } +} diff --git a/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesResolver.java b/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesResolver.java new file mode 100644 index 00000000000..e617d0b46aa --- /dev/null +++ b/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesResolver.java @@ -0,0 +1,22 @@ +/* + * 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.shield.authz.indicesresolver; + +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.transport.TransportRequest; + +import java.util.Set; + +/** + * + */ +public interface IndicesResolver { + + Class requestType(); + + Set resolve(Request request, MetaData metaData); + +}