You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ranger.apache.org by Abhay Kulkarni <ak...@hortonworks.com> on 2015/03/14 05:12:34 UTC
Re: incubator-ranger git commit: RANGER-307: Policy evaluation
optimization: reorder policies and short-circuit evaluation
Thanks, Madhan!
On 3/13/15, 7:50 PM, "madhan@apache.org" <ma...@apache.org> wrote:
>Repository: incubator-ranger
>Updated Branches:
> refs/heads/master d4f2eb20f -> 2e0be82df
>
>
>RANGER-307: Policy evaluation optimization: reorder policies and
>short-circuit evaluation
>
>
>Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
>Commit:
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/2e0be82d
>Tree:
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/2e0be82d
>Diff:
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/2e0be82d
>
>Branch: refs/heads/master
>Commit: 2e0be82df973a6f37e766b7e9fff2b41431d0db1
>Parents: d4f2eb2
>Author: Abhay Kulkarni <ak...@hortonworks.com>
>Authored: Fri Mar 13 19:50:19 2015 -0700
>Committer: Madhan Neethiraj <ma...@apache.org>
>Committed: Fri Mar 13 19:50:19 2015 -0700
>
>----------------------------------------------------------------------
> .../ranger/plugin/policyengine/CacheMap.java | 40 +++
> .../plugin/policyengine/RangerAccessData.java | 39 +++
> .../plugin/policyengine/RangerAccessResult.java | 32 ++-
> .../policyengine/RangerPolicyEngineImpl.java | 149 ++---------
> .../RangerPolicyEvaluatorFacade.java | 128 ++++++++++
> .../policyengine/RangerPolicyRepository.java | 231 +++++++++++++++++
> .../RangerDefaultPolicyEvaluator.java | 223 ++++++++++-------
> .../RangerOptimizedPolicyEvaluator.java | 247 +++++++++++++++++++
> .../RangerDefaultPolicyEvaluatorTest.java | 8 +-
> .../policyengine/test_policyengine_hdfs.json | 2 +-
> pom.xml | 2 +-
> src/main/assembly/ranger-src.xml | 83 ++++---
> 12 files changed, 913 insertions(+), 271 deletions(-)
>----------------------------------------------------------------------
>
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheMap.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheM
>ap
>.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheM
>ap
>.java
>new file mode 100644
>index 0000000..0a1566c
>--- /dev/null
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/CacheM
>ap
>.java
>@@ -0,0 +1,40 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one
>+ * or more contributor license agreements. See the NOTICE file
>+ * distributed with this work for additional information
>+ * regarding copyright ownership. The ASF licenses this file
>+ * to you under the Apache License, Version 2.0 (the
>+ * "License"); you may not use this file except in compliance
>+ * with the License. You may obtain a copy of the License at
>+ *
>+ * http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing,
>+ * software distributed under the License is distributed on an
>+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>+ * KIND, either express or implied. See the License for the
>+ * specific language governing permissions and limitations
>+ * under the License.
>+ */
>+package org.apache.ranger.plugin.policyengine;
>+
>+import java.util.LinkedHashMap;
>+import java.util.Map;
>+
>+
>+public class CacheMap<K, V> extends LinkedHashMap<K, V> {
>+ private static final float RANGER_CACHE_DEFAULT_LOAD_FACTOR = 0.75f;
>+
>+ protected int maxCapacity;
>+
>+ public CacheMap(int maxCapacity) {
>+ super(maxCapacity, CacheMap.RANGER_CACHE_DEFAULT_LOAD_FACTOR,
>true); // true for access-order
>+
>+ this.maxCapacity = maxCapacity;
>+ }
>+
>+ @Override
>+ protected boolean removeEldestEntry(Map.Entry eldest) {
>+ return size() > maxCapacity;
>+ }
>+}
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessD
>at
>a.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessData.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessData.java
>new file mode 100644
>index 0000000..34f7428
>--- /dev/null
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessData.java
>@@ -0,0 +1,39 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one
>+ * or more contributor license agreements. See the NOTICE file
>+ * distributed with this work for additional information
>+ * regarding copyright ownership. The ASF licenses this file
>+ * to you under the Apache License, Version 2.0 (the
>+ * "License"); you may not use this file except in compliance
>+ * with the License. You may obtain a copy of the License at
>+ *
>+ * http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing,
>+ * software distributed under the License is distributed on an
>+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>+ * KIND, either express or implied. See the License for the
>+ * specific language governing permissions and limitations
>+ * under the License.
>+ */
>+
>+package org.apache.ranger.plugin.policyengine;
>+
>+
>+public class RangerAccessData<T> {
>+ private String accessFDN = null;
>+ private T accessDetails = null;
>+
>+ public RangerAccessData(String accessFDN) {
>+ this.accessFDN = accessFDN;
>+ }
>+ public String getAccessFDN() {
>+ return accessFDN;
>+ }
>+ public T getAccessDetails() {
>+ return accessDetails;
>+ }
>+ public void setAccessDetails(T accessDetails) {
>+ this.accessDetails = accessDetails;
>+ }
>+}
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessR
>es
>ult.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessResult.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessResult.java
>index 2eaec16..3a1fa1d 100644
>---
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessResult.java
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Ac
>cessResult.java
>@@ -27,23 +27,23 @@ public class RangerAccessResult {
> private RangerServiceDef serviceDef = null;
> private RangerAccessRequest request = null;
>
>+ private boolean isAccessDetermined = false;
> private boolean isAllowed = false;
>+ private boolean isAuditedDetermined = false;
> private boolean isAudited = false;
> private long policyId = -1;
> private String reason = null;
>
> public RangerAccessResult(String serviceName, RangerServiceDef
>serviceDef, RangerAccessRequest request) {
>- this(serviceName, serviceDef, request, false, false, -1, null);
>- }
>-
>- public RangerAccessResult(String serviceName, RangerServiceDef
>serviceDef, RangerAccessRequest request, boolean isAllowed, boolean
>isAudited, long policyId, String reason) {
> this.serviceName = serviceName;
> this.serviceDef = serviceDef;
> this.request = request;
>- this.isAllowed = isAllowed;
>- this.isAudited = isAudited;
>- this.policyId = policyId;
>- this.reason = reason;
>+ this.isAccessDetermined = false;
>+ this.isAllowed = false;
>+ this.isAuditedDetermined = false;
>+ this.isAudited = false;
>+ this.policyId = -1;
>+ this.reason = null;
> }
>
> /**
>@@ -67,6 +67,10 @@ public class RangerAccessResult {
> return request;
> }
>
>+ public boolean getIsAccessDetermined() { return isAccessDetermined; }
>+
>+ private void setIsAccessDetermined(boolean value) { isAccessDetermined =
>value; }
>+
> /**
> * @return the isAllowed
> */
>@@ -78,6 +82,7 @@ public class RangerAccessResult {
> * @param isAllowed the isAllowed to set
> */
> public void setIsAllowed(boolean isAllowed) {
>+ setIsAccessDetermined(true);
> this.isAllowed = isAllowed;
> }
>
>@@ -87,6 +92,10 @@ public class RangerAccessResult {
> public void setReason(String reason) {
> this.reason = reason;
> }
>+
>+ public boolean getIsAuditedDetermined() { return isAuditedDetermined; }
>+
>+ private void setIsAuditedDetermined(boolean value) { isAuditedDetermined
>= value; }
>
> /**
> * @return the isAudited
>@@ -95,10 +104,13 @@ public class RangerAccessResult {
> return isAudited;
> }
>
>+
>+
> /**
> * @param isAudited the isAudited to set
> */
> public void setIsAudited(boolean isAudited) {
>+ setIsAuditedDetermined(true);
> this.isAudited = isAudited;
> }
>
>@@ -145,8 +157,10 @@ public class RangerAccessResult {
> public StringBuilder toString(StringBuilder sb) {
> sb.append("RangerAccessResult={");
>
>+
>sb.append("isAccessDetermined={").append(isAccessDetermined).append("} ");
> sb.append("isAllowed={").append(isAllowed).append("} ");
>- sb.append("isAudited={").append(isAudited).append("} ");
>+
>sb.append("isAuditedDetermined={").append(isAuditedDetermined).append("}
>");
>+ sb.append("isAudited={").append(isAudited).append("} ");
> sb.append("policyId={").append(policyId).append("} ");
> sb.append("reason={").append(reason).append("} ");
>
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyE
>ng
>ineImpl.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEngineImpl.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEngineImpl.java
>index 51787ac..abae1fe 100644
>---
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEngineImpl.java
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEngineImpl.java
>@@ -19,31 +19,25 @@
>
> package org.apache.ranger.plugin.policyengine;
>
>-import java.util.ArrayList;
>-import java.util.Collection;
>-import java.util.List;
>-
>-import org.apache.commons.collections.CollectionUtils;
>-import org.apache.commons.lang.StringUtils;
> import org.apache.commons.logging.Log;
> import org.apache.commons.logging.LogFactory;
> import org.apache.ranger.plugin.audit.RangerAuditHandler;
> import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
> import org.apache.ranger.plugin.model.RangerPolicy;
> import org.apache.ranger.plugin.model.RangerServiceDef;
>-import
>org.apache.ranger.plugin.model.RangerServiceDef.RangerContextEnricherDef;
>-import
>org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluator;
> import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
>
>+import java.util.ArrayList;
>+import java.util.Collection;
>+import java.util.List;
>+
>
> public class RangerPolicyEngineImpl implements RangerPolicyEngine {
> private static final Log LOG =
>LogFactory.getLog(RangerPolicyEngineImpl.class);
>
>- private String serviceName = null;
>- private RangerServiceDef serviceDef = null;
>- private List<RangerContextEnricher> contextEnrichers = null;
>- private List<RangerPolicyEvaluator> policyEvaluators = null;
>- private RangerAuditHandler defaultAuditHandler = null;
>+ private String serviceName = null;
>+ private RangerPolicyRepository policyRepository = null;
>+ private RangerAuditHandler defaultAuditHandler = null;
>
>
> public RangerPolicyEngineImpl() {
>@@ -63,12 +57,13 @@ public class RangerPolicyEngineImpl implements
>RangerPolicyEngine {
>
> @Override
> public RangerServiceDef getServiceDef() {
>- return serviceDef;
>+ return policyRepository == null ? null :
>policyRepository.getServiceDef();
> }
>
> @Override
> public List<RangerContextEnricher> getContextEnrichers() {
>- return contextEnrichers;
>+
>+ return policyRepository == null ? null : getContextEnrichers();
> }
>
> @Override
>@@ -77,51 +72,12 @@ public class RangerPolicyEngineImpl implements
>RangerPolicyEngine {
> LOG.debug("==> RangerPolicyEngineImpl.setPolicies(" + serviceName + ",
>" + serviceDef + ", policies.count=" + (policies == null ? 0 :
>policies.size()) + ")");
> }
>
>- if(serviceName != null && serviceDef != null && policies != null) {
>- List<RangerContextEnricher> contextEnrichers = new
>ArrayList<RangerContextEnricher>();
>-
>- if(!CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) {
>- for(RangerContextEnricherDef enricherDef :
>serviceDef.getContextEnrichers()) {
>- if(enricherDef == null) {
>- continue;
>- }
>-
>- RangerContextEnricher contextEnricher =
>getContextEnricher(enricherDef);
>-
>- contextEnrichers.add(contextEnricher);
>- }
>- }
>-
>- List<RangerPolicyEvaluator> evaluators = new
>ArrayList<RangerPolicyEvaluator>();
>-
>- for(RangerPolicy policy : policies) {
>- if(! policy.getIsEnabled()) {
>- continue;
>- }
>-
>- RangerPolicyEvaluator evaluator = getPolicyEvaluator(policy,
>serviceDef);
>-
>- if(evaluator != null) {
>- evaluators.add(evaluator);
>- }
>- }
>-
>- /* TODO:
>- * sort evaluators list for faster completion of isAccessAllowed()
>method
>- * 1. Global policies: the policies that cover for any resource (for
>example: database=*; table=*; column=*)
>- * 2. Policies that cover all resources under level-1 (for example:
>every thing in one or more databases)
>- * 3. Policies that cover all resources under level-2 (for example:
>every thing in one or more tables)
>- * ...
>- * 4. Policies that cover all resources under level-n (for example:
>one or more columns)
>- *
>- */
>-
>- this.serviceName = serviceName;
>- this.serviceDef = serviceDef;
>- this.contextEnrichers = contextEnrichers;
>- this.policyEvaluators = evaluators;
>+ if (serviceName != null && serviceDef != null && policies != null) {
>+ policyRepository = new RangerPolicyRepository(serviceName);
>+ policyRepository.init(serviceDef, policies);
>+ this.serviceName = serviceName;
> } else {
>- LOG.error("RangerPolicyEngineImpl.setPolicies(): invalid arguments -
>null serviceDef/policies");
>+ LOG.error("RangerPolicyEngineImpl.setPolicies ->Invalid arguments:
>serviceName, serviceDef, or policies is null");
> }
>
> if(LOG.isDebugEnabled()) {
>@@ -141,7 +97,7 @@ public class RangerPolicyEngineImpl implements
>RangerPolicyEngine {
>
> @Override
> public RangerAccessResult createAccessResult(RangerAccessRequest
>request)
>{
>- return new RangerAccessResult(serviceName, serviceDef, request);
>+ return policyRepository == null ? null : new
>RangerAccessResult(serviceName, policyRepository.getServiceDef(),
>request);
> }
>
> @Override
>@@ -207,73 +163,26 @@ public class RangerPolicyEngineImpl implements
>RangerPolicyEngine {
>
> RangerAccessResult ret = createAccessResult(request);
>
>- if(request != null) {
>- List<RangerPolicyEvaluator> evaluators = policyEvaluators;
>+ if(policyRepository != null && ret != null && request != null) {
>+ List<RangerPolicyEvaluatorFacade> evaluators =
>policyRepository.getPolicyEvaluators();
>
> if(evaluators != null) {
>+ policyRepository.retrieveAuditEnabled(request, ret);
> for(RangerPolicyEvaluator evaluator : evaluators) {
> evaluator.evaluate(request, ret);
>
>- // stop once allowed=true && audited==true
>- if(ret.getIsAllowed() && ret.getIsAudited()) {
>+ // stop once allowed==true && auditedDetermined==true
>+ if(ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) {
> break;
> }
> }
>- }
>- }
>+ policyRepository.storeAuditEnabled(request, ret);
>
>- if(LOG.isDebugEnabled()) {
>- LOG.debug("<== RangerPolicyEngineImpl.isAccessAllowedNoAudit(" +
>request + "): " + ret);
>- }
>-
>- return ret;
>- }
>-
>- private RangerContextEnricher
>getContextEnricher(RangerContextEnricherDef
>enricherDef) {
>- if(LOG.isDebugEnabled()) {
>- LOG.debug("==> RangerPolicyEngineImpl.getContextEnricher(" +
>enricherDef + ")");
>- }
>-
>- RangerContextEnricher ret = null;
>-
>- String name = enricherDef != null ? enricherDef.getName() :
>null;
>- String clsName = enricherDef != null ? enricherDef.getEnricher() :
>null;
>-
>- if(! StringUtils.isEmpty(clsName)) {
>- try {
>- @SuppressWarnings("unchecked")
>- Class<RangerContextEnricher> enricherClass =
>(Class<RangerContextEnricher>)Class.forName(clsName);
>-
>- ret = enricherClass.newInstance();
>- } catch(Exception excp) {
>- LOG.error("failed to instantiate context enricher '" + clsName + "'
>for '" + name + "'", excp);
> }
> }
>
>- if(ret != null) {
>- ret.init(enricherDef);
>- }
>-
> if(LOG.isDebugEnabled()) {
>- LOG.debug("<== RangerPolicyEngineImpl.getContextEnricher(" +
>enricherDef + "): " + ret);
>- }
>-
>- return ret;
>- }
>-
>- private RangerPolicyEvaluator getPolicyEvaluator(RangerPolicy policy,
>RangerServiceDef serviceDef) {
>- if(LOG.isDebugEnabled()) {
>- LOG.debug("==> RangerPolicyEngineImpl.getPolicyEvaluator(" + policy +
>"," + serviceDef + ")");
>- }
>-
>- RangerPolicyEvaluator ret = null;
>-
>- ret = new RangerDefaultPolicyEvaluator(); // TODO: configurable
>evaluator class?
>-
>- ret.init(policy, serviceDef);
>-
>- if(LOG.isDebugEnabled()) {
>- LOG.debug("<== RangerPolicyEngineImpl.getPolicyEvaluator(" + policy +
>"," + serviceDef + "): " + ret);
>+ LOG.debug("<== RangerPolicyEngineImpl.isAccessAllowedNoAudit(" +
>request + "): " + ret);
> }
>
> return ret;
>@@ -292,17 +201,7 @@ public class RangerPolicyEngineImpl implements
>RangerPolicyEngine {
> sb.append("RangerPolicyEngineImpl={");
>
> sb.append("serviceName={").append(serviceName).append("} ");
>- sb.append("serviceDef={").append(serviceDef).append("} ");
>-
>- sb.append("policyEvaluators={");
>- if(policyEvaluators != null) {
>- for(RangerPolicyEvaluator policyEvaluator : policyEvaluators) {
>- if(policyEvaluator != null) {
>- sb.append(policyEvaluator).append(" ");
>- }
>- }
>- }
>- sb.append("} ");
>+ sb.append(policyRepository);
>
> sb.append("}");
>
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyE
>va
>luatorFacade.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEvaluatorFacade.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEvaluatorFacade.java
>new file mode 100644
>index 0000000..5c30df3
>--- /dev/null
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyEvaluatorFacade.java
>@@ -0,0 +1,128 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one
>+ * or more contributor license agreements. See the NOTICE file
>+ * distributed with this work for additional information
>+ * regarding copyright ownership. The ASF licenses this file
>+ * to you under the Apache License, Version 2.0 (the
>+ * "License"); you may not use this file except in compliance
>+ * with the License. You may obtain a copy of the License at
>+ *
>+ * http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing,
>+ * software distributed under the License is distributed on an
>+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>+ * KIND, either express or implied. See the License for the
>+ * specific language governing permissions and limitations
>+ * under the License.
>+ */
>+
>+package org.apache.ranger.plugin.policyengine;
>+
>+import org.apache.commons.logging.Log;
>+import org.apache.commons.logging.LogFactory;
>+import
>org.apache.ranger.plugin.conditionevaluator.RangerConditionEvaluator;
>+import org.apache.ranger.plugin.model.RangerPolicy;
>+import org.apache.ranger.plugin.model.RangerServiceDef;
>+import
>org.apache.ranger.plugin.policyevaluator.RangerDefaultPolicyEvaluator;
>+import
>org.apache.ranger.plugin.policyevaluator.RangerOptimizedPolicyEvaluator;
>+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
>+
>+import java.util.Map;
>+
>+public class RangerPolicyEvaluatorFacade implements
>RangerPolicyEvaluator,
>Comparable<RangerPolicyEvaluatorFacade> {
>+ private static final Log LOG =
>LogFactory.getLog(RangerPolicyEvaluatorFacade.class);
>+
>+ RangerDefaultPolicyEvaluator delegate = null;
>+ int computedPriority = 0;
>+ boolean useCachePolicyEngine = false;
>+
>+ RangerPolicyEvaluatorFacade(boolean useCachePolicyEngine) {
>+ super();
>+ this.useCachePolicyEngine = useCachePolicyEngine;
>+ delegate = new RangerOptimizedPolicyEvaluator();
>+ }
>+
>+ RangerPolicyEvaluator getPolicyEvaluator() {
>+ return delegate;
>+ }
>+
>+ @Override
>+ public void init(RangerPolicy policy, RangerServiceDef serviceDef) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyEvaluatorFacade.init(),
>useCachePolicyEngine:" + useCachePolicyEngine);
>+ }
>+ delegate.init(policy, serviceDef);
>+ computedPriority = computePriority();
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyEvaluatorFacade.init(),
>useCachePolicyEngine:" + useCachePolicyEngine);
>+ }
>+ }
>+
>+ @Override
>+ public RangerPolicy getPolicy() {
>+ return delegate.getPolicy();
>+ }
>+
>+ @Override
>+ public RangerServiceDef getServiceDef() {
>+ return delegate.getServiceDef();
>+ }
>+
>+ @Override
>+ public void evaluate(RangerAccessRequest request, RangerAccessResult
>result) {
>+ delegate.evaluate(request, result);
>+ }
>+
>+ @Override
>+ public boolean isMatch(RangerResource resource) {
>+ return false;
>+ }
>+
>+ @Override
>+ public boolean isSingleAndExactMatch(RangerResource resource) {
>+ return false;
>+ }
>+
>+ @Override
>+ public int compareTo(RangerPolicyEvaluatorFacade other) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyEvaluatorFacade.compareTo()");
>+ }
>+ int result;
>+
>+ if (this.getComputedPriority() == other.getComputedPriority()) {
>+ Map<String, RangerConditionEvaluator> myConditionEvaluators =
>this.delegate.getConditionEvaluators();
>+ Map<String, RangerConditionEvaluator>
>otherConditionEvaluators
>= other.delegate.getConditionEvaluators();
>+
>+ int myConditionEvaluatorCount = myConditionEvaluators == null
>? 0 : myConditionEvaluators.size();
>+ int otherConditionEvaluatorCount = otherConditionEvaluators
>==
>null ? 0 : otherConditionEvaluators.size();
>+
>+ result = Integer.compare(myConditionEvaluatorCount,
>otherConditionEvaluatorCount);
>+ } else {
>+ int myComputedPriority = this.getComputedPriority();
>+ int otherComputedPriority = other.getComputedPriority();
>+ result = Integer.compare(myComputedPriority,
>otherComputedPriority);
>+ }
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyEvaluatorFacade.compareTo(),
>result:" + result);
>+ }
>+
>+ return result;
>+ }
>+
>+ private int getComputedPriority() {
>+ return computedPriority;
>+ }
>+
>+ private int computePriority() {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerPolicyEvaluatorFacade.computePriority()");
>+ }
>+ int result = delegate.computePriority();
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<==RangerPolicyEvaluatorFacade.computePriority(),
>result:" + result);
>+ }
>+ return result;
>+ }
>+}
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyR
>ep
>ository.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyRepository.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyRepository.java
>new file mode 100644
>index 0000000..700b3ad
>--- /dev/null
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/Ranger
>Po
>licyRepository.java
>@@ -0,0 +1,231 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one
>+ * or more contributor license agreements. See the NOTICE file
>+ * distributed with this work for additional information
>+ * regarding copyright ownership. The ASF licenses this file
>+ * to you under the Apache License, Version 2.0 (the
>+ * "License"); you may not use this file except in compliance
>+ * with the License. You may obtain a copy of the License at
>+ *
>+ * http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing,
>+ * software distributed under the License is distributed on an
>+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>+ * KIND, either express or implied. See the License for the
>+ * specific language governing permissions and limitations
>+ * under the License.
>+ */
>+
>+package org.apache.ranger.plugin.policyengine;
>+
>+import org.apache.commons.collections.CollectionUtils;
>+import org.apache.commons.lang.StringUtils;
>+import org.apache.commons.logging.Log;
>+import org.apache.commons.logging.LogFactory;
>+import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
>+import org.apache.ranger.plugin.contextenricher.RangerContextEnricher;
>+import org.apache.ranger.plugin.model.RangerPolicy;
>+import org.apache.ranger.plugin.model.RangerServiceDef;
>+import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
>+
>+import java.util.ArrayList;
>+import java.util.Collections;
>+import java.util.List;
>+import java.util.Map;
>+
>+public class RangerPolicyRepository {
>+ private static final Log LOG =
>LogFactory.getLog(RangerPolicyRepository.class);
>+
>+ private String serviceName = null;
>+ private List<RangerPolicyEvaluatorFacade> policyEvaluators = null;
>+ private List<RangerContextEnricher> contextEnrichers = null;
>+ private RangerServiceDef serviceDef = null;
>+ // Not used at this time
>+ private boolean useCachePolicyEngine =
>false;
>+ private Map<String, RangerAccessData<Boolean>> accessAuditCache =
>null;
>+
>+ private static int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE =
>64*1024;
>+
>+ RangerPolicyRepository(String serviceName) {
>+ super();
>+ this.serviceName = serviceName;
>+ }
>+ String getRepositoryName() {
>+ return serviceName;
>+ }
>+ List<RangerPolicyEvaluatorFacade> getPolicyEvaluators() {
>+ return policyEvaluators;
>+ }
>+ List<RangerContextEnricher> getContextEnrichers() {
>+ return contextEnrichers;
>+ }
>+ RangerServiceDef getServiceDef() {
>+ return serviceDef;
>+ }
>+
>+ void init(RangerServiceDef serviceDef, List<RangerPolicy> policies) {
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyRepository.init(" + serviceDef +
>",
>policies.count=" + (policies == null ? 0 : policies.size()) + ")");
>+ }
>+
>+ this.serviceDef = serviceDef;
>+
>+ contextEnrichers = new ArrayList<RangerContextEnricher>();
>+
>+ if (!CollectionUtils.isEmpty(serviceDef.getContextEnrichers())) {
>+ for (RangerServiceDef.RangerContextEnricherDef enricherDef :
>serviceDef.getContextEnrichers()) {
>+ if (enricherDef == null) {
>+ continue;
>+ }
>+
>+ RangerContextEnricher contextEnricher =
>buildContextEnricher(enricherDef);
>+
>+ contextEnrichers.add(contextEnricher);
>+ }
>+ }
>+
>+ policyEvaluators = new ArrayList<RangerPolicyEvaluatorFacade>();
>+
>+ for (RangerPolicy policy : policies) {
>+ if (!policy.getIsEnabled()) {
>+ continue;
>+ }
>+
>+ RangerPolicyEvaluatorFacade evaluator =
>buildPolicyEvaluator(policy, serviceDef);
>+
>+ if (evaluator != null) {
>+ policyEvaluators.add(evaluator);
>+ }
>+
>+ Collections.sort(policyEvaluators);
>+
>+ }
>+
>+ String propertyName = "ranger.plugin." + serviceName +
>".policyengine.auditcachesize";
>+
>+ int auditResultCacheSize =
>RangerConfiguration.getInstance().getInt(propertyName,
>RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE);
>+
>+ accessAuditCache = new CacheMap<String,
>RangerAccessData<Boolean>>(auditResultCacheSize);
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyRepository.init(" + serviceDef +
>",
>policies.count=" + (policies == null ? 0 : policies.size()) + ")");
>+ }
>+ }
>+
>+ private RangerContextEnricher
>buildContextEnricher(RangerServiceDef.RangerContextEnricherDef
>enricherDef)
>{
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyRepository.buildContextEnricher("
>+
>enricherDef + ")");
>+ }
>+
>+ RangerContextEnricher ret = null;
>+
>+ String name = enricherDef != null ? enricherDef.getName()
>:
>null;
>+ String clsName = enricherDef != null ? enricherDef.getEnricher()
>:
>null;
>+
>+ if(! StringUtils.isEmpty(clsName)) {
>+ try {
>+ @SuppressWarnings("unchecked")
>+ Class<RangerContextEnricher> enricherClass =
>(Class<RangerContextEnricher>)Class.forName(clsName);
>+
>+ ret = enricherClass.newInstance();
>+ } catch(Exception excp) {
>+ LOG.error("failed to instantiate context enricher '" +
>clsName + "' for '" + name + "'", excp);
>+ }
>+ }
>+
>+ if(ret != null) {
>+ ret.init(enricherDef);
>+ }
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyRepository.buildContextEnricher("
>+
>enricherDef + "): " + ret);
>+ }
>+ return ret;
>+ }
>+
>+ private RangerPolicyEvaluatorFacade buildPolicyEvaluator(RangerPolicy
>policy, RangerServiceDef serviceDef) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyRepository.buildPolicyEvaluator("
>+
>policy + "," + serviceDef + ")");
>+ }
>+
>+ RangerPolicyEvaluatorFacade ret = null;
>+
>+ ret = new RangerPolicyEvaluatorFacade(useCachePolicyEngine);
>+ ret.init(policy, serviceDef);
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyRepository.buildPolicyEvaluator("
>+
>policy + "," + serviceDef + "): " + ret);
>+ }
>+ return ret;
>+ }
>+
>+ synchronized void retrieveAuditEnabled(RangerAccessRequest request,
>RangerAccessResult ret) {
>+ if (LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerPolicyRepository.retrieveAuditEnabled()");
>+ }
>+ RangerAccessData<Boolean> value =
>accessAuditCache.get(request.getResource().toString());
>+ if ((value != null)) {
>+ ret.setIsAudited(value.getAccessDetails());
>+ }
>+
>+ if (LOG.isDebugEnabled()) {
>+ LOG.debug("<==
>RangerPolicyRepository.retrieveAuditEnabled()");
>+ }
>+ }
>+
>+ synchronized void storeAuditEnabled(RangerAccessRequest request,
>RangerAccessResult ret) {
>+ if (LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerPolicyRepository.storeAuditEnabled()");
>+ }
>+ RangerAccessData<Boolean> lookup =
>accessAuditCache.get(request.getResource().toString());
>+ if ((lookup == null && ret.getIsAuditedDetermined() == true)) {
>+ RangerAccessData<Boolean> value = new
>RangerAccessData<Boolean>(request.toString());
>+ value.setAccessDetails(ret.getIsAudited());
>+ accessAuditCache.put(request.getResource().toString(),
>value);
>+ }
>+
>+ if (LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerPolicyRepository.storeAuditEnabled()");
>+ }
>+ }
>+
>+ @Override
>+ public String toString( ) {
>+ StringBuilder sb = new StringBuilder();
>+
>+ toString(sb);
>+
>+ return sb.toString();
>+ }
>+
>+ public StringBuilder toString(StringBuilder sb) {
>+
>+ sb.append("RangerPolicyRepository={");
>+
>+ sb.append("serviceName={").append(serviceName).append("} ");
>+ sb.append("serviceDef={").append(serviceDef).append("} ");
>+ sb.append("policyEvaluators={");
>+ if (policyEvaluators != null) {
>+ for (RangerPolicyEvaluator policyEvaluator :
>policyEvaluators)
>{
>+ if (policyEvaluator != null) {
>+ sb.append(policyEvaluator).append(" ");
>+ }
>+ }
>+ }
>+ if (contextEnrichers != null) {
>+ for (RangerContextEnricher contextEnricher :
>contextEnrichers)
>{
>+ if (contextEnricher != null) {
>+ sb.append(contextEnricher).append(" ");
>+ }
>+ }
>+ }
>+
>sb.append("useCachePolicyEngine={").append(useCachePolicyEngine).append("}
>
>");
>+
>+ sb.append("} ");
>+
>+ return sb;
>+ }
>+
>+}
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefa
>ul
>tPolicyEvaluator.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluator.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluator.java
>index 0ac5eed..30b36fa 100644
>---
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluator.java
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluator.java
>@@ -19,13 +19,7 @@
>
> package org.apache.ranger.plugin.policyevaluator;
>
>-import java.util.Collection;
>-import java.util.Collections;
>-import java.util.HashMap;
>-import java.util.HashSet;
>-import java.util.Iterator;
>-import java.util.Map;
>-
>+import com.google.common.base.Strings;
> import org.apache.commons.collections.CollectionUtils;
> import org.apache.commons.lang.StringUtils;
> import org.apache.commons.logging.Log;
>@@ -47,7 +41,7 @@ import
>org.apache.ranger.plugin.policyengine.RangerResource;
> import
>org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
> import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
>
>-import com.google.common.base.Strings;
>+import java.util.*;
>
>
> public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator {
>@@ -92,7 +86,13 @@ public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator
> }
> }
>
>- /**
>+ public Map<String, RangerConditionEvaluator>
>getConditionEvaluators()
>{
>+ return conditionEvaluators;
>+ }
>+ public int computePriority() { return 0;}
>+
>+
>+ /**
> * Non-private only for testability.
> * @param policy
> * @param serviceDef
>@@ -129,7 +129,7 @@ public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator
> if (Strings.isNullOrEmpty(evaluatorClassName)) {
> LOG.error("initializeConditionEvaluators: Serious Configuration
>error: Couldn't get condition evaluator class name for condition[" +
>conditionName + "]! Disabling all checks for this condition.");
> } else {
>- RangerConditionEvaluator anEvaluator =
>newConditionEvauator(evaluatorClassName);
>+ RangerConditionEvaluator anEvaluator =
>newConditionEvaluator(evaluatorClassName);
> if (anEvaluator == null) {
> LOG.error("initializeConditionEvaluators: Serious Configuration
>error: Couldn't instantiate condition evaluator for class[" +
>evaluatorClassName + "]. All checks for condition[" + conditionName + "]
>disabled.");
> } else {
>@@ -179,9 +179,9 @@ public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator
> return result;
> }
>
>- RangerConditionEvaluator newConditionEvauator(String className) {
>+ RangerConditionEvaluator newConditionEvaluator(String className) {
> if(LOG.isDebugEnabled()) {
>- LOG.debug(String.format("==>
>RangerDefaultPolicyEvaluator.newConditionEvauator(%s)", className));
>+ LOG.debug(String.format("==>
>RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", className));
> }
>
> RangerConditionEvaluator evaluator = null;
>@@ -195,92 +195,135 @@ public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator
> }
>
> if(LOG.isDebugEnabled()) {
>- LOG.debug(String.format("<==
>RangerDefaultPolicyEvaluator.newConditionEvauator(%s)", evaluator == null
>?
>null : evaluator.toString()));
>+ LOG.debug(String.format("<==
>RangerDefaultPolicyEvaluator.newConditionEvaluator(%s)", evaluator ==
>null ?
>null : evaluator.toString()));
> }
> return evaluator;
> }
>
> @Override
>- public void evaluate(RangerAccessRequest request, RangerAccessResult
>result) {
>- if(LOG.isDebugEnabled()) {
>- LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" + request + ",
>"
>+ result + ")");
>- }
>-
>- RangerPolicy policy = getPolicy();
>-
>- if(policy != null && request != null && result != null) {
>- boolean isResourceMatch = isMatch(request.getResource());
>- boolean isResourceHeadMatch = isResourceMatch ||
>matchResourceHead(request.getResource());
>- String accessType = request.getAccessType();
>-
>- if(StringUtils.isEmpty(accessType)) {
>- accessType = RangerPolicyEngine.ANY_ACCESS;
>- }
>-
>- boolean isAnyAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ANY_ACCESS);
>- boolean isAdminAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ADMIN_ACCESS);
>-
>- if(isResourceMatch || (isResourceHeadMatch && isAnyAccess)) {
>- if(policy.getIsAuditEnabled()) {
>- result.setIsAudited(true);
>- }
>-
>- for(RangerPolicyItem policyItem : policy.getPolicyItems()) {
>- if(isAdminAccess) {
>- if(policyItem.getDelegateAdmin()) {
>- result.setIsAllowed(true);
>- result.setPolicyId(policy.getId());
>- break;
>- }
>-
>- continue;
>- }
>-
>- if(CollectionUtils.isEmpty(policyItem.getAccesses())) {
>- continue;
>- }
>-
>- boolean isUserGroupMatch = matchUserGroup(policyItem,
>request.getUser(), request.getUserGroups());
>-
>- if(! isUserGroupMatch) {
>- continue;
>- }
>-
>- boolean isCustomConditionsMatch = matchCustomConditions(policyItem,
>request, conditionEvaluators);
>-
>- if(! isCustomConditionsMatch) {
>- continue;
>- }
>-
>- if(isAnyAccess) {
>- for(RangerPolicyItemAccess access : policyItem.getAccesses()) {
>- if(access.getIsAllowed()) {
>- result.setIsAllowed(true);
>- result.setPolicyId(policy.getId());
>- break;
>- }
>- }
>- } else {
>- RangerPolicyItemAccess access = getAccess(policyItem, accessType);
>-
>- if(access != null && access.getIsAllowed()) {
>- result.setIsAllowed(true);
>- result.setPolicyId(policy.getId());
>- }
>- }
>-
>- if(result.getIsAllowed()) {
>- break;
>- }
>- }
>- }
>- }
>-
>- if(LOG.isDebugEnabled()) {
>+ public void evaluate(RangerAccessRequest request, RangerAccessResult
>result) {
>+ if (LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(" +
>request + ", " + result + ")");
>+ }
>+ RangerPolicy policy = getPolicy();
>+
>+ if (policy != null && request != null && result != null) {
>+
>+ String accessType = request.getAccessType();
>+ if (StringUtils.isEmpty(accessType)) {
>+ accessType = RangerPolicyEngine.ANY_ACCESS;
>+ }
>+ boolean isAnyAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ANY_ACCESS);
>+
>+ boolean isMatchAttempted = false;
>+ boolean matchResult = false;
>+ boolean headMatchResult = false;
>+
>+ if (!result.getIsAuditedDetermined()) {
>+ // Need to match request.resource first. If it matches
>(or
>head matches), then only more progress can be made
>+ matchResult = isMatch(request.getResource());
>+ isMatchAttempted = true;
>+
>+ if (matchResult) {
>+ // Do all stuff.
>+ if (policy.getIsAuditEnabled()) {
>+ result.setIsAudited(true);
>+ }
>+ }
>+ }
>+
>+ if (!result.getIsAccessDetermined()) {
>+ if (!isMatchAttempted) {
>+ // Need to match request.resource first. If it
>matches
>(or head matches), then only more progress can be made
>+ matchResult = isMatch(request.getResource());
>+ isMatchAttempted = true;
>+ }
>+
>+ // Try head match only if it is useful
>+ if (isAnyAccess) {
>+ headMatchResult = matchResult ||
>matchResourceHead(request.getResource());
>+ }
>+
>+ if (matchResult || (isAnyAccess && headMatchResult)) {
>+ // A match was found earlier
>+ evaluatePolicyItemsForAccess(request, result);
>+ }
>+ }
>+ }
>+
>+ if(LOG.isDebugEnabled()) {
> LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(" + request + ",
>"
>+ result + ")");
> }
> }
>
>+ protected void evaluatePolicyItemsForAccess(RangerAccessRequest
>request, RangerAccessResult result) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess()");
>+ }
>+ String accessType = request.getAccessType();
>+ if (StringUtils.isEmpty(accessType)) {
>+ accessType = RangerPolicyEngine.ANY_ACCESS;
>+ }
>+ boolean isAnyAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ANY_ACCESS);
>+ boolean isAdminAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ADMIN_ACCESS);
>+
>+ for (RangerPolicy.RangerPolicyItem policyItem :
>getPolicy().getPolicyItems()) {
>+
>+ boolean isUserGroupMatch = matchUserGroup(policyItem,
>request.getUser(), request.getUserGroups());
>+
>+ if (!isUserGroupMatch) {
>+ continue;
>+ }
>+ // This is only for Grant and Revoke access requests sent by
>the component. For those cases
>+ // Our plugin will fill in the accessType as ADMIN_ACCESS.
>+
>+ if (isAdminAccess) {
>+ if (policyItem.getDelegateAdmin()) {
>+ result.setIsAllowed(true);
>+ result.setPolicyId(getPolicy().getId());
>+ break;
>+ }
>+ continue;
>+ }
>+
>+ if (CollectionUtils.isEmpty(policyItem.getAccesses())) {
>+ continue;
>+ }
>+
>+ boolean accessAllowed = false;
>+ if (isAnyAccess) {
>+ for (RangerPolicy.RangerPolicyItemAccess access :
>policyItem.getAccesses()) {
>+ if (access.getIsAllowed()) {
>+ accessAllowed = true;
>+ break;
>+ }
>+ }
>+ } else {
>+ RangerPolicy.RangerPolicyItemAccess access =
>getAccess(policyItem, accessType);
>+
>+ if (access != null && access.getIsAllowed()) {
>+ accessAllowed = true;
>+ }
>+ }
>+ if (accessAllowed == false) {
>+ continue;
>+ }
>+
>+ boolean isCustomConditionsMatch =
>matchCustomConditions(policyItem, request, getConditionEvaluators());
>+
>+ if (!isCustomConditionsMatch) {
>+ continue;
>+ }
>+
>+ result.setIsAllowed(true);
>+ result.setPolicyId(getPolicy().getId());
>+ break;
>+ }
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<==
>RangerDefaultPolicyEvaluator.evaluatePolicyItemsForAccess()");
>+ }
>+ }
>+
> @Override
> public boolean isMatch(RangerResource resource) {
> if(LOG.isDebugEnabled()) {
>@@ -554,7 +597,7 @@ public class RangerDefaultPolicyEvaluator extends
>RangerAbstractPolicyEvaluator
> }
>
> if(LOG.isDebugEnabled()) {
>- LOG.debug("==> RangerDefaultPolicyEvaluator.createResourceMatcher(" +
>resourceDef + ", " + resource + "): " + ret);
>+ LOG.debug("<== RangerDefaultPolicyEvaluator.createResourceMatcher(" +
>resourceDef + ", " + resource + "): " + ret);
> }
>
> return ret;
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOpti
>mi
>zedPolicyEvaluator.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rOptimizedPolicyEvaluator.java
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rOptimizedPolicyEvaluator.java
>new file mode 100644
>index 0000000..59fb87c
>--- /dev/null
>+++
>b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rOptimizedPolicyEvaluator.java
>@@ -0,0 +1,247 @@
>+/*
>+ * Licensed to the Apache Software Foundation (ASF) under one
>+ * or more contributor license agreements. See the NOTICE file
>+ * distributed with this work for additional information
>+ * regarding copyright ownership. The ASF licenses this file
>+ * to you under the Apache License, Version 2.0 (the
>+ * "License"); you may not use this file except in compliance
>+ * with the License. You may obtain a copy of the License at
>+ *
>+ * http://www.apache.org/licenses/LICENSE-2.0
>+ *
>+ * Unless required by applicable law or agreed to in writing,
>+ * software distributed under the License is distributed on an
>+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>+ * KIND, either express or implied. See the License for the
>+ * specific language governing permissions and limitations
>+ * under the License.
>+ */
>+
>+package org.apache.ranger.plugin.policyevaluator;
>+
>+import org.apache.commons.collections.CollectionUtils;
>+import org.apache.commons.lang.StringUtils;
>+import org.apache.commons.logging.Log;
>+import org.apache.commons.logging.LogFactory;
>+import org.apache.ranger.plugin.model.RangerPolicy;
>+import org.apache.ranger.plugin.model.RangerServiceDef;
>+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
>+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
>+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
>+
>+import java.util.*;
>+import java.lang.Math;
>+
>+public class RangerOptimizedPolicyEvaluator extends
>RangerDefaultPolicyEvaluator {
>+ private static final Log LOG =
>LogFactory.getLog(RangerOptimizedPolicyEvaluator.class);
>+
>+ private Set<String> groups = null;
>+ private Set<String> users = null;
>+ private Set<String> accessPerms = null;
>+ private boolean delegateAdmin = false;
>+ private boolean hasAllPerms = false;
>+ private boolean hasPublicGroup = false;
>+
>+
>+ // For computation of priority
>+ private static final String
>RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING = "*";
>+ private static final String
>RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING = "?";
>+ private static final int
>RANGER_POLICY_EVAL_MATCH_ANY_WILDCARD_PREMIUM
>= 25;
>+ private static final int
>RANGER_POLICY_EVAL_CONTAINS_MATCH_ANY_WILDCARD_PREMIUM = 10;
>+ private static final int
>RANGER_POLICY_EVAL_CONTAINS_MATCH_ONE_CHARACTER_WILDCARD_PREMIUM = 10;
>+ private static final int RANGER_POLICY_EVAL_HAS_EXCLUDES_PREMIUM
>
>= 25;
>+ private static final int RANGER_POLICY_EVAL_IS_RECURSIVE_PREMIUM
>
>= 25;
>+ private static final int
>RANGER_POLICY_EVAL_PUBLIC_GROUP_ACCESS_PREMIUM = 25;
>+ private static final int RANGER_POLICY_EVAL_ALL_ACCESS_TYPES_PREMIUM
>
>= 25;
>+ private static final int RANGER_POLICY_EVAL_RESERVED_SLOTS_NUMBER
>
>= 10000;
>+ private static final int
>RANGER_POLICY_EVAL_RESERVED_SLOTS_PER_LEVEL_NUMBER = 1000;
>+
>+ @Override
>+ public void init(RangerPolicy policy, RangerServiceDef serviceDef) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==> RangerOptimizedPolicyEvaluator.init()");
>+ }
>+
>+ super.init(policy, serviceDef);
>+
>+ accessPerms = new HashSet<String>();
>+ groups = new HashSet<String>();
>+ users = new HashSet<String>();
>+
>+ for (RangerPolicy.RangerPolicyItem item :
>policy.getPolicyItems())
>{
>+ delegateAdmin = delegateAdmin || item.getDelegateAdmin();
>+
>+ List<RangerPolicy.RangerPolicyItemAccess> policyItemAccesses
>=
>item.getAccesses();
>+ for(RangerPolicy.RangerPolicyItemAccess policyItemAccess :
>policyItemAccesses) {
>+
>+ if (policyItemAccess.getIsAllowed()) {
>+ String accessType = policyItemAccess.getType();
>+ accessPerms.add(accessType);
>+ }
>+ }
>+
>+ groups.addAll(item.getGroups());
>+ users.addAll(item.getUsers());
>+ }
>+
>+ hasAllPerms = checkIfHasAllPerms();
>+
>+ for (String group : groups) {
>+ if (group.equalsIgnoreCase(RangerPolicyEngine.GROUP_PUBLIC))
>{
>+ hasPublicGroup = true;
>+ }
>+ }
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<== RangerOptimizedPolicyEvaluator.init()");
>+ }
>+ }
>+
>+ @Override
>+ public int computePriority() {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerOptimizedPolicyEvaluator.computePriority()");
>+ }
>+ RangerServiceDef serviceDef = getServiceDef();
>+ RangerPolicy policy = getPolicy();
>+
>+ class LevelResourceNames implements
>Comparable<LevelResourceNames>
>{
>+ int level;
>+ RangerPolicy.RangerPolicyResource policyResource;
>+
>+ @Override
>+ public int compareTo(LevelResourceNames other) {
>+ // Sort in ascending order of level numbers
>+ return Integer.compare(this.level, other.level);
>+ }
>+ }
>+ List<LevelResourceNames> tmpList = new
>ArrayList<LevelResourceNames>();
>+
>+ List<RangerServiceDef.RangerResourceDef> resourceDefs =
>serviceDef.getResources();
>+
>+ for (Map.Entry<String, RangerPolicy.RangerPolicyResource>
>keyValuePair : policy.getResources().entrySet()) {
>+ String serviceDefResourceName = keyValuePair.getKey();
>+ RangerPolicy.RangerPolicyResource policyResource =
>keyValuePair.getValue();
>+ List<String> policyResourceNames =
>policyResource.getValues();
>+
>+ RangerServiceDef.RangerResourceDef found = null;
>+ for (RangerServiceDef.RangerResourceDef resourceDef :
>resourceDefs) {
>+ if
>(serviceDefResourceName.equals(resourceDef.getName()))
>{
>+ found = resourceDef;
>+ break;
>+ }
>+ }
>+ if (found != null) {
>+ int level = found.getLevel();
>+ if (policyResourceNames != null) {
>+ LevelResourceNames item = new LevelResourceNames();
>+ item.level = level;
>+ item.policyResource = policyResource;
>+ tmpList.add(item);
>+ }
>+
>+ }
>+
>+ }
>+ Collections.sort(tmpList); // Sort in ascending order of levels
>+
>+ CharSequence matchesAnySeq =
>RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING.subSequence(0, 1);
>+ CharSequence matchesSingleCharacterSeq =
>RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING.subSequence(0, 1);
>+
>+ int priorityLevel = RANGER_POLICY_EVAL_RESERVED_SLOTS_NUMBER;
>+ boolean seenFirstMatchAny = false;
>+
>+ for (LevelResourceNames item : tmpList) {
>+ // Expect lowest level first
>+ List<String> resourceNames = item.policyResource.getValues();
>+ boolean foundStarWildcard = false;
>+ boolean foundQuestionWildcard = false;
>+ boolean foundMatchAny = false;
>+
>+ for (String resourceName : resourceNames) {
>+ if (resourceName.isEmpty()
>||resourceName.equals(RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING)) {
>+ foundMatchAny = true;
>+ break;
>+ }
>+ if (resourceName.contains(matchesAnySeq))
>+ foundStarWildcard = true;
>+ else if
>(resourceName.contains(matchesSingleCharacterSeq))
>+ foundQuestionWildcard = true;
>+ }
>+ if (foundMatchAny) {
>+ if (seenFirstMatchAny)
>+ priorityLevel -=
>RANGER_POLICY_EVAL_MATCH_ANY_WILDCARD_PREMIUM;
>+ else {
>+ seenFirstMatchAny = true;
>+ }
>+ } else {
>+ priorityLevel +=
>RANGER_POLICY_EVAL_RESERVED_SLOTS_PER_LEVEL_NUMBER;
>+ if (foundStarWildcard) priorityLevel -=
>RANGER_POLICY_EVAL_CONTAINS_MATCH_ANY_WILDCARD_PREMIUM;
>+ else if (foundQuestionWildcard) priorityLevel -=
>RANGER_POLICY_EVAL_CONTAINS_MATCH_ONE_CHARACTER_WILDCARD_PREMIUM;
>+
>+ RangerPolicy.RangerPolicyResource resource =
>item.policyResource;
>+ if (resource.getIsExcludes()) priorityLevel -=
>RANGER_POLICY_EVAL_HAS_EXCLUDES_PREMIUM;
>+ if (resource.getIsRecursive()) priorityLevel -=
>RANGER_POLICY_EVAL_IS_RECURSIVE_PREMIUM;
>+ }
>+ }
>+
>+ if (hasPublicGroup) {
>+ priorityLevel -=
>RANGER_POLICY_EVAL_PUBLIC_GROUP_ACCESS_PREMIUM;
>+ } else {
>+ priorityLevel -= groups.size();
>+ }
>+ priorityLevel -= users.size();
>+
>+ priorityLevel -=
>Math.round(((float)RANGER_POLICY_EVAL_ALL_ACCESS_TYPES_PREMIUM *
>accessPerms.size()) / serviceDef.getAccessTypes().size());
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<==
>RangerOptimizedPolicyEvaluator.computePriority(), policyName:" +
>policy.getName() + ", priority:" + priorityLevel);
>+ }
>+ return priorityLevel;
>+ }
>+ @Override
>+ protected void evaluatePolicyItemsForAccess(RangerAccessRequest
>request, RangerAccessResult result) {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerOptimizedPolicyEvaluator.evaluatePolicyItemsForAccess()");
>+ }
>+ String accessType = request.getAccessType();
>+ if (StringUtils.isEmpty(accessType)) {
>+ accessType = RangerPolicyEngine.ANY_ACCESS;
>+ }
>+ boolean isAnyAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ANY_ACCESS);
>+ boolean isAdminAccess = StringUtils.equals(accessType,
>RangerPolicyEngine.ADMIN_ACCESS);
>+
>+ if (hasPublicGroup || users.contains(request.getUser()) ||
>CollectionUtils.containsAny(groups, request.getUserGroups())) {
>+ // No need to reject based on users and groups
>+
>+ if (isAnyAccess || (isAdminAccess && delegateAdmin) ||
>hasAllPerms || accessPerms.contains(accessType)) {
>+ // No need to reject based on aggregated access
>permissions
>+ super.evaluatePolicyItemsForAccess(request, result);
>+ }
>+ }
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("<==
>RangerOptimizedPolicyEvaluator.evaluatePolicyItemsForAccess()");
>+ }
>+
>+ }
>+ private boolean checkIfHasAllPerms() {
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerOptimizedPolicyEvaluator.checkIfHasAllPerms()");
>+ }
>+
>+ boolean result = true;
>+
>+ List<RangerServiceDef.RangerAccessTypeDef> serviceAccessTypes =
>getServiceDef().getAccessTypes();
>+ for (RangerServiceDef.RangerAccessTypeDef serviceAccessType :
>serviceAccessTypes) {
>+ if(! accessPerms.contains(serviceAccessType.getName())) {
>+ return false;
>+ }
>+ }
>+
>+ if(LOG.isDebugEnabled()) {
>+ LOG.debug("==>
>RangerOptimizedPolicyEvaluator.checkIfHasAllPerms(), " + result);
>+ }
>+
>+ return result;
>+ }
>+
>+}
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/test/java/org/apache/ranger/plugin/policyevaluator/RangerDefa
>ul
>tPolicyEvaluatorTest.java
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluatorTest.java
>b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluatorTest.java
>index 9256995..9efbcaf 100644
>---
>a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluatorTest.java
>+++
>b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/Ran
>ge
>rDefaultPolicyEvaluatorTest.java
>@@ -59,15 +59,15 @@ public class RangerDefaultPolicyEvaluatorTest {
> }
>
> @Test
>- public void test_newConditionEvauator() {
>+ public void test_newConditionEvaulator() {
> RangerDefaultPolicyEvaluator evaluator = new
>RangerDefaultPolicyEvaluator();
>- RangerConditionEvaluator ipMatcher =
>evaluator.newConditionEvauator("org.apache.ranger.plugin.conditionevaluato
>r.
>RangerIpMatcher");
>+ RangerConditionEvaluator ipMatcher =
>evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluat
>or
>.RangerIpMatcher");
> assertTrue(ipMatcher.getClass().equals(RangerIpMatcher.class));
>
> // bogus value will lead to null object from coming back
>- ipMatcher =
>evaluator.newConditionEvauator("org.apache.ranger.plugin.conditionevaluato
>r.
>RangerIpMatcha");
>+ ipMatcher =
>evaluator.newConditionEvaluator("org.apache.ranger.plugin.conditionevaluat
>or
>.RangerIpMatcha");
> assertNull(ipMatcher);
>- ipMatcher = evaluator.newConditionEvauator("RangerIpMatcher");
>+ ipMatcher = evaluator.newConditionEvaluator("RangerIpMatcher");
> assertNull(ipMatcher);
> }
>
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/agen
>t
>s-common/src/test/resources/policyengine/test_policyengine_hdfs.json
>----------------------------------------------------------------------
>diff --git
>a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.jso
>n
>b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.jso
>n
>index 943fe80..2acf868 100644
>---
>a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.jso
>n
>+++
>b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs.jso
>n
>@@ -23,7 +23,7 @@
> }
> ,
> {"id":2,"name":"allow-read-to-all under
>/public/","isEnabled":true,"isAuditEnabled":false,
>- "resources":{"path":{"values":["/public/"],"isRecursive":true}},
>+ "resources":{"path":{"values":["/public/*"],"isRecursive":true}},
> "policyItems":[
>
>{"accesses":[{"type":"read","isAllowed":true},{"type":"execute","isAllowed
>":
>true}],"users":[],"groups":["public"],"delegateAdmin":false}
> ]
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/pom.
>x
>ml
>----------------------------------------------------------------------
>diff --git a/pom.xml b/pom.xml
>index 7df033d..fe340c4 100644
>--- a/pom.xml
>+++ b/pom.xml
>@@ -333,9 +333,9 @@
> <descriptor>src/main/assembly/plugin-yarn.xml</descriptor>
> <descriptor>src/main/assembly/admin-web.xml</descriptor>
> <descriptor>src/main/assembly/usersync.xml</descriptor>
>- <descriptor>src/main/assembly/ranger-src.xml</descriptor>
>
><descriptor>src/main/assembly/migration-util.xml</descriptor>
> <descriptor>src/main/assembly/kms.xml</descriptor>
>+ <descriptor>src/main/assembly/ranger-src.xml</descriptor>
> </descriptors>
> </configuration>
> </plugin>
>
>http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/2e0be82d/src/
>m
>ain/assembly/ranger-src.xml
>----------------------------------------------------------------------
>diff --git a/src/main/assembly/ranger-src.xml
>b/src/main/assembly/ranger-src.xml
>index cf6b1da..077fa42 100644
>--- a/src/main/assembly/ranger-src.xml
>+++ b/src/main/assembly/ranger-src.xml
>@@ -16,45 +16,46 @@
> limitations under the License.
> -->
> <assembly>
>- <id>src</id>
>- <formats>
>- <format>tar.gz</format>
>- <format>zip</format>
>- </formats>
>- <baseDirectory>${project.name}-${project.version}-src</baseDirectory>
>- <includeBaseDirectory>true</includeBaseDirectory>
>- <fileSets>
>- <fileSet>
>- <directory>.</directory>
>- <includes>
>- <include>LICENCE.txt</include>
>- <include>README.txt</include>
>- <include>NOTICE.txt</include>
>- <include>DISCLAIMER.txt</include>
>- </includes>
>- </fileSet>
>- <fileSet>
>- <directory>.</directory>
>- <useDefaultExcludes>true</useDefaultExcludes>
>- <excludes>
>- <exclude>.git/**</exclude>
>- <exclude>**/.gitignore</exclude>
>- <exclude>**/.svn</exclude>
>- <exclude>**/*.iws</exclude>
>- <exclude>**/*.ipr</exclude>
>- <exclude>**/*.iml</exclude>
>- <exclude>**/.classpath</exclude>
>- <exclude>**/.project</exclude>
>- <exclude>**/.settings</exclude>
>- <exclude>**/target/**</exclude>
>- <!-- until the code that does this is fixed -->
>- <exclude>**/*.log</exclude>
>- <exclude>**/build/**</exclude>
>- <exclude>**/file:/**</exclude>
>- <exclude>**/debugfiles.list</exclude>
>- <exclude>**/debuglinks.list</exclude>
>- <exclude>**/debugsources.list</exclude>
>- </excludes>
>- </fileSet>
>- </fileSets>
>+ <id>src</id>
>+ <formats>
>+ <format>tar.gz</format>
>+ <format>zip</format>
>+ </formats>
>+ <baseDirectory>${project.name}-${project.version}-src</baseDirectory>
>+ <includeBaseDirectory>true</includeBaseDirectory>
>+ <fileSets>
>+ <fileSet>
>+ <directory>.</directory>
>+ <includes>
>+ <include>LICENCE.txt</include>
>+ <include>README.txt</include>
>+ <include>NOTICE.txt</include>
>+ <include>DISCLAIMER.txt</include>
>+ </includes>
>+ <useDefaultExcludes>true</useDefaultExcludes>
>+ </fileSet>
>+ <fileSet>
>+ <directory>.</directory>
>+ <excludes>
>+ <exclude>.git/**</exclude>
>+ <exclude>**/.gitignore</exclude>
>+ <exclude>**/.svn</exclude>
>+ <exclude>**/*.iws</exclude>
>+ <exclude>**/*.ipr</exclude>
>+ <exclude>**/*.iml</exclude>
>+ <exclude>**/.classpath</exclude>
>+ <exclude>**/.project</exclude>
>+ <exclude>**/.settings</exclude>
>+ <exclude>**/target/**</exclude>
>+ <exclude>.idea/**</exclude>
>+ <!-- until the code that does this is fixed -->
>+ <exclude>**/*.log</exclude>
>+ <exclude>**/build/**</exclude>
>+ <exclude>**/file:/**</exclude>
>+ <exclude>**/debugfiles.list</exclude>
>+ <exclude>**/debuglinks.list</exclude>
>+ <exclude>**/debugsources.list</exclude>
>+ </excludes>
>+ </fileSet>
>+ </fileSets>
> </assembly>
>
>
>