You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2015/05/04 23:00:25 UTC

incubator-ranger git commit: RANGER-359 Store policy resource signature in database and use stored value to check for duplicates

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 73b22d3eb -> 5ac7c52ad


RANGER-359 Store policy resource signature in database and use stored value to check for duplicates

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


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

Branch: refs/heads/master
Commit: 5ac7c52ad1b9f4d68cd2226e29af412c127d5c53
Parents: 73b22d3
Author: Alok Lal <al...@hortonworks.com>
Authored: Fri May 1 17:47:40 2015 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Mon May 4 13:50:16 2015 -0700

----------------------------------------------------------------------
 .../model/RangerPolicyResourceSignature.java    | 161 +++++++++++++
 .../RangerPolicyResourceSignature.java          | 162 -------------
 .../model/validation/RangerPolicyValidator.java |  53 ++---
 .../model/validation/RangerValidator.java       |  19 ++
 .../plugin/store/AbstractServiceStore.java      |  49 +++-
 .../ranger/plugin/store/ServiceStore.java       |   2 +
 .../plugin/store/file/ServiceFileStore.java     |  17 ++
 .../plugin/store/rest/ServiceRESTStore.java     |   5 +
 .../ranger/plugin/util/RangerObjectFactory.java |   2 +-
 .../apache/ranger/plugin/util/SearchFilter.java |  24 ++
 .../TestRangerPolicyResourceSignature.java      | 234 +++++++++++++++++++
 .../TestRangerPolicyResourceSignature.java      | 232 ------------------
 .../validation/TestRangerPolicyValidator.java   |  76 +++---
 .../model/validation/TestRangerValidator.java   |  22 +-
 .../model/validation/ValidationTestUtils.java   |   2 +-
 .../org/apache/ranger/biz/ServiceDBStore.java   |  40 +++-
 .../apache/ranger/service/RangerFactory.java    |  33 +++
 17 files changed, 653 insertions(+), 480 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
