Repository: incubator-ranger
Updated Branches:
  refs/heads/ranger-0.5 80c46f22f -> 0d73c38af


RANGER-507: Resource-match logic moved out of policy-evaluator implementation 
to enable reuse


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/776533f9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/776533f9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/776533f9

Branch: refs/heads/ranger-0.5
Commit: 776533f9463a2c9e7c6e4c83845e955bc70d4820
Parents: 80c46f2
Author: Madhan Neethiraj <[email protected]>
Authored: Wed May 27 16:19:24 2015 -0700
Committer: Madhan Neethiraj <[email protected]>
Committed: Wed May 27 17:30:30 2015 -0700

----------------------------------------------------------------------
 .../RangerDefaultPolicyEvaluator.java           | 239 ++----------
 .../RangerDefaultPolicyResourceMatcher.java     | 364 +++++++++++++++++++
 .../RangerPolicyResourceMatcher.java            |  44 +++
 3 files changed, 430 insertions(+), 217 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/776533f9/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index ede91f0..9233f8d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -40,24 +40,22 @@ import 
org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
 import 
org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
-import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerAccessResult;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
-import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
-import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+import 
org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
+import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
 
 import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
 
 
 public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator {
        private static final Log LOG = 
LogFactory.getLog(RangerDefaultPolicyEvaluator.class);
 
-       private Map<String, RangerResourceMatcher>    matchers;
-       private Map<String, RangerConditionEvaluator> conditionEvaluators;
+       private RangerPolicyResourceMatcher           resourceMatcher     = 
null;
+       private Map<String, RangerConditionEvaluator> conditionEvaluators = 
null;
 
        @Override
        public void init(RangerPolicy policy, RangerServiceDef serviceDef, 
RangerPolicyEngineOptions options) {
@@ -69,24 +67,11 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                super.init(policy, serviceDef, options);
 
-               this.matchers = new HashMap<String, RangerResourceMatcher>();
+               resourceMatcher = new RangerDefaultPolicyResourceMatcher();
 
-               if(policy != null && policy.getResources() != null && 
serviceDef != null) {
-                       for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                               String               resourceName   = 
resourceDef.getName();
-                               RangerPolicyResource policyResource = 
policy.getResources().get(resourceName);
-
-                               if(policyResource != null) {
-                                       RangerResourceMatcher matcher = 
createResourceMatcher(resourceDef, policyResource);
-
-                                       if(matcher != null) {
-                                               matchers.put(resourceName, 
matcher);
-                                       } else {
-                                               LOG.error("failed to find 
matcher for resource " + resourceName);
-                                       }
-                               }
-                       }
-               }
+               resourceMatcher.setServiceDef(serviceDef);
+               resourceMatcher.setPolicyResources(policy == null ? null : 
policy.getResources());
+               resourceMatcher.init();
 
                if(options.disableCustomConditions) {
                        conditionEvaluators = Collections.<String, 
RangerConditionEvaluator>emptyMap();
@@ -347,36 +332,8 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                boolean ret = false;
 
-               RangerServiceDef serviceDef = getServiceDef();
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resource == null ? 
null : resource.getKeys();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = 
CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && 
policyKeys.containsAll(resourceKeys));
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName  = 
resourceDef.getName();
-                                       String                resourceValue = 
resource == null ? null : resource.getValue(resourceName);
-                                       RangerResourceMatcher matcher       = 
matchers == null ? null : matchers.get(resourceName);
-
-                                       // when no value exists for a 
resourceName, consider it a match only if: policy doesn't have a matcher OR 
matcher allows no-value resource
-                                       if(StringUtils.isEmpty(resourceValue)) {
-                                               ret = matcher == null || 
matcher.isMatch(resourceValue);
-                                       } else {
-                                               ret = matcher != null && 
matcher.isMatch(resourceValue);
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isMatch(): keysMatch=false. 
isMatch=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
+               if(resourceMatcher != null) {
+                       ret = resourceMatcher.isMatch(resource);
                }
 
                if(LOG.isDebugEnabled()) {
@@ -394,39 +351,8 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                boolean ret = false;
 
-               RangerServiceDef serviceDef = getServiceDef();
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resource == null ? 
null : resource.getKeys();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = false;
-
-                       if (resourceKeys != null && policyKeys != null) {
-                               keysMatch = 
CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
-                       }
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName  = 
resourceDef.getName();
-                                       String                resourceValue = 
resource == null ? null : resource.getValue(resourceName);
-                                       RangerResourceMatcher matcher       = 
matchers == null ? null : matchers.get(resourceName);
-
-                                       if(StringUtils.isEmpty(resourceValue)) {
-                                               ret = matcher == null || 
matcher.isSingleAndExactMatch(resourceValue);
-                                       } else {
-                                               ret = matcher != null && 
matcher.isSingleAndExactMatch(resourceValue);
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isSingleAndExactMatch(): 
keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
+               if(resourceMatcher != null) {
+                       ret = resourceMatcher.isSingleAndExactMatch(resource);
                }
 
                if(LOG.isDebugEnabled()) {
@@ -471,53 +397,11 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                if(LOG.isDebugEnabled()) {
                        LOG.debug("==> 
RangerDefaultPolicyEvaluator.matchResourceHead(" + resource + ")");
                }
-               boolean ret; 
-               
-               if (resource == null || 
CollectionUtils.isEmpty(resource.getKeys())) { // sanity-check, firewalling
-                       LOG.debug("matchResourceHead: resource was 
null/empty!");
-                       ret = true; // null resource matches anything
-               } else if (getServiceDef() == null) { // sanity-check, 
firewalling
-                       LOG.debug("matchResourceHead: service-def was null!");
-                       ret = false; // null policy can never match a non-empty 
resource 
-               } else if (getPolicy() == null || getPolicy().getResources() == 
null) {
-                       LOG.debug("matchResourceHead: policy or its resources 
were null!");
-                       ret = false; // null policy can never match a non-empty 
resource 
-               } else if (matchers == null || matchers.size() != 
getPolicy().getResources().size()) { // sanity-check, firewalling
-                       LOG.debug("matchResourceHead: matchers could be found 
for some of the policy resources");
-                       ret = false; // empty policy can never match a 
non-empty resources and can't be evaluated meaningfully in matchers are absent
-               } else {
-                       if (!Sets.difference(resource.getKeys(), 
matchers.keySet()).isEmpty()) { // e.g. avoid using udf policy for resource 
that has more than db specified and vice-versa
-                               LOG.debug("matchResourceHead: resource/policy 
resource-keys mismatch. policy is incompatible with resource; can't match.");
-                               ret = false;
-                       } else {
-                               Set<String> policyResourceNames = 
matchers.keySet();
-                               boolean skipped = false;
-                               boolean matched = true;
-                               Iterator<RangerResourceDef> iterator = 
getServiceDef().getResources().iterator();
-                               while (iterator.hasNext() && matched) {
-                                       RangerResourceDef resourceDef = 
iterator.next();
-                                       String resourceName = 
resourceDef.getName();
-                                       // we only work with resources that are 
relevant to this policy
-                                       if 
(policyResourceNames.contains(resourceName)) {
-                                               String resourceValue = 
resource.getValue(resourceName);
-                                               if 
(StringUtils.isEmpty(resourceValue)) {
-                                                       if 
(LOG.isDebugEnabled()) {
-                                                               
LOG.debug("Skipping matching for " + resourceName + " since it is null/empty on 
resource");
-                                                       }
-                                                       skipped = true; // once 
we skip a level all lower levels must be skippable, too
-                                               } else if (skipped == true) {
-                                                       
LOG.debug("matchResourceHead: found a lower level resource when a higer level 
resource was absent!");
-                                                       matched = false;
-                                               } else if 
(!matchers.get(resourceName).isMatch(resourceValue)) {
-                                                       if 
(LOG.isDebugEnabled()) {
-                                                               
LOG.debug("matchResourceHead: matcher for " + resourceName + " failed");
-                                                       }
-                                                       matched = false;
-                                               }
-                                       }
-                               }
-                               ret = matched;
-                       }
+
+               boolean ret = false;
+
+               if(resourceMatcher != null) {
+                       ret = resourceMatcher.isHeadMatch(resource);
                }
 
                if(LOG.isDebugEnabled()) {
@@ -623,49 +507,6 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
                return ret;
        }
 
-       protected static RangerResourceMatcher 
createResourceMatcher(RangerResourceDef resourceDef, RangerPolicyResource 
resource) {
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("==> 
RangerDefaultPolicyEvaluator.createResourceMatcher(" + resourceDef + ", " + 
resource + ")");
-               }
-
-               RangerResourceMatcher ret = null;
-
-               if (resourceDef != null) {
-                       String resName = resourceDef.getName();
-                       String clsName = resourceDef.getMatcher();
-
-                       if (!StringUtils.isEmpty(clsName)) {
-                               try {
-                                       @SuppressWarnings("unchecked")
-                                       Class<RangerResourceMatcher> 
matcherClass = (Class<RangerResourceMatcher>) Class.forName(clsName);
-
-                                       ret = matcherClass.newInstance();
-                               } catch (Exception excp) {
-                                       LOG.error("failed to instantiate 
resource matcher '" + clsName + "' for '" + resName + "'. Default resource 
matcher will be used", excp);
-                               }
-                       }
-
-
-                       if (ret == null) {
-                               ret = new RangerDefaultResourceMatcher();
-                       }
-
-                       if (ret != null) {
-                               ret.setResourceDef(resourceDef);
-                               ret.setPolicyResource(resource);
-                               ret.init();
-                       }
-               } else {
-                       LOG.error("RangerDefaultPolicyEvaluator: 
RangerResourceDef is null");
-               }
-
-               if(LOG.isDebugEnabled()) {
-                       LOG.debug("<== 
RangerDefaultPolicyEvaluator.createResourceMatcher(" + resourceDef + ", " + 
resource + "): " + ret);
-               }
-
-               return ret;
-       }
-
        protected boolean isMatch(Map<String, RangerPolicyResource> resources) {
                if(LOG.isDebugEnabled()) {
                        LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + 
resources + ")");
@@ -673,42 +514,8 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                boolean ret = false;
 
-               RangerServiceDef serviceDef = getServiceDef();
-
-               if(serviceDef != null && serviceDef.getResources() != null) {
-                       Collection<String> resourceKeys = resources == null ? 
null : resources.keySet();
-                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
-
-                       boolean keysMatch = 
CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && 
policyKeys.containsAll(resourceKeys));
-
-                       if(keysMatch) {
-                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                                       String                resourceName   = 
resourceDef.getName();
-                                       RangerPolicyResource  resourceValues = 
resources == null ? null : resources.get(resourceName);
-                                       RangerResourceMatcher matcher        = 
matchers == null ? null : matchers.get(resourceName);
-
-                                       // when no value exists for a 
resourceName, consider it a match only if: policy doesn't have a matcher OR 
matcher allows no-value resource
-                                       if(resourceValues == null || 
CollectionUtils.isEmpty(resourceValues.getValues())) {
-                                               ret = matcher == null || 
matcher.isMatch(null);
-                                       } else if(matcher != null) {
-                                               for(String resourceValue : 
resourceValues.getValues()) {
-                                                       ret = 
matcher.isMatch(resourceValue);
-
-                                                       if(! ret) {
-                                                               break;
-                                                       }
-                                               }
-                                       }
-
-                                       if(! ret) {
-                                               break;
-                                       }
-                               }
-                       } else {
-                               if(LOG.isDebugEnabled()) {
-                                       LOG.debug("isMatch(): keysMatch=false. 
resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
-                               }
-                       }
+               if(resourceMatcher != null) {
+                       ret = resourceMatcher.isMatch(resources);
                }
 
                if(LOG.isDebugEnabled()) {
@@ -785,11 +592,9 @@ public class RangerDefaultPolicyEvaluator extends 
RangerAbstractPolicyEvaluator
 
                super.toString(sb);
 
-               sb.append("matchers={");
-               if(matchers != null) {
-                       for(RangerResourceMatcher matcher : matchers.values()) {
-                               sb.append("{").append(matcher).append("} ");
-                       }
+               sb.append("resourceMatcher={");
+               if(resourceMatcher != null) {
+                       resourceMatcher.toString(sb);
                }
                sb.append("} ");
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/776533f9/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
new file mode 100644
index 0000000..a020b68
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java
@@ -0,0 +1,364 @@
+/*
+ * 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.policyresourcematcher;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+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.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher;
+import org.apache.ranger.plugin.resourcematcher.RangerResourceMatcher;
+
+import com.google.common.collect.Sets;
+
+public class RangerDefaultPolicyResourceMatcher implements 
RangerPolicyResourceMatcher {
+       private static final Log LOG = 
LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class);
+
+       protected RangerServiceDef                  serviceDef     = null;
+       protected Map<String, RangerPolicyResource> policyResources = null;
+
+       private Map<String, RangerResourceMatcher> matchers = null;
+
+       @Override
+       public void setServiceDef(RangerServiceDef serviceDef) {
+               this.serviceDef = serviceDef;
+       }
+
+       @Override
+       public void setPolicyResources(Map<String, RangerPolicyResource> 
policyResources) {
+               this.policyResources = policyResources;
+       }
+
+       @Override
+       public void init() {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.init()");
+               }
+
+               this.matchers = new HashMap<String, RangerResourceMatcher>();
+
+               if(policyResources != null && serviceDef != null) {
+                       for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
+                               String               resourceName   = 
resourceDef.getName();
+                               RangerPolicyResource policyResource = 
policyResources.get(resourceName);
+
+                               if(policyResource != null) {
+                                       RangerResourceMatcher matcher = 
createResourceMatcher(resourceDef, policyResource);
+
+                                       if(matcher != null) {
+                                               matchers.put(resourceName, 
matcher);
+                                       } else {
+                                               LOG.error("failed to find 
matcher for resource " + resourceName);
+                                       }
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.init()");
+               }
+       }
+
+       @Override
+       public boolean isMatch(RangerAccessResource resource) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isMatch(" + resource + ")");
+               }
+
+               boolean ret = false;
+
+               if(serviceDef != null && serviceDef.getResources() != null) {
+                       Collection<String> resourceKeys = resource == null ? 
null : resource.getKeys();
+                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
+
+                       boolean keysMatch = 
CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && 
policyKeys.containsAll(resourceKeys));
+
+                       if(keysMatch) {
+                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
+                                       String                resourceName  = 
resourceDef.getName();
+                                       String                resourceValue = 
resource == null ? null : resource.getValue(resourceName);
+                                       RangerResourceMatcher matcher       = 
matchers == null ? null : matchers.get(resourceName);
+
+                                       // when no value exists for a 
resourceName, consider it a match only if: policy doesn't have a matcher OR 
matcher allows no-value resource
+                                       if(StringUtils.isEmpty(resourceValue)) {
+                                               ret = matcher == null || 
matcher.isMatch(resourceValue);
+                                       } else {
+                                               ret = matcher != null && 
matcher.isMatch(resourceValue);
+                                       }
+
+                                       if(! ret) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               if(LOG.isDebugEnabled()) {
+                                       LOG.debug("isMatch(): keysMatch=false. 
isMatch=" + resourceKeys + "; policyKeys=" + policyKeys);
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isMatch(" + resource + "): " + ret);
+               }
+
+               return ret;
+       }
+
+
+       @Override
+       public boolean isMatch(Map<String, RangerPolicyResource> resources) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ")");
+               }
+
+               boolean ret = false;
+
+               if(serviceDef != null && serviceDef.getResources() != null) {
+                       Collection<String> resourceKeys = resources == null ? 
null : resources.keySet();
+                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
+
+                       boolean keysMatch = 
CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && 
policyKeys.containsAll(resourceKeys));
+
+                       if(keysMatch) {
+                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
+                                       String                resourceName   = 
resourceDef.getName();
+                                       RangerPolicyResource  resourceValues = 
resources == null ? null : resources.get(resourceName);
+                                       RangerResourceMatcher matcher        = 
matchers == null ? null : matchers.get(resourceName);
+
+                                       // when no value exists for a 
resourceName, consider it a match only if: policy doesn't have a matcher OR 
matcher allows no-value resource
+                                       if(resourceValues == null || 
CollectionUtils.isEmpty(resourceValues.getValues())) {
+                                               ret = matcher == null || 
matcher.isMatch(null);
+                                       } else if(matcher != null) {
+                                               for(String resourceValue : 
resourceValues.getValues()) {
+                                                       ret = 
matcher.isMatch(resourceValue);
+
+                                                       if(! ret) {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       if(! ret) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               if(LOG.isDebugEnabled()) {
+                                       LOG.debug("isMatch(): keysMatch=false. 
resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isMatch(" + resources + "): " + ret);
+               }
+
+               return ret;
+       }
+
+       @Override
+       public boolean isSingleAndExactMatch(RangerAccessResource resource) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.isSingleAndExactMatch(" + resource + ")");
+               }
+
+               boolean ret = false;
+
+               if(serviceDef != null && serviceDef.getResources() != null) {
+                       Collection<String> resourceKeys = resource == null ? 
null : resource.getKeys();
+                       Collection<String> policyKeys   = matchers == null ? 
null : matchers.keySet();
+
+                       boolean keysMatch = false;
+
+                       if (resourceKeys != null && policyKeys != null) {
+                               keysMatch = 
CollectionUtils.isEqualCollection(resourceKeys, policyKeys);
+                       }
+
+                       if(keysMatch) {
+                               for(RangerResourceDef resourceDef : 
serviceDef.getResources()) {
+                                       String                resourceName  = 
resourceDef.getName();
+                                       String                resourceValue = 
resource == null ? null : resource.getValue(resourceName);
+                                       RangerResourceMatcher matcher       = 
matchers == null ? null : matchers.get(resourceName);
+
+                                       if(StringUtils.isEmpty(resourceValue)) {
+                                               ret = matcher == null || 
matcher.isSingleAndExactMatch(resourceValue);
+                                       } else {
+                                               ret = matcher != null && 
matcher.isSingleAndExactMatch(resourceValue);
+                                       }
+
+                                       if(! ret) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               if(LOG.isDebugEnabled()) {
+                                       LOG.debug("isSingleAndExactMatch(): 
keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys);
+                               }
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.isSingleAndExactMatch(" + resource + "): " + 
ret);
+               }
+
+               return ret;
+       }
+
+       @Override
+       public boolean isHeadMatch(RangerAccessResource resource) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + ")");
+               }
+               boolean ret; 
+               
+               if (resource == null || 
CollectionUtils.isEmpty(resource.getKeys())) { // sanity-check, firewalling
+                       LOG.debug("isHeadMatch: resource was null/empty!");
+                       ret = true; // null resource matches anything
+               } else if (serviceDef == null) { // sanity-check, firewalling
+                       LOG.debug("isHeadMatch: service-def was null!");
+                       ret = false; // null policy can never match a non-empty 
resource 
+               } else if (policyResources == null) {
+                       LOG.debug("isHeadMatch: policyResources were null!");
+                       ret = false; // null policy can never match a non-empty 
resource 
+               } else if (matchers == null || matchers.size() != 
policyResources.size()) { // sanity-check, firewalling
+                       LOG.debug("isHeadMatch: matchers could be found for 
some of the policy resources");
+                       ret = false; // empty policy can never match a 
non-empty resources and can't be evaluated meaningfully in matchers are absent
+               } else {
+                       if (!Sets.difference(resource.getKeys(), 
matchers.keySet()).isEmpty()) { // e.g. avoid using udf policy for resource 
that has more than db specified and vice-versa
+                               LOG.debug("isHeadMatch: resource/policy 
resource-keys mismatch. policy is incompatible with resource; can't match.");
+                               ret = false;
+                       } else {
+                               Set<String> policyResourceNames = 
matchers.keySet();
+                               boolean skipped = false;
+                               boolean matched = true;
+                               Iterator<RangerResourceDef> iterator = 
serviceDef.getResources().iterator();
+                               while (iterator.hasNext() && matched) {
+                                       RangerResourceDef resourceDef = 
iterator.next();
+                                       String resourceName = 
resourceDef.getName();
+                                       // we only work with resources that are 
relevant to this policy
+                                       if 
(policyResourceNames.contains(resourceName)) {
+                                               String resourceValue = 
resource.getValue(resourceName);
+                                               if 
(StringUtils.isEmpty(resourceValue)) {
+                                                       if 
(LOG.isDebugEnabled()) {
+                                                               
LOG.debug("Skipping matching for " + resourceName + " since it is null/empty on 
resource");
+                                                       }
+                                                       skipped = true; // once 
we skip a level all lower levels must be skippable, too
+                                               } else if (skipped == true) {
+                                                       LOG.debug("isHeadMatch: 
found a lower level resource when a higer level resource was absent!");
+                                                       matched = false;
+                                               } else if 
(!matchers.get(resourceName).isMatch(resourceValue)) {
+                                                       if 
(LOG.isDebugEnabled()) {
+                                                               
LOG.debug("isHeadMatch: matcher for " + resourceName + " failed");
+                                                       }
+                                                       matched = false;
+                                               }
+                                       }
+                               }
+                               ret = matched;
+                       }
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.matchResourceHead(" + resource + "): " + 
ret);
+               }
+
+               return ret;
+       }
+
+       @Override
+       public String toString() {
+               StringBuilder sb = new StringBuilder();
+
+               toString(sb);
+
+               return sb.toString();
+       }
+
+       @Override
+       public StringBuilder toString(StringBuilder sb) {
+               sb.append("RangerDefaultPolicyResourceMatcher={");
+
+               sb.append("matchers={");
+               if(matchers != null) {
+                       for(RangerResourceMatcher matcher : matchers.values()) {
+                               sb.append("{").append(matcher).append("} ");
+                       }
+               }
+               sb.append("} ");
+
+               sb.append("}");
+
+               return sb;
+       }
+
+       protected static RangerResourceMatcher 
createResourceMatcher(RangerResourceDef resourceDef, RangerPolicyResource 
resource) {
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + ")");
+               }
+
+               RangerResourceMatcher ret = null;
+
+               if (resourceDef != null) {
+                       String resName = resourceDef.getName();
+                       String clsName = resourceDef.getMatcher();
+
+                       if (!StringUtils.isEmpty(clsName)) {
+                               try {
+                                       @SuppressWarnings("unchecked")
+                                       Class<RangerResourceMatcher> 
matcherClass = (Class<RangerResourceMatcher>) Class.forName(clsName);
+
+                                       ret = matcherClass.newInstance();
+                               } catch (Exception excp) {
+                                       LOG.error("failed to instantiate 
resource matcher '" + clsName + "' for '" + resName + "'. Default resource 
matcher will be used", excp);
+                               }
+                       }
+
+
+                       if (ret == null) {
+                               ret = new RangerDefaultResourceMatcher();
+                       }
+
+                       if (ret != null) {
+                               ret.setResourceDef(resourceDef);
+                               ret.setPolicyResource(resource);
+                               ret.init();
+                       }
+               } else {
+                       LOG.error("RangerDefaultPolicyResourceMatcher: 
RangerResourceDef is null");
+               }
+
+               if(LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " 
+ resource + "): " + ret);
+               }
+
+               return ret;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/776533f9/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
----------------------------------------------------------------------
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
new file mode 100644
index 0000000..4a613a2
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java
@@ -0,0 +1,44 @@
+/*
+ * 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.policyresourcematcher;
+
+import java.util.Map;
+
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+
+public interface RangerPolicyResourceMatcher {
+       void setServiceDef(RangerServiceDef serviceDef);
+
+       void setPolicyResources(Map<String, RangerPolicyResource> 
policyResources);
+
+       void init();
+
+       boolean isMatch(RangerAccessResource resource);
+
+       boolean isMatch(Map<String, RangerPolicyResource> resources);
+
+       boolean isSingleAndExactMatch(RangerAccessResource resource);
+
+       boolean isHeadMatch(RangerAccessResource resource);
+
+       StringBuilder toString(StringBuilder sb);
+}

Reply via email to