new file mode 100644
index 0000000..62fdabc
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPolicyResourceSignature.java
@@ -0,0 +1,161 @@
+/*
+ * 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.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+
+public class RangerPolicyResourceSignature {
+
+	private static final Log LOG = LogFactory.getLog(RangerPolicyResourceSignature.class);
+	static final RangerPolicyResourceSignature _EmptyResourceSignature = new RangerPolicyResourceSignature((RangerPolicy)null);
+	
+	private final String _string;
+	private final String _hash;
+	private final RangerPolicy _policy;
+
+	public RangerPolicyResourceSignature(RangerPolicy policy) {
+		_policy = policy;
+		String asString = getResourceString(_policy);
+		if (asString == null) {
+			_string = "";
+		} else {
+			_string = asString;
+		}
+		_hash = DigestUtils.md5Hex(_string);
+	}
+
+	/**
+	 * Only added for testability.  Do not make public
+	 * @param string
+	 */
+	RangerPolicyResourceSignature(String string) {
+		_policy = null;
+		if (string == null) {
+			_string = "";
+		} else {
+			_string = string;
+		}
+		_hash = DigestUtils.md5Hex(_string);
+	}
+	
+	String asString() {
+		return _string;
+	}
+
+	public String getSignature() {
+		return _hash;
+	}
+	
+	@Override
+	public int hashCode() {
+		// we assume no collision
+		return Objects.hashCode(_hash);
+	}
+	
+	@Override
+	public boolean equals(Object object) {
+		if (object == null || !(object instanceof RangerPolicyResourceSignature)) {
+			return false;
+		}
+		RangerPolicyResourceSignature that = (RangerPolicyResourceSignature)object;
+		return Objects.equals(this._hash, that._hash);
+	}
+	
+	@Override
+	public String toString() {
+		return String.format("%s: %s", _hash, _string);
+	}
+
+	String getResourceString(RangerPolicy policy) {
+		// invalid/empty policy gets a deterministic signature as if it had an
+		// empty resource string
+		if (!isPolicyValidForResourceSignatureComputation(policy)) {
+			return null;
+		}
+		Map<String, RangerPolicyResourceView> resources = new TreeMap<String, RangerPolicyResourceView>();
+		for (Map.Entry<String, RangerPolicyResource> entry : policy.getResources().entrySet()) {
+			String resourceName = entry.getKey();
+			RangerPolicyResourceView resourceView = new RangerPolicyResourceView(entry.getValue());
+			resources.put(resourceName, resourceView);
+		}
+		String result = resources.toString();
+		return result;
+	}
+
+	boolean isPolicyValidForResourceSignatureComputation(RangerPolicy policy) {
+		boolean valid = false;
+		if (policy == null) {
+			LOG.debug("isPolicyValidForResourceSignatureComputation: policy was null!");
+		} else if (policy.getResources() == null) {
+			LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection on policy was null!");
+		} else if (policy.getResources().containsKey(null)) {
+			LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection has resource with null name!");
+		} else {
+			valid = true;
+		}
+		return valid;
+	}
+
+	static class RangerPolicyResourceView {
+		final RangerPolicyResource _policyResource;
+
+		RangerPolicyResourceView(RangerPolicyResource policyResource) {
+			_policyResource = policyResource;
+		}
+
+		@Override
+		public String toString() {
+			StringBuilder builder = new StringBuilder();
+			builder.append("{");
+			if (_policyResource != null) {
+				builder.append("values=");
+				if (_policyResource.getValues() != null) {
+					List<String> values = new ArrayList<String>(_policyResource.getValues());
+					Collections.sort(values);
+					builder.append(values);
+				}
+				builder.append(",excludes=");
+				if (_policyResource.getIsExcludes() == null) { // null is same as false
+					builder.append(Boolean.FALSE);
+				} else {
+					builder.append(_policyResource.getIsExcludes());
+				}
+				builder.append(",recursive=");
+				if (_policyResource.getIsRecursive() == null) { // null is the same as false
+					builder.append(Boolean.FALSE);
+				} else {
+					builder.append(_policyResource.getIsRecursive());
+				}
+			}
+			builder.append("}");
+			return builder.toString();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyResourceSignature.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyResourceSignature.java
deleted file mode 100644
index 9b21dc9..0000000
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyResourceSignature.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.model.validation;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
-
-import org.apache.commons.codec.digest.DigestUtils;
-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.RangerPolicy.RangerPolicyResource;
-
-public class RangerPolicyResourceSignature {
-
-	private static final Log LOG = LogFactory.getLog(RangerPolicyResourceSignature.class);
-	static final RangerPolicyResourceSignature _EmptyResourceSignature = new RangerPolicyResourceSignature((RangerPolicy)null);
-	
-	private final String _string;
-	private final String _hash;
-	private final RangerPolicy _policy;
-
-	public RangerPolicyResourceSignature(RangerPolicy policy) {
-		_policy = policy;
-		String asString = getResourceString(_policy);
-		if (asString == null) {
-			_string = "";
-		} else {
-			_string = asString;
-		}
-		_hash = DigestUtils.md5Hex(_string);
-	}
-
-	/**
-	 * Only added for testability.  Do not make public
-	 * @param string
-	 */
-	RangerPolicyResourceSignature(String string) {
-		_policy = null;
-		if (string == null) {
-			_string = "";
-		} else {
-			_string = string;
-		}
-		_hash = DigestUtils.md5Hex(_string);
-	}
-	
-	public String asString() {
-		return _string;
-	}
-
-	public String asHashHex() {
-		return _hash;
-	}
-	
-	@Override
-	public int hashCode() {
-		// we assume no collision
-		return Objects.hashCode(_hash);
-	}
-	
-	@Override
-	public boolean equals(Object object) {
-		if (object == null || !(object instanceof RangerPolicyResourceSignature)) {
-			return false;
-		}
-		RangerPolicyResourceSignature that = (RangerPolicyResourceSignature)object;
-		return Objects.equals(this._hash, that._hash);
-	}
-	
-	@Override
-	public String toString() {
-		return String.format("%s: %s", _hash, _string);
-	}
-
-	String getResourceString(RangerPolicy policy) {
-		// invalid/empty policy gets a deterministic signature as if it had an
-		// empty resource string
-		if (!isPolicyValidForResourceSignatureComputation(policy)) {
-			return null;
-		}
-		Map<String, RangerPolicyResourceView> resources = new TreeMap<String, RangerPolicyResourceView>();
-		for (Map.Entry<String, RangerPolicyResource> entry : policy.getResources().entrySet()) {
-			String resourceName = entry.getKey();
-			RangerPolicyResourceView resourceView = new RangerPolicyResourceView(entry.getValue());
-			resources.put(resourceName, resourceView);
-		}
-		String result = resources.toString();
-		return result;
-	}
-
-	boolean isPolicyValidForResourceSignatureComputation(RangerPolicy policy) {
-		boolean valid = false;
-		if (policy == null) {
-			LOG.debug("isPolicyValidForResourceSignatureComputation: policy was null!");
-		} else if (policy.getResources() == null) {
-			LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection on policy was null!");
-		} else if (policy.getResources().containsKey(null)) {
-			LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection has resource with null name!");
-		} else {
-			valid = true;
-		}
-		return valid;
-	}
-
-	static class RangerPolicyResourceView {
-		final RangerPolicyResource _policyResource;
-
-		RangerPolicyResourceView(RangerPolicyResource policyResource) {
-			_policyResource = policyResource;
-		}
-
-		@Override
-		public String toString() {
-			StringBuilder builder = new StringBuilder();
-			builder.append("{");
-			if (_policyResource != null) {
-				builder.append("values=");
-				if (_policyResource.getValues() != null) {
-					List<String> values = new ArrayList<String>(_policyResource.getValues());
-					Collections.sort(values);
-					builder.append(values);
-				}
-				builder.append(",excludes=");
-				if (_policyResource.getIsExcludes() == null) { // null is same as false
-					builder.append(Boolean.FALSE);
-				} else {
-					builder.append(_policyResource.getIsExcludes());
-				}
-				builder.append(",recursive=");
-				if (_policyResource.getIsRecursive() == null) { // null is the same as false
-					builder.append(Boolean.FALSE);
-				} else {
-					builder.append(_policyResource.getIsRecursive());
-				}
-			}
-			builder.append("}");
-			return builder.toString();
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
index a76e970..0092aaf 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerPolicyValidator.java
@@ -33,6 +33,7 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
@@ -240,13 +241,13 @@ public class RangerPolicyValidator extends RangerValidator {
 		
 		boolean valid = true;
 		Map<String, RangerPolicyResource> resourceMap = policy.getResources();
-		if (serviceDef != null && resourceMap != null) { // following checks can't be done meaningfully otherwise
-			valid = isValidResourceNames(policy, failures, serviceDef) && valid;
-			valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
-			valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDef.getName(), policy.getName(), isAdmin) && valid;
-		}
-		if (StringUtils.isNotBlank(serviceName)) { // resource uniqueness check cannot be done meaningfully otherwise
-			valid = isPolicyResourceUnique(policy, failures, action, serviceName) && valid;
+		if (resourceMap != null) { // following checks can't be done meaningfully otherwise
+			valid = isPolicyResourceUnique(policy, failures) && valid;
+			if (serviceDef != null) { // following checks can't be done meaningfully otherwise
+				valid = isValidResourceNames(policy, failures, serviceDef) && valid;
+				valid = isValidResourceValues(resourceMap, failures, serviceDef) && valid;
+				valid = isValidResourceFlags(resourceMap, failures, serviceDef.getResources(), serviceDef.getName(), policy.getName(), isAdmin) && valid;
+			}
 		}
 
 		if(LOG.isDebugEnabled()) {
@@ -255,38 +256,28 @@ public class RangerPolicyValidator extends RangerValidator {
 		return valid;
 	}
 	
-	boolean isPolicyResourceUnique(RangerPolicy policy, final List<ValidationFailureDetails> failures, Action action, final String serviceName) {
+	boolean isPolicyResourceUnique(RangerPolicy policy, final List<ValidationFailureDetails> failures) {
 		
 		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("==> RangerPolicyValidator.isPolicyResourceUnique(%s, %s, %s, %s)", policy, failures, action, serviceName));
+			LOG.debug(String.format("==> RangerPolicyValidator.isPolicyResourceUnique(%s, %s)", policy, failures));
 		}
 
-		boolean foundDuplicate = false;
-		RangerPolicyResourceSignature signature = _factory.createPolicyResourceSignature(policy);
-		List<RangerPolicy> policies = getPolicies(serviceName, null);
+		boolean valid = true;
+		RangerPolicyResourceSignature policySignature = _factory.createPolicyResourceSignature(policy);
+		String signature = policySignature.getSignature();
+		List<RangerPolicy> policies = getPoliciesForResourceSignature(signature);
 		if (CollectionUtils.isNotEmpty(policies)) {
-			Iterator<RangerPolicy> iterator = policies.iterator();
-			while (iterator.hasNext() && !foundDuplicate) {
-				RangerPolicy otherPolicy = iterator.next();
-				if (otherPolicy.getId().equals(policy.getId()) && action == Action.UPDATE) {
-					LOG.debug("isPolicyResourceUnique: Skipping self during update!");
-				} else {
-					RangerPolicyResourceSignature otherSignature = _factory.createPolicyResourceSignature(otherPolicy);
-					if (signature.equals(otherSignature)) {
-						foundDuplicate = true;
-						failures.add(new ValidationFailureDetailsBuilder()
-							.field("resources")
-							.isSemanticallyIncorrect()
-							.becauseOf("found another policy[" + otherPolicy.getName() + "] with matching resources[" + otherPolicy.getResources() + "]!")
-							.build());
-					}
-				}
-			}
+			RangerPolicy otherPolicy = policies.iterator().next();
+			valid = false;
+			failures.add(new ValidationFailureDetailsBuilder()
+				.field("resources")
+				.isSemanticallyIncorrect()
+				.becauseOf("found another policy[" + otherPolicy.getName() + "] with matching resources[" + otherPolicy.getResources() + "]!")
+				.build());
 		}
 
-		boolean valid = !foundDuplicate;
 		if(LOG.isDebugEnabled()) {
-			LOG.debug(String.format("<== RangerPolicyValidator.isPolicyResourceUnique(%s, %s, %s, %s): %s", policy, failures, action, serviceName, valid));
+			LOG.debug(String.format("<== RangerPolicyValidator.isPolicyResourceUnique(%s, %s): %s", policy, failures, valid));
 		}
 		return valid;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
index 492949b..bc4c7f1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerValidator.java
@@ -268,6 +268,25 @@ public abstract class RangerValidator {
 		}
 		return policies;
 	}
+	
+	List<RangerPolicy> getPoliciesForResourceSignature(String hexSignature) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerValidator.getPolicies(" + hexSignature + ")");
+		}
+
+		List<RangerPolicy> policies = null;
+		try {
+			policies = _store.getPoliciesByResourceSignature(hexSignature);
+		} catch (Exception e) {
+			LOG.debug("Encountred exception while retrieving policies from service store!", e);
+		}
+		
+		if(LOG.isDebugEnabled()) {
+			int count = policies == null ? 0 : policies.size();
+			LOG.debug("<== RangerValidator.getPolicies(" + hexSignature + "): count[" + count + "], " + policies);
+		}
+		return policies;
+	}
 
 	Set<String> getAccessTypes(RangerServiceDef serviceDef) {
 		if(LOG.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractServiceStore.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractServiceStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractServiceStore.java
index ee480fa..2ce08bb 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractServiceStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/AbstractServiceStore.java
@@ -36,10 +36,10 @@ import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.plugin.model.RangerBaseModelObject;
 import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerService;
-import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerService;
+import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.util.SearchFilter;
 
@@ -81,6 +81,7 @@ public abstract class AbstractServiceStore implements ServiceStore {
 		addPredicateForIsRecursive(filter.getParam(SearchFilter.IS_RECURSIVE), predicates);
 		addPredicateForUserName(filter.getParam(SearchFilter.USER), predicates);
 		addPredicateForGroupName(filter.getParam(SearchFilter.GROUP), predicates);
+		addPredicateForResourceSignature(filter.getParam(SearchFilter.RESOURCE_SIGNATURE), predicates);
 		addPredicateForResources(filter.getParamsWithPrefix(SearchFilter.RESOURCE_PREFIX, true), predicates);
 
 		Predicate ret = CollectionUtils.isEmpty(predicates) ? null : PredicateUtils.allPredicate(predicates);
@@ -683,4 +684,48 @@ public abstract class AbstractServiceStore implements ServiceStore {
 
 		return ret;
 	}
+
+	private Predicate addPredicateForResourceSignature(final String hexSignature, List<Predicate> predicates) {
+
+		Predicate ret = createPredicateForResourceSignature(hexSignature);
+
+		if(predicates != null && ret != null) {
+			predicates.add(ret);
+		}
+
+		return ret;
+	}
+
+	/**
+	 * NOTE: Null or empty hexSignature, though invalid, is supported in search.
+	 * @param hexSignature
+	 * @return
+	 */
+	public Predicate createPredicateForResourceSignature(final String hexSignature) {
+
+		if(StringUtils.isEmpty(hexSignature)) {
+			return null;
+		}
+
+		return new Predicate() {
+			@Override
+			public boolean evaluate(Object object) {
+				if(object == null) {
+					return false;
+				}
+
+				boolean ret = false;
+
+				if (object instanceof RangerPolicy) {
+					RangerPolicy policy = (RangerPolicy)object;
+
+					ret = StringUtils.equals(hexSignature, policy.getResourceSignature());
+				} else {
+					ret = true;
+				}
+
+				return ret;
+			}
+		};
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
index e8d970c..708fbd2 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
@@ -66,6 +66,8 @@ public interface ServiceStore {
 
 	List<RangerPolicy> getPolicies(SearchFilter filter) throws Exception;
 
+	List<RangerPolicy> getPoliciesByResourceSignature(String hexSignature) throws Exception;
+
 	List<RangerPolicy> getServicePolicies(Long serviceId, SearchFilter filter) throws Exception;
 
 	List<RangerPolicy> getServicePolicies(String serviceName, SearchFilter filter) throws Exception;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/store/file/ServiceFileStore.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/file/ServiceFileStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/file/ServiceFileStore.java
index b90de22..00b7521 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/file/ServiceFileStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/file/ServiceFileStore.java
@@ -615,6 +615,23 @@ public class ServiceFileStore extends BaseFileStore {
 	}
 
 	@Override
+	public List<RangerPolicy> getPoliciesByResourceSignature(String hexSignature) throws Exception {
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("==> ServiceFileStore.getPolicies()");
+		}
+
+		List<RangerPolicy> ret = getAllPolicies();
+
+		CollectionUtils.filter(ret, createPredicateForResourceSignature(hexSignature));
+
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("<== ServiceFileStore.getPolicies(): count=" + (ret == null ? 0 : ret.size()));
+		}
+
+		return ret;
+	}
+
+	@Override
 	public List<RangerPolicy> getPolicies(SearchFilter filter) throws Exception {
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("==> ServiceFileStore.getPolicies()");

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
index ca8024f..5c742f9 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/rest/ServiceRESTStore.java
@@ -612,4 +612,9 @@ public class ServiceRESTStore implements ServiceStore {
 
 		return ret;
 	}
+
+	@Override
+	public List<RangerPolicy> getPoliciesByResourceSignature(String hexSignature) throws Exception {
+		throw new UnsupportedOperationException("Querying policies by resource signature is not supported!");
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerObjectFactory.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerObjectFactory.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerObjectFactory.java
index 0faa20d..72f0fd5 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerObjectFactory.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerObjectFactory.java
@@ -20,7 +20,7 @@
 package org.apache.ranger.plugin.util;
 
 import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.validation.RangerPolicyResourceSignature;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
 
 public class RangerObjectFactory {
 	public RangerPolicyResourceSignature createPolicyResourceSignature(RangerPolicy policy) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
index dac8a8e..17738be 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java
@@ -46,6 +46,7 @@ public class SearchFilter {
 	public static final String START_INDEX     = "startIndex";
 	public static final String PAGE_SIZE       = "pageSize";
 	public static final String SORT_BY         = "sortBy";
+	public static final String RESOURCE_SIGNATURE = "resourceSignature:";     // search
 
 	private Map<String, String> params     = null;
 	private int                 startIndex = 0;
@@ -175,4 +176,27 @@ public class SearchFilter {
 	public int hashCode() {
 		return Objects.hash(params);
 	}
+	
+	@Override
+	public String toString( ) {
+		StringBuilder sb = new StringBuilder();
+
+		toString(sb);
+
+		return sb.toString();
+	}
+
+	public StringBuilder toString(StringBuilder sb) {
+		sb.append("SearchFilter={");
+
+		sb.append("getCount={").append(getCount).append("} ");
+		sb.append("maxRows={").append(maxRows).append("} ");
+		sb.append("params={").append(params).append("} ");
+		sb.append("sortBy={").append(sortBy).append("} ");
+		sb.append("sortType={").append(sortType).append("} ");
+		sb.append("startIndex={").append(startIndex).append("} ");
+		sb.append("}");
+
+		return sb;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
new file mode 100644
index 0000000..46e924f
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/TestRangerPolicyResourceSignature.java
@@ -0,0 +1,234 @@
+/*
+ * 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.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature.RangerPolicyResourceView;
+import org.apache.ranger.plugin.model.validation.ValidationTestUtils;
+import org.junit.Test;
+
+public class TestRangerPolicyResourceSignature {
+
+	@Test
+	public void test_RangerPolicyResourceView_toString() {
+		// null resource
+		RangerPolicyResource policyResource = null;
+		RangerPolicyResourceView policyResourceView = new RangerPolicyResourceView(policyResource);
+		assertEquals("{}", policyResourceView.toString());
+		
+		// non-null policy resource with null values/recursive flag
+		policyResource = createPolicyResource(null, null, null);
+		policyResourceView = new RangerPolicyResourceView(policyResource);
+		assertEquals("{values=,excludes=false,recursive=false}", policyResourceView.toString());
+		
+		// valid values in non-asending order
+		policyResource = createPolicyResource(new String[]{"b", "a", "d", "c"}, true, false);
+		policyResourceView = new RangerPolicyResourceView(policyResource);
+		assertEquals("{values=[a, b, c, d],excludes=false,recursive=true}", policyResourceView.toString());
+		
+		// recursive flag is false and different variation of values to show lexicographic ordering
+		policyResource = createPolicyResource(new String[]{"9", "A", "e", "_"}, false, true);
+		policyResourceView = new RangerPolicyResourceView(policyResource);
+		assertEquals("{values=[9, A, _, e],excludes=true,recursive=false}", policyResourceView.toString());
+	}
+	
+	RangerPolicyResource createPolicyResource(String[] values, Boolean recursive, Boolean excludes) {
+		
+		RangerPolicyResource resource = mock(RangerPolicyResource.class);
+		if (values == null) {
+			when(resource.getValues()).thenReturn(null);
+		} else {
+			when(resource.getValues()).thenReturn(Arrays.asList(values));
+		}
+		when(resource.getIsRecursive()).thenReturn(recursive);
+		when(resource.getIsExcludes()).thenReturn(excludes);
+		
+		return resource;
+	}
+
+	@Test
+	public void test_isPolicyValidForResourceSignatureComputation() {
+		// null policy is invalid
+		RangerPolicyResourceSignature utils = new RangerPolicyResourceSignature((String)null);
+		RangerPolicy rangerPolicy = null;
+		assertFalse("policy==null", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
+
+		// null resource map is invalid
+		rangerPolicy = mock(RangerPolicy.class);
+		when(rangerPolicy.getResources()).thenReturn(null);
+		assertFalse("policy.getResources()==null", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
+		
+		// empty resources map is ok!
+		Map<String, RangerPolicyResource> policyResources = new HashMap<String, RangerPolicyResource>();
+		when(rangerPolicy.getResources()).thenReturn(policyResources);
+		assertTrue("policy.getResources().isEmpty()", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
+		
+		// but having a resource map with null key is not ok!
+		RangerPolicyResource aPolicyResource = mock(RangerPolicyResource.class);
+		policyResources.put(null, aPolicyResource);
+		assertFalse("policy.getResources().contains(null)", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
+	}
+	
+	@Test
+	public void test_RangerPolicyResourceSignature() {
+		// String rep of a null policy is an empty string! and its hash is sha of empty string!
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
+		assertEquals("", signature.asString());
+		assertEquals(DigestUtils.md5Hex(""), signature.getSignature());
+	}
+
+	/*
+	 * Format of data expected by the utility function which uses this is:
+	 * { "resource-name", "values" "isExcludes", "isRecursive" }
+	 */
+	Object[][] first = new Object[][] {
+			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
+			{ "db",    new String[] { "db1", "db2"},           false, null},
+			{ "col",   new String[] { "col2", "col1", "col3"}, null,  true},
+	};
+
+	Object[][] first_recursive_null_or_false = new Object[][] {
+			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  null}, // recursive flag is false in first
+			{ "db",    new String[] { "db1", "db2"},           false, null},
+			{ "col",   new String[] { "col2", "col1", "col3"}, null,  true},
+	};
+
+	Object[][] first_recursive_flag_different = new Object[][] {
+			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
+			{ "db",    new String[] { "db1", "db2"},           false, null},
+			{ "col",   new String[] { "col2", "col1", "col3"}, null,  false}, // recursive flag is true in first
+	};
+
+	Object[][] first_excludes_null_or_false = new Object[][] {
+			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
+			{ "db",    new String[] { "db1", "db2"},           false, null}, // excludes flag is null in first
+			{ "col",   new String[] { "col2", "col1", "col3"}, false, true},
+	};
+
+	Object[][] first_excludes_flag_different = new Object[][] {
+			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
+			{ "db",    new String[] { "db1", "db2"},           false, null},
+			{ "col",   new String[] { "col2", "col1", "col3"}, true,  true}, // excludes flag is false in first
+	};
+
+	Object[][] data_second = new Object[][] {
+			{ "db",    new String[] { "db2", "db1"},           false, null},
+			{ "table", new String[] { "tbl2", "tbl3", "tbl1"}, true, false},
+			{ "col",   new String[] { "col1", "col3", "col2"}, null, true},
+	};
+
+	@Test
+	public void test_getResourceSignature_happyPath() {
+		// null policy returns signature of empty resource
+		RangerPolicy policy = null;
+		RangerPolicyResourceSignature sig = new RangerPolicyResourceSignature(policy);
+		assertEquals(null, sig.getResourceString(policy));
+		
+		policy = mock(RangerPolicy.class);
+		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(first);
+		when(policy.getResources()).thenReturn(policyResources);
+		String expected = "{" +
+			"col={values=[col1, col2, col3],excludes=false,recursive=true}, " + 
+			"db={values=[db1, db2],excludes=false,recursive=false}, " +
+			"table={values=[tbl1, tbl2, tbl3],excludes=true,recursive=false}" +
+		"}"; 
+		assertEquals(expected, sig.getResourceString(policy));
+
+		// order of values should not matter
+		policyResources = _utils.createPolicyResourceMap(data_second);
+		when(policy.getResources()).thenReturn(policyResources);
+		assertEquals(expected, sig.getResourceString(policy));
+	}
+	
+	
+	@Test
+	public void test_nullRecursiveFlagIsSameAsFlase() {
+		// create two policies with resources that differ only in the recursive flag such that flags are null in one and false in another
+		RangerPolicy policy1 = createPolicy(first);
+		RangerPolicy policy2 = createPolicy(first_recursive_null_or_false);
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
+		assertEquals("null is same as false", signature.getResourceString(policy1), signature.getResourceString(policy2));
+	}
+	
+	@Test
+	public void test_onlyDifferByRecursiveFlag() {
+		// create two policies with resources that differ only in the recursive flag, i.e. null/false in one and true in another
+		RangerPolicy policy1 = createPolicy(first);
+		RangerPolicy policy2 = createPolicy(first_recursive_flag_different);
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
+		assertFalse("Resources differ only by recursive flag true vs false/null", signature.getResourceString(policy1).equals(signature.getResourceString(policy2)));
+	}
+	
+	@Test
+	public void test_nullExcludesFlagIsSameAsFlase() {
+		// create two policies with resources that differ only in the excludes flag such that flags are null in one and false in another
+		RangerPolicy policy1 = createPolicy(first);
+		RangerPolicy policy2 = createPolicy(first_excludes_null_or_false);
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
+		assertEquals("null is same as false", signature.getResourceString(policy1), signature.getResourceString(policy2));
+	}
+	
+	@Test
+	public void test_onlyDifferByExcludesFlag() {
+		// create two policies with resources that differ only in the excludes flag, i.e. null/false in one and true in another
+		RangerPolicy policy1 = createPolicy(first);
+		RangerPolicy policy2 = createPolicy(first_excludes_flag_different);
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
+		assertFalse("Resources differ only by recursive flag true vs false/null", signature.getResourceString(policy1).equals(signature.getResourceString(policy2)));
+	}
+	
+	RangerPolicy createPolicy(Object[][] data) {
+		RangerPolicy policy = mock(RangerPolicy.class);
+		Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(data);
+		when(policy.getResources()).thenReturn(resources);
+		return policy;
+	}
+
+	@Test
+	public void test_integration() {
+		// setup two policies with resources that are structurally different but semantically the same.
+		RangerPolicy aPolicy = mock(RangerPolicy.class);
+		Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(first);
+		when(aPolicy.getResources()).thenReturn(resources);
+		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature(aPolicy);
+		
+		RangerPolicy anotherPolicy = mock(RangerPolicy.class);
+		resources = _utils.createPolicyResourceMap(data_second);
+		when(anotherPolicy.getResources()).thenReturn(resources);
+		RangerPolicyResourceSignature anotherSignature = new RangerPolicyResourceSignature(anotherPolicy);
+		assertTrue(signature.equals(anotherSignature));
+		assertTrue(anotherSignature.equals(signature));
+	}
+	
+	ValidationTestUtils _utils = new ValidationTestUtils();
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyResourceSignature.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyResourceSignature.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyResourceSignature.java
deleted file mode 100644
index a8b03ce..0000000
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyResourceSignature.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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.model.validation;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.ranger.plugin.model.RangerPolicy;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
-import org.apache.ranger.plugin.model.validation.RangerPolicyResourceSignature.RangerPolicyResourceView;
-import org.junit.Test;
-
-public class TestRangerPolicyResourceSignature {
-
-	@Test
-	public void test_RangerPolicyResourceView_toString() {
-		// null resource
-		RangerPolicyResource policyResource = null;
-		RangerPolicyResourceView policyResourceView = new RangerPolicyResourceView(policyResource);
-		assertEquals("{}", policyResourceView.toString());
-		
-		// non-null policy resource with null values/recursive flag
-		policyResource = createPolicyResource(null, null, null);
-		policyResourceView = new RangerPolicyResourceView(policyResource);
-		assertEquals("{values=,excludes=false,recursive=false}", policyResourceView.toString());
-		
-		// valid values in non-asending order
-		policyResource = createPolicyResource(new String[]{"b", "a", "d", "c"}, true, false);
-		policyResourceView = new RangerPolicyResourceView(policyResource);
-		assertEquals("{values=[a, b, c, d],excludes=false,recursive=true}", policyResourceView.toString());
-		
-		// recursive flag is false and different variation of values to show lexicographic ordering
-		policyResource = createPolicyResource(new String[]{"9", "A", "e", "_"}, false, true);
-		policyResourceView = new RangerPolicyResourceView(policyResource);
-		assertEquals("{values=[9, A, _, e],excludes=true,recursive=false}", policyResourceView.toString());
-	}
-	
-	RangerPolicyResource createPolicyResource(String[] values, Boolean recursive, Boolean excludes) {
-		
-		RangerPolicyResource resource = mock(RangerPolicyResource.class);
-		if (values == null) {
-			when(resource.getValues()).thenReturn(null);
-		} else {
-			when(resource.getValues()).thenReturn(Arrays.asList(values));
-		}
-		when(resource.getIsRecursive()).thenReturn(recursive);
-		when(resource.getIsExcludes()).thenReturn(excludes);
-		
-		return resource;
-	}
-
-	@Test
-	public void test_isPolicyValidForResourceSignatureComputation() {
-		// null policy is invalid
-		RangerPolicyResourceSignature utils = new RangerPolicyResourceSignature((String)null);
-		RangerPolicy rangerPolicy = null;
-		assertFalse("policy==null", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
-
-		// null resource map is invalid
-		rangerPolicy = mock(RangerPolicy.class);
-		when(rangerPolicy.getResources()).thenReturn(null);
-		assertFalse("policy.getResources()==null", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
-		
-		// empty resources map is ok!
-		Map<String, RangerPolicyResource> policyResources = new HashMap<String, RangerPolicyResource>();
-		when(rangerPolicy.getResources()).thenReturn(policyResources);
-		assertTrue("policy.getResources().isEmpty()", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
-		
-		// but having a resource map with null key is not ok!
-		RangerPolicyResource aPolicyResource = mock(RangerPolicyResource.class);
-		policyResources.put(null, aPolicyResource);
-		assertFalse("policy.getResources().contains(null)", utils.isPolicyValidForResourceSignatureComputation(rangerPolicy));
-	}
-	
-	@Test
-	public void test_RangerPolicyResourceSignature() {
-		// String rep of a null policy is an empty string! and its hash is sha of empty string!
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
-		assertEquals("", signature.asString());
-		assertEquals(DigestUtils.md5Hex(""), signature.asHashHex());
-	}
-
-	/*
-	 * Format of data expected by the utility function which uses this is:
-	 * { "resource-name", "values" "isExcludes", "isRecursive" }
-	 */
-	Object[][] first = new Object[][] {
-			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
-			{ "db",    new String[] { "db1", "db2"},           false, null},
-			{ "col",   new String[] { "col2", "col1", "col3"}, null,  true},
-	};
-
-	Object[][] first_recursive_null_or_false = new Object[][] {
-			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  null}, // recursive flag is false in first
-			{ "db",    new String[] { "db1", "db2"},           false, null},
-			{ "col",   new String[] { "col2", "col1", "col3"}, null,  true},
-	};
-
-	Object[][] first_recursive_flag_different = new Object[][] {
-			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
-			{ "db",    new String[] { "db1", "db2"},           false, null},
-			{ "col",   new String[] { "col2", "col1", "col3"}, null,  false}, // recursive flag is true in first
-	};
-
-	Object[][] first_excludes_null_or_false = new Object[][] {
-			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
-			{ "db",    new String[] { "db1", "db2"},           false, null}, // excludes flag is null in first
-			{ "col",   new String[] { "col2", "col1", "col3"}, false, true},
-	};
-
-	Object[][] first_excludes_flag_different = new Object[][] {
-			{ "table", new String[] { "tbl3", "tbl1", "tbl2"}, true,  false},
-			{ "db",    new String[] { "db1", "db2"},           false, null},
-			{ "col",   new String[] { "col2", "col1", "col3"}, true,  true}, // excludes flag is false in first
-	};
-
-	Object[][] data_second = new Object[][] {
-			{ "db",    new String[] { "db2", "db1"},           false, null},
-			{ "table", new String[] { "tbl2", "tbl3", "tbl1"}, true, false},
-			{ "col",   new String[] { "col1", "col3", "col2"}, null, true},
-	};
-
-	@Test
-	public void test_getResourceSignature_happyPath() {
-		// null policy returns signature of empty resource
-		RangerPolicy policy = null;
-		RangerPolicyResourceSignature sig = new RangerPolicyResourceSignature(policy);
-		assertEquals(null, sig.getResourceString(policy));
-		
-		policy = mock(RangerPolicy.class);
-		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(first);
-		when(policy.getResources()).thenReturn(policyResources);
-		String expected = "{" +
-			"col={values=[col1, col2, col3],excludes=false,recursive=true}, " + 
-			"db={values=[db1, db2],excludes=false,recursive=false}, " +
-			"table={values=[tbl1, tbl2, tbl3],excludes=true,recursive=false}" +
-		"}"; 
-		assertEquals(expected, sig.getResourceString(policy));
-
-		// order of values should not matter
-		policyResources = _utils.createPolicyResourceMap(data_second);
-		when(policy.getResources()).thenReturn(policyResources);
-		assertEquals(expected, sig.getResourceString(policy));
-	}
-	
-	
-	@Test
-	public void test_nullRecursiveFlagIsSameAsFlase() {
-		// create two policies with resources that differ only in the recursive flag such that flags are null in one and false in another
-		RangerPolicy policy1 = createPolicy(first);
-		RangerPolicy policy2 = createPolicy(first_recursive_null_or_false);
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
-		assertEquals("null is same as false", signature.getResourceString(policy1), signature.getResourceString(policy2));
-	}
-	
-	@Test
-	public void test_onlyDifferByRecursiveFlag() {
-		// create two policies with resources that differ only in the recursive flag, i.e. null/false in one and true in another
-		RangerPolicy policy1 = createPolicy(first);
-		RangerPolicy policy2 = createPolicy(first_recursive_flag_different);
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
-		assertFalse("Resources differ only by recursive flag true vs false/null", signature.getResourceString(policy1).equals(signature.getResourceString(policy2)));
-	}
-	
-	@Test
-	public void test_nullExcludesFlagIsSameAsFlase() {
-		// create two policies with resources that differ only in the excludes flag such that flags are null in one and false in another
-		RangerPolicy policy1 = createPolicy(first);
-		RangerPolicy policy2 = createPolicy(first_excludes_null_or_false);
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
-		assertEquals("null is same as false", signature.getResourceString(policy1), signature.getResourceString(policy2));
-	}
-	
-	@Test
-	public void test_onlyDifferByExcludesFlag() {
-		// create two policies with resources that differ only in the excludes flag, i.e. null/false in one and true in another
-		RangerPolicy policy1 = createPolicy(first);
-		RangerPolicy policy2 = createPolicy(first_excludes_flag_different);
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature((String)null);
-		assertFalse("Resources differ only by recursive flag true vs false/null", signature.getResourceString(policy1).equals(signature.getResourceString(policy2)));
-	}
-	
-	RangerPolicy createPolicy(Object[][] data) {
-		RangerPolicy policy = mock(RangerPolicy.class);
-		Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(data);
-		when(policy.getResources()).thenReturn(resources);
-		return policy;
-	}
-
-	@Test
-	public void test_integration() {
-		// setup two policies with resources that are structurally different but semantically the same.
-		RangerPolicy aPolicy = mock(RangerPolicy.class);
-		Map<String, RangerPolicyResource> resources = _utils.createPolicyResourceMap(first);
-		when(aPolicy.getResources()).thenReturn(resources);
-		RangerPolicyResourceSignature signature = new RangerPolicyResourceSignature(aPolicy);
-		
-		RangerPolicy anotherPolicy = mock(RangerPolicy.class);
-		resources = _utils.createPolicyResourceMap(data_second);
-		when(anotherPolicy.getResources()).thenReturn(resources);
-		RangerPolicyResourceSignature anotherSignature = new RangerPolicyResourceSignature(anotherPolicy);
-		assertTrue(signature.equals(anotherSignature));
-		assertTrue(anotherSignature.equals(signature));
-	}
-	
-	ValidationTestUtils _utils = new ValidationTestUtils();
-}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
index f02b96e..1a4f366 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerPolicyValidator.java
@@ -38,6 +38,7 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
@@ -195,6 +196,8 @@ public class TestRangerPolicyValidator {
 		when(_store.getPolicies(updateFilter)).thenReturn(existingPolicies);
 		// valid policy can have empty set of policy items if audit is turned on
 		// null value for audit is treated as audit on.
+		// for now we want to turn any resource related checking off
+		when(_policy.getResources()).thenReturn(null);
 		for (Action action : cu) {
 			for (Boolean auditEnabled : new Boolean[] { null, true } ) {
 				for (boolean isAdmin : new boolean[] { true, false }) {
@@ -243,12 +246,13 @@ public class TestRangerPolicyValidator {
 		Map<String, RangerPolicyResource> resourceMap = _utils.createPolicyResourceMap(policyResourceMap_good);
 		when(_policy.getResources()).thenReturn(resourceMap);
 		// let's add some other policies in the store for this service that have a different signature
-		SearchFilter resourceDuplicationFilter = new SearchFilter();
-		resourceDuplicationFilter.setParam(SearchFilter.SERVICE_NAME, "service-name");
-		when(_factory.createPolicyResourceSignature(_policy)).thenReturn(new RangerPolicyResourceSignature("policy"));
-		when(_factory.createPolicyResourceSignature(existingPolicy)).thenReturn(new RangerPolicyResourceSignature("policy-name-2"));
+		// setup the signatures on the policies
+		RangerPolicyResourceSignature policySignature = mock(RangerPolicyResourceSignature.class);
+		when(_factory.createPolicyResourceSignature(_policy)).thenReturn(policySignature);
+		// setup the store to indicate that no other policy exists with matching signature
+		when(policySignature.getSignature()).thenReturn("hash-1");
+		when(_store.getPoliciesByResourceSignature("hash-1")).thenReturn(null);
 		// we are reusing the same policies collection here -- which is fine
-		when(_store.getPolicies(resourceDuplicationFilter)).thenReturn(existingPolicies);
 		for (Action action : cu) {
 			if (action == Action.CREATE) {
 				when(_policy.getId()).thenReturn(7L);
@@ -299,6 +303,7 @@ public class TestRangerPolicyValidator {
 			_policy = mock(RangerPolicy.class);
 			for (String name : new String[] { null, "  " }) {
 				when(_policy.getName()).thenReturn(name);
+				when(_policy.getResources()).thenReturn(null);
 				checkFailure_isValid(action, "missing", "name");
 			}
 			
@@ -437,6 +442,11 @@ public class TestRangerPolicyValidator {
 		// one mandatory is missing (tbl) and one unknown resource is specified (extra), and values of option resource don't conform to validation pattern (col)
 		Map<String, RangerPolicyResource> policyResources = _utils.createPolicyResourceMap(policyResourceMap_bad);
 		when(_policy.getResources()).thenReturn(policyResources);
+		// ensure thta policy is kosher when it comes to resource signature
+		RangerPolicyResourceSignature signature = mock(RangerPolicyResourceSignature.class);
+		when(_factory.createPolicyResourceSignature(_policy)).thenReturn(signature);
+		when(signature.getSignature()).thenReturn("hash-1");
+		when(_store.getPoliciesByResourceSignature("hash-1")).thenReturn(null); // store does not have any policies for that signature hash 
 		for (Action action : cu) {
 			for (boolean isAdmin : new boolean[] { true, false }) {
 				_failures.clear(); assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
@@ -448,13 +458,8 @@ public class TestRangerPolicyValidator {
 			}
 		}
 		
-		// create the right resource def but let it clash with another policy with matching resource-def
-		policyResources = _utils.createPolicyResourceMap(policyResourceMap_good);
-		when(_policy.getResources()).thenReturn(policyResources);
-		filter = new SearchFilter(); filter.setParam(SearchFilter.SERVICE_NAME, "service-name");
-		when(_store.getPolicies(filter)).thenReturn(existingPolicies);
-		// we are doctoring the factory to always return the same signature
-		when(_factory.createPolicyResourceSignature(anyPolicy())).thenReturn(new RangerPolicyResourceSignature("blah"));
+		// Check if error around resource signature clash are reported.  have Store return policies for same signature
+		when(_store.getPoliciesByResourceSignature("hash-1")).thenReturn(existingPolicies);
 		for (Action action : cu) {
 			for (boolean isAdmin : new boolean[] { true, false }) {
 				_failures.clear(); assertFalse(_validator.isValid(_policy, action, isAdmin, _failures));
@@ -665,38 +670,23 @@ public class TestRangerPolicyValidator {
 	@Test
 	public final void test_isPolicyResourceUnique() throws Exception {
 
-		RangerPolicy[] policies = new RangerPolicy[3];
-		RangerPolicyResourceSignature[] signatures = new RangerPolicyResourceSignature[3];
-		for (int i = 0; i < 3; i++) {
-			RangerPolicy policy = mock(RangerPolicy.class);
-			when(policy.getId()).thenReturn((long)i);
-			policies[i] = policy;
-			signatures[i] = new RangerPolicyResourceSignature("policy" + i);
-			when(_factory.createPolicyResourceSignature(policies[i])).thenReturn(signatures[i]);
-		}
-		
-		SearchFilter searchFilter = new SearchFilter();
-		String serviceName = "aService";
-		searchFilter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-		
-		List<RangerPolicy> existingPolicies = Arrays.asList(new RangerPolicy[] { policies[1], policies[2]} );
-		// all existing policies have distinct signatures
-		for (Action action : cu) {
-			when(_store.getPolicies(searchFilter)).thenReturn(existingPolicies);
-			assertTrue("No duplication: " + action, _validator.isPolicyResourceUnique(policies[0], _failures, action, serviceName));
-		}
-	
-		// Failure if signature matches an existing policy
-		// We change the signature of 3rd policy to be same as that of 1st so duplication check will fail
-		for (Action action : cu) {
-			when(_factory.createPolicyResourceSignature(policies[2])).thenReturn(new RangerPolicyResourceSignature("policy0"));
-			when(_store.getPolicies(searchFilter)).thenReturn(existingPolicies);
-			assertFalse("Duplication:" + action, _validator.isPolicyResourceUnique(policies[0], _failures, action, serviceName));
-		}
+		// if store does not contain any matching policies then check should succeed
+		RangerPolicyResourceSignature signature = mock(RangerPolicyResourceSignature.class);
+		String hash = "hash-1";
+		when(signature.getSignature()).thenReturn(hash);
+		when(_factory.createPolicyResourceSignature(_policy)).thenReturn(signature);
+		List<RangerPolicy> policies = null;
+		when(_store.getPoliciesByResourceSignature(hash)).thenReturn(policies);
+		assertTrue(_validator.isPolicyResourceUnique(_policy, _failures));
+		policies = new ArrayList<RangerPolicy>();
+		assertTrue(_validator.isPolicyResourceUnique(_policy, _failures));
 
-		// update should exclude itself! - let's change id of 3rd policy to be the same as the 1st one.
-		when(policies[2].getId()).thenReturn((long)0);
-		assertTrue("No duplication if updating policy", _validator.isPolicyResourceUnique(policies[0], _failures, Action.UPDATE, serviceName));
+		// if store does have any policy then test should fail with appropriate error message.
+		RangerPolicy policy1 = mock(RangerPolicy.class); policies.add(policy1); 
+		RangerPolicy policy2 = mock(RangerPolicy.class); policies.add(policy2); 
+		when(_store.getPoliciesByResourceSignature(hash)).thenReturn(policies);
+		assertFalse(_validator.isPolicyResourceUnique(_policy, _failures));
+		_utils.checkFailureForSemanticError(_failures, "resources");
 	}
 	
 	@Test

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
index 81ecfdd..46f488e 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerValidator.java
@@ -46,7 +46,6 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.model.validation.RangerValidator;
 import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.plugin.store.ServiceStore;
 import org.apache.ranger.plugin.util.SearchFilter;
@@ -193,6 +192,27 @@ public class TestRangerValidator {
 		assertNull(_validator.getPolicy(2L));
 		assertTrue(_validator.getPolicy(3L) != null);
 	}
+	
+	@Test
+	public final void test_getPoliciesForResourceSignature() throws Exception {
+		// return null if store returns null or throws an exception
+		String hexSignature = "aSignature";
+		when(_store.getPoliciesByResourceSignature(hexSignature)).thenReturn(null);
+		assertNull(_validator.getPoliciesForResourceSignature(hexSignature));
+		when(_store.getPoliciesByResourceSignature(hexSignature)).thenThrow(new Exception());
+		assertNull(_validator.getPoliciesForResourceSignature(hexSignature));
+
+		// what ever store returns should come back
+		hexSignature = "anotherSignature";
+		List<RangerPolicy> policies = new ArrayList<RangerPolicy>();
+		RangerPolicy policy1 = mock(RangerPolicy.class);
+		policies.add(policy1);
+		RangerPolicy policy2 = mock(RangerPolicy.class);
+		policies.add(policy2);
+		when(_store.getPoliciesByResourceSignature(hexSignature)).thenReturn(policies);
+		List<RangerPolicy> result = _validator.getPoliciesForResourceSignature(hexSignature);
+		assertTrue(result.contains(policy1) && result.contains(policy2));
+	}
 
 	@Test
 	public void test_getService_byId() throws Exception {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
----------------------------------------------------------------------
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
index 432c9d4..bc4b2c5 100644
--- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/ValidationTestUtils.java
@@ -332,7 +332,7 @@ public class ValidationTestUtils {
 		return defs;
 	}
 
-	Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
+	public Map<String, RangerPolicyResource> createPolicyResourceMap(Object[][] input) {
 		if (input == null) {
 			return null;
 		}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 12aa31c..5542f72 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -87,9 +87,10 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemAccess;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItemCondition;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.model.RangerServiceDef;
-import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerAccessTypeDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerContextEnricherDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumDef;
@@ -97,13 +98,15 @@ import org.apache.ranger.plugin.model.RangerServiceDef.RangerEnumElementDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerPolicyConditionDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerServiceConfigDef;
-import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.store.AbstractServiceStore;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
+import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.plugin.util.ServicePolicies;
-import org.apache.ranger.service.RangerPolicyWithAssignedIdService;
 import org.apache.ranger.service.RangerAuditFields;
 import org.apache.ranger.service.RangerDataHistService;
+import org.apache.ranger.service.RangerFactory;
 import org.apache.ranger.service.RangerPolicyService;
+import org.apache.ranger.service.RangerPolicyWithAssignedIdService;
 import org.apache.ranger.service.RangerServiceDefService;
 import org.apache.ranger.service.RangerServiceService;
 import org.apache.ranger.service.RangerServiceWithAssignedIdService;
@@ -120,7 +123,6 @@ import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallback;
 import org.springframework.transaction.support.TransactionTemplate;
-import org.apache.ranger.plugin.util.SearchFilter;
 
 
 @Component
@@ -170,6 +172,9 @@ public class ServiceDBStore extends AbstractServiceStore {
     @Autowired
     RangerServiceWithAssignedIdService svcServiceWithAssignedId;
 
+    @Autowired
+    RangerFactory factory;
+    
 	private static volatile boolean legacyServiceDefsInitDone = false;
 	private Boolean populateExistingBaseFields = false;
 	
@@ -1194,6 +1199,18 @@ public class ServiceDBStore extends AbstractServiceStore {
 	}
 
 	@Override
+	public List<RangerPolicy> getPoliciesByResourceSignature(String hexSignature) throws Exception {
+		List<XXPolicy> xxPolicies = daoMgr.getXXPolicy().findByResourceSignature(hexSignature);
+		List<RangerPolicy> policies = new ArrayList<RangerPolicy>(xxPolicies.size());
+		for (XXPolicy xxPolicy : xxPolicies) {
+			RangerPolicy policy = policyService.getPopulatedViewObject(xxPolicy);
+			policies.add(policy);
+		}
+		
+		return policies;
+	}
+
+	@Override
 	public RangerService getService(Long id) throws Exception {
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("==> ServiceDBStore.getService()");
@@ -1270,6 +1287,9 @@ public class ServiceDBStore extends AbstractServiceStore {
 		List<RangerPolicyItem> policyItems = policy.getPolicyItems();
 
 		policy.setVersion(new Long(1));
+		RangerPolicyResourceSignature signature = factory.createPolicyResourceSignature(policy);
+		String hexSignature = signature.getSignature();
+		policy.setResourceSignature(hexSignature);
 
 		if(populateExistingBaseFields) {
 			assignedIdPolicyService.setPopulateExistingBaseFields(true);
@@ -1433,15 +1453,21 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 	public RangerPolicyList getPaginatedPolicies(SearchFilter filter) throws Exception {
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("==> ServiceDBStore.getPaginatedPolicies()");
+			LOG.debug("==> ServiceDBStore.getPaginatedPolicies(+ " + filter + ")");
 		}
 
 		RangerPolicyList policyList = policyService.searchRangerPolicies(filter);
-
+		
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("before filter: count=" + policyList.getListSize());
+		}
 		applyFilter(policyList.getPolicies(), filter);
+		if (LOG.isDebugEnabled()) {
+			LOG.debug("after filter: count=" + policyList.getListSize());
+		}
 
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("<== ServiceDBStore.getPaginatedPolicies()");
+			LOG.debug("<== ServiceDBStore.getPaginatedPolicies(" + filter + "): count=" + policyList.getListSize());
 		}
 
 		return policyList;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/5ac7c52a/security-admin/src/main/java/org/apache/ranger/service/RangerFactory.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerFactory.java b/security-admin/src/main/java/org/apache/ranger/service/RangerFactory.java
new file mode 100644
index 0000000..7834262
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.service;
+
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicyResourceSignature;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+@Service
+@Scope("singleton")
+public class RangerFactory {
+	public RangerPolicyResourceSignature createPolicyResourceSignature(RangerPolicy policy) {
+		return new RangerPolicyResourceSignature(policy);
+	}
+}