You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ab...@apache.org on 2021/01/23 22:09:26 UTC

[ranger] branch master updated: RANGER-3156: RangerResouceTrie.add() and RangerResourceTrie.delete() do not work correctly for the resources containing wildcards

This is an automated email from the ASF dual-hosted git repository.

abhay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new e9b724b  RANGER-3156: RangerResouceTrie.add() and RangerResourceTrie.delete() do not work correctly for the resources containing wildcards
e9b724b is described below

commit e9b724b05e395587c0fcd67ce576fe3a0bc54b80
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Sat Jan 23 13:28:42 2021 -0800

    RANGER-3156: RangerResouceTrie.add() and RangerResourceTrie.delete() do not work correctly for the resources containing wildcards
---
 .../plugin/policyengine/RangerResourceTrie.java    |  46 +-
 .../ranger/plugin/service/RangerBasePlugin.java    |   5 +-
 .../ranger/plugin/util/RangerPolicyDeltaUtil.java  |   7 +-
 .../policyengine/TestPolicyEngineForDeltas.java    | 570 ++++++++++++++++++
 .../test_policyengine_hdfs_incremental_delete.json | 635 +++++++++++++++++++++
 .../main/resources/META-INF/jpa_named_queries.xml  |   4 +-
 6 files changed, 1244 insertions(+), 23 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
index 6d784c2..7149135 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
@@ -258,6 +258,11 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator> {
     public void wrapUpUpdate() {
         if (root != null) {
             root.wrapUpUpdate();
+            if (TRACE_LOG.isTraceEnabled()) {
+                StringBuilder sb = new StringBuilder();
+                root.toString("", sb);
+                TRACE_LOG.trace("Trie Dump from RangerResourceTrie.wrapUpUpdate(name=" + resourceDef.getName() + "):\n{" + sb.toString() + "}");
+            }
         }
     }
 
@@ -988,13 +993,14 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator> {
         }
 
         void addWildcardEvaluator(U evaluator) {
+            undoSetup();
+
             if (wildcardEvaluators == null) {
                 wildcardEvaluators = new HashSet<>();
             }
 
             if (!wildcardEvaluators.contains(evaluator)) {
                 wildcardEvaluators.add(evaluator);
-                undoSetup();
             }
         }
 
@@ -1008,20 +1014,13 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator> {
             }
         }
 
-        boolean removeWildcardEvaluator(U evaluator) {
-            if (CollectionUtils.isNotEmpty(wildcardEvaluators) && wildcardEvaluators.contains(evaluator)) {
-                undoSetup();
-
-                if (CollectionUtils.isNotEmpty(wildcardEvaluators)) {
-                    wildcardEvaluators.remove(evaluator);
+        void removeWildcardEvaluator(U evaluator) {
+            if (CollectionUtils.isNotEmpty(wildcardEvaluators)) {
+                wildcardEvaluators.remove(evaluator);
 
-                    if (CollectionUtils.isEmpty(wildcardEvaluators)) {
-                        wildcardEvaluators = null;
-                    }
+                if (CollectionUtils.isEmpty(wildcardEvaluators)) {
+                    wildcardEvaluators = null;
                 }
-                return true;
-            } else {
-                return false;
             }
         }
 
@@ -1066,6 +1065,15 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator> {
             }
         }
 
+        void removeSelfFromTrie() {
+            if (evaluators == null && wildcardEvaluators == null && children.size() == 0) {
+                TrieNode<U> parent = getParent();
+                if (parent != null) {
+                    parent.children.remove(str.charAt(0));
+                }
+            }
+        }
+
         void wrapUpUpdate() {
             if (isOptimizedForRetrieval) {
                 RangerPerfTracer postSetupPerf = null;
@@ -1155,13 +1163,13 @@ public class RangerResourceTrie<T extends RangerPolicyResourceEvaluator> {
         }
 
         private void removeEvaluatorFromSubtree(U evaluator) {
-            if (removeWildcardEvaluator(evaluator)) {
-                for (Map.Entry<Character, TrieNode<U>> entry : children.entrySet()) {
-                    entry.getValue().removeEvaluatorFromSubtree(evaluator);
-                }
+            if (CollectionUtils.isNotEmpty(wildcardEvaluators) && wildcardEvaluators.contains(evaluator)) {
+                undoSetup();
+                removeWildcardEvaluator(evaluator);
+            } else {
+                removeEvaluator(evaluator);
             }
-
-            removeEvaluator(evaluator);
+            removeSelfFromTrie();
         }
 
         void toString(StringBuilder sb) {
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
index e1f09b8..fda57f9 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
@@ -212,7 +212,7 @@ public class RangerBasePlugin {
 				Boolean hasPolicyDeltas = RangerPolicyDeltaUtil.hasPolicyDeltas(policies);
 
 				if (hasPolicyDeltas == null) {
-					LOG.warn("Downloaded policies are internally inconsistent!! [" + policies + "]. Please check server-side code! Keeping old policy-engine!");
+					LOG.warn("Downloaded policies do not require policy change !! [" + policies + "]. Keeping old policy-engine!");
 					isNewEngineNeeded = false;
 				} else {
 					if (hasPolicyDeltas.equals(Boolean.TRUE)) {
@@ -230,6 +230,9 @@ public class RangerBasePlugin {
 						}
 					} else {
 						usePolicyDeltas = false;
+						if (policies.getPolicies() == null) {
+							policies.setPolicies(new ArrayList<>());
+						}
 					}
 				}
 			}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPolicyDeltaUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPolicyDeltaUtil.java
index 0269461..62b60a1 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPolicyDeltaUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerPolicyDeltaUtil.java
@@ -183,8 +183,13 @@ public class RangerPolicyDeltaUtil {
             boolean isPolicyDeltasExist = CollectionUtils.isNotEmpty(servicePolicies.getPolicyDeltas()) || isPolicyDeltasExistInSecurityZones;
 
             if (isPoliciesExist && isPolicyDeltasExist) {
-                LOG.warn("ServicePolicies contain both policies and policy-deltas!!");
+                LOG.warn("ServicePolicies contain both policies and policy-deltas!! Cannot build policy-engine from these servicePolicies. Please check server-side code!");
+                LOG.warn("Downloaded ServicePolicies are [" + servicePolicies + "]");
                 ret = null;
+            } else if (!isPoliciesExist && !isPolicyDeltasExist) {
+                LOG.warn("ServicePolicies do not contain any policies or policy-deltas!! There are no material changes in the policies. There may be service changes!");
+                LOG.warn("Downloaded ServicePolicies are [" + servicePolicies + "]");
+                ret = false;
             } else {
                 ret = isPolicyDeltasExist;
             }
diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngineForDeltas.java b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngineForDeltas.java
new file mode 100644
index 0000000..c4187cc
--- /dev/null
+++ b/agents-common/src/test/java/org/apache/ranger/plugin/policyengine/TestPolicyEngineForDeltas.java
@@ -0,0 +1,570 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.policyengine;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.reflect.TypeToken;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.audit.provider.AuditHandler;
+import org.apache.ranger.audit.provider.AuditProviderFactory;
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicyDelta;
+import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.TestPolicyEngineForDeltas.PolicyEngineTestCase.TestData;
+import org.apache.ranger.plugin.service.RangerBasePlugin;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.apache.ranger.plugin.util.RangerRequestedResources;
+import org.apache.ranger.plugin.util.RangerRoles;
+import org.apache.ranger.plugin.util.ServicePolicies;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class TestPolicyEngineForDeltas {
+	static RangerPluginContext pluginContext;
+	static Gson gsonBuilder;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws Exception {
+		pluginContext = new RangerPluginContext(new RangerPluginConfig("hive", null, "hive", "cl1", "on-prem", null));
+
+		gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ")
+				.setPrettyPrinting()
+				.registerTypeAdapter(RangerAccessRequest.class, new RangerAccessRequestDeserializer())
+				.registerTypeAdapter(RangerAccessResource.class, new RangerResourceDeserializer())
+				.create();
+
+		// For setting up auditProvider
+		Properties auditProperties = new Properties();
+
+		String AUDIT_PROPERTIES_FILE = "xasecure-audit.properties";
+
+		File propFile = new File(AUDIT_PROPERTIES_FILE);
+
+		if (propFile.exists()) {
+			System.out.println("Loading Audit properties file" + AUDIT_PROPERTIES_FILE);
+
+			auditProperties.load(new FileInputStream(propFile));
+		} else {
+			System.out.println("Audit properties file missing: " + AUDIT_PROPERTIES_FILE);
+
+			auditProperties.setProperty("xasecure.audit.jpa.javax.persistence.jdbc.url", "jdbc:mysql://node-1:3306/xasecure_audit");
+			auditProperties.setProperty("xasecure.audit.jpa.javax.persistence.jdbc.user", "xalogger");
+			auditProperties.setProperty("xasecure.audit.jpa.javax.persistence.jdbc.password", "xalogger");
+			auditProperties.setProperty("xasecure.audit.jpa.javax.persistence.jdbc.driver", "com.mysql.jdbc.Driver");
+
+			auditProperties.setProperty("xasecure.audit.is.enabled", "false"); // Set this to true to enable audit logging
+			auditProperties.setProperty("xasecure.audit.log4j.is.enabled", "false");
+			auditProperties.setProperty("xasecure.audit.log4j.is.async", "false");
+			auditProperties.setProperty("xasecure.audit.log4j.async.max.queue.size", "100000");
+			auditProperties.setProperty("xasecure.audit.log4j.async.max.flush.interval.ms", "30000");
+			auditProperties.setProperty("xasecure.audit.db.is.enabled", "false");
+			auditProperties.setProperty("xasecure.audit.db.is.async", "false");
+			auditProperties.setProperty("xasecure.audit.db.async.max.queue.size", "100000");
+			auditProperties.setProperty("xasecure.audit.db.async.max.flush.interval.ms", "30000");
+			auditProperties.setProperty("xasecure.audit.db.batch.size", "100");
+		}
+
+		AuditProviderFactory factory = AuditProviderFactory.getInstance();
+		factory.init(auditProperties, "hdfs"); // second parameter does not matter for v2
+
+		AuditHandler provider = factory.getAuditProvider();
+
+		System.out.println("provider=" + provider.toString());
+
+		File file = File.createTempFile("ranger-admin-test-site", ".xml");
+		file.deleteOnExit();
+
+		FileOutputStream outStream = new FileOutputStream(file);
+		OutputStreamWriter writer = new OutputStreamWriter(outStream);
+
+		/*
+		// For setting up TestTagProvider
+
+		writer.write("<configuration>\n" +
+				"        <property>\n" +
+				"                <name>ranger.plugin.tag.policy.rest.url</name>\n" +
+				"                <value>http://os-def:6080</value>\n" +
+				"        </property>\n" +
+				"        <property>\n" +
+				"                <name>ranger.externalurl</name>\n" +
+				"                <value>http://os-def:6080</value>\n" +
+				"        </property>\n" +
+				"</configuration>\n");
+				*/
+
+		writer.write("<configuration>\n" +
+				/*
+				// For setting up TestTagProvider
+				"        <property>\n" +
+				"                <name>ranger.plugin.tag.policy.rest.url</name>\n" +
+				"                <value>http://os-def:6080</value>\n" +
+				"        </property>\n" +
+				"        <property>\n" +
+				"                <name>ranger.externalurl</name>\n" +
+				"                <value>http://os-def:6080</value>\n" +
+				"        </property>\n" +
+				*/
+				// For setting up x-forwarded-for for Hive
+				"        <property>\n" +
+				"                <name>ranger.plugin.hive.use.x-forwarded-for.ipaddress</name>\n" +
+				"                <value>true</value>\n" +
+				"        </property>\n" +
+				"        <property>\n" +
+				"                <name>ranger.plugin.hive.trusted.proxy.ipaddresses</name>\n" +
+				"                <value>255.255.255.255; 128.101.101.101;128.101.101.99</value>\n" +
+				"        </property>\n" +
+				"        <property>\n" +
+				"                <name>ranger.plugin.tag.attr.additional.date.formats</name>\n" +
+				"                <value>abcd||xyz||yyyy/MM/dd'T'HH:mm:ss.SSS'Z'</value>\n" +
+				"        </property>\n" +
+				"        <property>\n" +
+				"                <name>ranger.policyengine.trie.builder.thread.count</name>\n" +
+				"                <value>3</value>\n" +
+				"        </property>\n" +
+                "</configuration>\n");
+		writer.close();
+
+		pluginContext.getConfig().addResource(new org.apache.hadoop.fs.Path(file.toURI()));
+	}
+
+	@AfterClass
+	public static void tearDownAfterClass() {
+	}
+
+	@Test
+	public void testPolicyEngine_hdfs_incremental_delete() {
+		String[] hdfsTestResourceFiles = {"/policyengine/test_policyengine_hdfs_incremental_delete.json"};
+
+		runTestsFromResourceFiles(hdfsTestResourceFiles);
+	}
+
+	private void runTestsFromResourceFiles(String[] resourceNames) {
+		for(String resourceName : resourceNames) {
+			InputStream inStream = this.getClass().getResourceAsStream(resourceName);
+			InputStreamReader reader   = new InputStreamReader(inStream);
+
+			runTests(reader, resourceName);
+		}
+	}
+
+	private void runTests(InputStreamReader reader, String testName) {
+		PolicyEngineTestCase testCase = gsonBuilder.fromJson(reader, PolicyEngineTestCase.class);
+
+		assertTrue("invalid input: " + testName, testCase != null && testCase.serviceDef != null && testCase.policies != null && testCase.testsInfo != null && testCase.testsInfo.tests != null);
+
+		ServicePolicies servicePolicies = new ServicePolicies();
+		servicePolicies.setPolicyVersion(100L);
+		servicePolicies.setServiceName(testCase.serviceName);
+		servicePolicies.setServiceDef(testCase.serviceDef);
+		servicePolicies.setPolicies(testCase.policies);
+		servicePolicies.setSecurityZones(testCase.securityZones);
+		servicePolicies.setServiceConfig(testCase.serviceConfig);
+
+		if (StringUtils.isNotBlank(testCase.auditMode)) {
+			servicePolicies.setAuditMode(testCase.auditMode);
+		}
+
+		if (null != testCase.tagPolicyInfo) {
+			ServicePolicies.TagPolicies tagPolicies = new ServicePolicies.TagPolicies();
+			tagPolicies.setServiceName(testCase.tagPolicyInfo.serviceName);
+			tagPolicies.setServiceDef(testCase.tagPolicyInfo.serviceDef);
+			tagPolicies.setPolicies(testCase.tagPolicyInfo.tagPolicies);
+			tagPolicies.setServiceConfig(testCase.tagPolicyInfo.serviceConfig);
+
+			if (StringUtils.isNotBlank(testCase.auditMode)) {
+				tagPolicies.setAuditMode(testCase.auditMode);
+			}
+			servicePolicies.setTagPolicies(tagPolicies);
+		}
+
+		boolean useForwardedIPAddress = pluginContext.getConfig().getBoolean("ranger.plugin.hive.use.x-forwarded-for.ipaddress", false);
+		String trustedProxyAddressString = pluginContext.getConfig().get("ranger.plugin.hive.trusted.proxy.ipaddresses");
+		String[] trustedProxyAddresses = StringUtils.split(trustedProxyAddressString, ';');
+		if (trustedProxyAddresses != null) {
+			for (int i = 0; i < trustedProxyAddresses.length; i++) {
+				trustedProxyAddresses[i] = trustedProxyAddresses[i].trim();
+			}
+		}
+
+		RangerRoles roles = new RangerRoles();
+		roles.setServiceName(testCase.serviceName);
+		roles.setRoleVersion(-1L);
+		Set<RangerRole> rolesSet = new HashSet<>();
+
+		Map<String, Set<String>> userRoleMapping = testCase.userRoles;
+		Map<String, Set<String>> groupRoleMapping = testCase.groupRoles;
+		Map<String, Set<String>> roleRoleMapping = testCase.roleRoles;
+		if (userRoleMapping != null) {
+			for (Map.Entry<String, Set<String>> userRole : userRoleMapping.entrySet()) {
+				String user = userRole.getKey();
+				Set<String> userRoles = userRole.getValue();
+				RangerRole.RoleMember userRoleMember = new RangerRole.RoleMember(user, true);
+				List<RangerRole.RoleMember> userRoleMembers = Arrays.asList(userRoleMember);
+				for (String usrRole : userRoles) {
+					RangerRole rangerUserRole = new RangerRole(usrRole, usrRole, null, userRoleMembers, null);
+					rolesSet.add(rangerUserRole);
+				}
+			}
+		}
+
+		if (groupRoleMapping != null) {
+			for (Map.Entry<String, Set<String>> groupRole : groupRoleMapping.entrySet()) {
+				String group = groupRole.getKey();
+				Set<String> groupRoles = groupRole.getValue();
+				RangerRole.RoleMember groupRoleMember = new RangerRole.RoleMember(group, true);
+				List<RangerRole.RoleMember> groupRoleMembers = Arrays.asList(groupRoleMember);
+				for (String grpRole : groupRoles) {
+					RangerRole rangerGroupRole = new RangerRole(grpRole, grpRole, null, null, groupRoleMembers);
+					rolesSet.add(rangerGroupRole);
+				}
+			}
+		}
+
+		if (roleRoleMapping != null) {
+			for (Map.Entry<String, Set<String>> roleRole : roleRoleMapping.entrySet()) {
+				String role = roleRole.getKey();
+				Set<String> roleRoles = roleRole.getValue();
+				RangerRole.RoleMember roleRoleMember = new RangerRole.RoleMember(role, true);
+				List<RangerRole.RoleMember> roleRoleMembers = Arrays.asList(roleRoleMember);
+				for (String rleRole : roleRoles) {
+					RangerRole rangerRoleRole = new RangerRole(rleRole, rleRole, null, null, null, roleRoleMembers);
+					rolesSet.add(rangerRoleRole);
+				}
+			}
+		}
+
+		roles.setRangerRoles(rolesSet);
+
+        RangerPolicyEngineOptions policyEngineOptions = pluginContext.getConfig().getPolicyEngineOptions();
+
+        policyEngineOptions.disableAccessEvaluationWithPolicyACLSummary = true;
+
+        setPluginConfig(pluginContext.getConfig(), ".super.users", testCase.superUsers);
+        setPluginConfig(pluginContext.getConfig(), ".super.groups", testCase.superGroups);
+        setPluginConfig(pluginContext.getConfig(), ".audit.exclude.users", testCase.auditExcludedUsers);
+        setPluginConfig(pluginContext.getConfig(), ".audit.exclude.groups", testCase.auditExcludedGroups);
+        setPluginConfig(pluginContext.getConfig(), ".audit.exclude.roles", testCase.auditExcludedRoles);
+
+        // so that setSuperUsersAndGroups(), setAuditExcludedUsersGroupsRoles() will be called on the pluginConfig
+        new RangerBasePlugin(pluginContext.getConfig());
+
+        RangerPolicyEngineImpl policyEngine = new RangerPolicyEngineImpl(servicePolicies, pluginContext, roles);
+
+        policyEngine.setUseForwardedIPAddress(useForwardedIPAddress);
+        policyEngine.setTrustedProxyAddresses(trustedProxyAddresses);
+
+        policyEngineOptions.disableAccessEvaluationWithPolicyACLSummary = false;
+
+		RangerPolicyEngineImpl policyEngineForEvaluatingWithACLs = new RangerPolicyEngineImpl(servicePolicies, pluginContext, roles);
+
+		policyEngineForEvaluatingWithACLs.setUseForwardedIPAddress(useForwardedIPAddress);
+		policyEngineForEvaluatingWithACLs.setTrustedProxyAddresses(trustedProxyAddresses);
+
+		PolicyEngineTestCase.TestsInfo testsInfo = testCase.testsInfo;
+		do {
+			runTestCaseTests(policyEngine, policyEngineForEvaluatingWithACLs, testCase.serviceDef, testName, testsInfo.tests);
+			if (testsInfo.updatedPolicies != null && CollectionUtils.isNotEmpty(testsInfo.updatedPolicies.policyDeltas)) {
+				servicePolicies.setPolicyDeltas(testsInfo.updatedPolicies.policyDeltas);
+				servicePolicies.setPolicies(null);
+				if (MapUtils.isNotEmpty(testsInfo.updatedPolicies.securityZones)) {
+					servicePolicies.setSecurityZones(testsInfo.updatedPolicies.securityZones);
+				}
+				policyEngine = (RangerPolicyEngineImpl) RangerPolicyEngineImpl.getPolicyEngine(policyEngine, servicePolicies);
+				policyEngineForEvaluatingWithACLs = (RangerPolicyEngineImpl) RangerPolicyEngineImpl.getPolicyEngine(policyEngineForEvaluatingWithACLs, servicePolicies);
+				if (policyEngine != null && policyEngineForEvaluatingWithACLs != null) {
+					testsInfo = testsInfo.updatedTestsInfo;
+				} else {
+					testsInfo = null;
+				}
+			} else {
+				testsInfo = null;
+			}
+
+		} while (testsInfo != null && testsInfo.tests != null);
+
+	}
+
+    private void runTestCaseTests(RangerPolicyEngine policyEngine, RangerPolicyEngine policyEngineForEvaluatingWithACLs, RangerServiceDef serviceDef, String testName, List<TestData> tests) {
+        RangerAccessRequest request;
+
+        for(TestData test : tests) {
+			request = test.request;
+
+			if (request.getContext().containsKey(RangerAccessRequestUtil.KEY_CONTEXT_TAGS) ||
+					request.getContext().containsKey(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES)) {
+				// Create a new AccessRequest
+				RangerAccessRequestImpl newRequest =
+						new RangerAccessRequestImpl(request.getResource(), request.getAccessType(),
+								request.getUser(), request.getUserGroups(), null);
+
+				newRequest.setClientType(request.getClientType());
+				newRequest.setAccessTime(request.getAccessTime());
+				newRequest.setAction(request.getAction());
+				newRequest.setRemoteIPAddress(request.getRemoteIPAddress());
+				newRequest.setForwardedAddresses(request.getForwardedAddresses());
+				newRequest.setRequestData(request.getRequestData());
+				newRequest.setSessionId(request.getSessionId());
+
+				Map<String, Object> context = request.getContext();
+				String tagsJsonString = (String) context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
+				context.remove(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
+
+				if(!StringUtils.isEmpty(tagsJsonString)) {
+					try {
+						Type setType = new TypeToken<Set<RangerTagForEval>>() {
+						}.getType();
+						Set<RangerTagForEval> tags = gsonBuilder.fromJson(tagsJsonString, setType);
+
+						context.put(RangerAccessRequestUtil.KEY_CONTEXT_TAGS, tags);
+					} catch (Exception e) {
+						System.err.println("TestPolicyEngineForDeltas.runTests(): error parsing TAGS JSON string in file " + testName + ", tagsJsonString=" +
+								tagsJsonString + ", exception=" + e);
+					}
+				} else if (request.getContext().containsKey(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES)) {
+					String resourcesJsonString = (String) context.get(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES);
+					context.remove(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES);
+					if (!StringUtils.isEmpty(resourcesJsonString)) {
+						try {
+							/*
+							Reader stringReader = new StringReader(resourcesJsonString);
+							RangerRequestedResources resources = gsonBuilder.fromJson(stringReader, RangerRequestedResources.class);
+							*/
+
+							Type myType = new TypeToken<RangerRequestedResources>() {
+							}.getType();
+							RangerRequestedResources resources = gsonBuilder.fromJson(resourcesJsonString, myType);
+
+							context.put(RangerAccessRequestUtil.KEY_CONTEXT_REQUESTED_RESOURCES, resources);
+						} catch (Exception e) {
+							System.err.println("TestPolicyEngineForDeltas.runTests(): error parsing REQUESTED_RESOURCES string in file " + testName + ", resourcesJsonString=" +
+									resourcesJsonString + ", exception=" + e);
+						}
+					}
+				}
+				newRequest.setContext(context);
+
+				// accessResource.ServiceDef is set here, so that we can skip call to policyEngine.preProcess() which
+				// sets the serviceDef in the resource AND calls enrichers. We dont want enrichers to be called when
+				// context already contains tags -- This may change when we want enrichers to enrich request in the
+				// presence of tags!!!
+
+				// Safe cast
+				RangerAccessResourceImpl accessResource = (RangerAccessResourceImpl) request.getResource();
+				accessResource.setServiceDef(serviceDef);
+
+				request = newRequest;
+
+			}
+
+			RangerAccessResultProcessor auditHandler = new RangerDefaultAuditHandler();
+
+			if(test.result != null) {
+                RangerAccessResult expected = test.result;
+                RangerAccessResult result;
+
+				result   = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ACCESS, auditHandler);
+
+				policyEngine.evaluateAuditPolicies(result);
+
+				assertNotNull("result was null! - " + test.name, result);
+				assertEquals("isAllowed mismatched! - " + test.name, expected.getIsAllowed(), result.getIsAllowed());
+				assertEquals("policy-id mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
+				assertEquals("isAudited mismatched! - " + test.name, expected.getIsAudited(), result.getIsAudited() && result.getIsAuditedDetermined());
+
+				result   = policyEngineForEvaluatingWithACLs.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ACCESS, auditHandler);
+
+				policyEngine.evaluateAuditPolicies(result);
+
+                assertNotNull("result was null! - " + test.name, result);
+                assertEquals("isAllowed mismatched! - " + test.name, expected.getIsAllowed(), result.getIsAllowed());
+                assertEquals("isAudited mismatched! - " + test.name, expected.getIsAudited(), result.getIsAudited());
+			}
+
+			if(test.dataMaskResult != null) {
+				RangerAccessResult expected = test.dataMaskResult;
+				RangerAccessResult result;
+
+                result   = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_DATAMASK, auditHandler);
+
+                policyEngine.evaluateAuditPolicies(result);
+
+                assertNotNull("result was null! - " + test.name, result);
+                assertEquals("maskType mismatched! - " + test.name, expected.getMaskType(), result.getMaskType());
+                assertEquals("maskCondition mismatched! - " + test.name, expected.getMaskCondition(), result.getMaskCondition());
+                assertEquals("maskedValue mismatched! - " + test.name, expected.getMaskedValue(), result.getMaskedValue());
+                assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
+
+                result = policyEngineForEvaluatingWithACLs.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_DATAMASK, auditHandler);
+
+                policyEngine.evaluateAuditPolicies(result);
+
+				assertNotNull("result was null! - " + test.name, result);
+				assertEquals("maskType mismatched! - " + test.name, expected.getMaskType(), result.getMaskType());
+				assertEquals("maskCondition mismatched! - " + test.name, expected.getMaskCondition(), result.getMaskCondition());
+				assertEquals("maskedValue mismatched! - " + test.name, expected.getMaskedValue(), result.getMaskedValue());
+				assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
+
+			}
+
+			if(test.rowFilterResult != null) {
+				RangerAccessResult expected = test.rowFilterResult;
+				RangerAccessResult result;
+
+                result   = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ROWFILTER, auditHandler);
+
+                policyEngine.evaluateAuditPolicies(result);
+
+                assertNotNull("result was null! - " + test.name, result);
+                assertEquals("filterExpr mismatched! - " + test.name, expected.getFilterExpr(), result.getFilterExpr());
+                assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
+
+				result = policyEngineForEvaluatingWithACLs.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ROWFILTER, auditHandler);
+
+				policyEngine.evaluateAuditPolicies(result);
+
+				assertNotNull("result was null! - " + test.name, result);
+				assertEquals("filterExpr mismatched! - " + test.name, expected.getFilterExpr(), result.getFilterExpr());
+				assertEquals("policyId mismatched! - " + test.name, expected.getPolicyId(), result.getPolicyId());
+
+			}
+
+			if(test.resourceAccessInfo != null) {
+
+				RangerResourceAccessInfo expected = new RangerResourceAccessInfo(test.resourceAccessInfo);
+				RangerResourceAccessInfo result   = policyEngine.getResourceAccessInfo(test.request);
+
+				assertNotNull("result was null! - " + test.name, result);
+				assertEquals("allowedUsers mismatched! - " + test.name, expected.getAllowedUsers(), result.getAllowedUsers());
+				assertEquals("allowedGroups mismatched! - " + test.name, expected.getAllowedGroups(), result.getAllowedGroups());
+				assertEquals("deniedUsers mismatched! - " + test.name, expected.getDeniedUsers(), result.getDeniedUsers());
+				assertEquals("deniedGroups mismatched! - " + test.name, expected.getDeniedGroups(), result.getDeniedGroups());
+			}
+		}
+
+	}
+
+	private void setPluginConfig(RangerPluginConfig conf, String suffix, Set<String> value) {
+		conf.set(conf.getPropertyPrefix() + suffix, CollectionUtils.isNotEmpty(value) ? StringUtils.join(value, ',') : "");
+	}
+
+	static class PolicyEngineTestCase {
+		public String             serviceName;
+		public RangerServiceDef   serviceDef;
+		public List<RangerPolicy> policies;
+		public TagPolicyInfo	  tagPolicyInfo;
+		public Map<String, ServicePolicies.SecurityZoneInfo> securityZones;
+		public Map<String, Set<String>> userRoles;
+		public Map<String, Set<String>> groupRoles;
+		public Map<String, Set<String>> roleRoles;
+		public String             auditMode;
+		public TestsInfo          testsInfo;
+		//public List<TestData>     tests;
+		public Map<String, String> serviceConfig;
+		//public UpdatedPolicies    updatedPolicies;
+		//public List<TestData>     updatedTests;
+		public Set<String>        superUsers;
+		public Set<String>        superGroups;
+		public Set<String>        auditExcludedUsers;
+		public Set<String>        auditExcludedGroups;
+		public Set<String>        auditExcludedRoles;
+
+		static class TestsInfo {
+			public List<TestData>     tests;
+			public UpdatedPolicies    updatedPolicies;
+			public TestsInfo          updatedTestsInfo;
+
+		}
+		static class TestData {
+			public String              name;
+			public RangerAccessRequest request;
+			public RangerAccessResult  result;
+			public RangerAccessResult  dataMaskResult;
+			public RangerAccessResult rowFilterResult;
+			public RangerResourceAccessInfo resourceAccessInfo;
+		}
+
+		static class TagPolicyInfo {
+			public String	serviceName;
+			public RangerServiceDef serviceDef;
+			public Map<String, String> serviceConfig;
+			public List<RangerPolicy> tagPolicies;
+		}
+	}
+
+	static class UpdatedPolicies {
+		public Map<String, ServicePolicies.SecurityZoneInfo> securityZones;
+		public List<RangerPolicyDelta>                       policyDeltas;
+	}
+
+    static class RangerAccessRequestDeserializer implements JsonDeserializer<RangerAccessRequest> {
+		@Override
+		public RangerAccessRequest deserialize(JsonElement jsonObj, Type type,
+				JsonDeserializationContext context) throws JsonParseException {
+			RangerAccessRequestImpl ret = gsonBuilder.fromJson(jsonObj, RangerAccessRequestImpl.class);
+
+			ret.setAccessType(ret.getAccessType()); // to force computation of isAccessTypeAny and isAccessTypeDelegatedAdmin
+			if (ret.getAccessTime() == null) {
+				ret.setAccessTime(new Date());
+			}
+
+			return ret;
+		}
+	}
+	
+	static class RangerResourceDeserializer implements JsonDeserializer<RangerAccessResource> {
+		@Override
+		public RangerAccessResource deserialize(JsonElement jsonObj, Type type,
+				JsonDeserializationContext context) throws JsonParseException {
+			return gsonBuilder.fromJson(jsonObj, RangerAccessResourceImpl.class);
+		}
+	}
+
+}
+
diff --git a/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_incremental_delete.json b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_incremental_delete.json
new file mode 100644
index 0000000..c74af3e
--- /dev/null
+++ b/agents-common/src/test/resources/policyengine/test_policyengine_hdfs_incremental_delete.json
@@ -0,0 +1,635 @@
+{
+  "serviceName":"hdfsdev",
+
+  "serviceDef":{
+    "name":"hdfs",
+    "id":1,
+    "resources":[
+      {"name":"path","type":"path","level":10,"mandatory":true,"lookupSupported":true,"recursiveSupported": true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":false},"label":"Resource Path","description":"HDFS file or directory path"}
+    ],
+    "accessTypes":[
+      {"itemId": 1, "name":"read","label":"Read"},
+      {"itemId": 2, "name":"write","label":"Write"},
+      {"itemId": 3, "name":"execute","label":"Execute"}
+    ],
+    "contextEnrichers": [],
+    "policyConditions": []
+  },
+
+  "policies":[
+    {"id":1,"name":"policy_for_audits","isEnabled":true,"isAuditEnabled":true,
+      "resources":{"path":{"values":["/*"],"isRecursive":true}},
+      "policyItems":[]
+    }
+  ,
+    {"id":10,"name":"user1_/test?_notrecursive","isEnabled":true,"isAuditEnabled":true,
+      "resources":{"path":{"values":["/test?"],"isRecursive":false}},
+      "policyItems":[
+        {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+      ]
+    }
+  ],
+
+  "testsInfo" : {
+    "tests":[
+      {"name":"ALLOW test_01A_wildcard_true_recursive_false",
+        "request":{
+          "resource":{"elements":{"path":"/test1"}},
+          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1"
+        },
+        "result":{"isAudited":true,"isAllowed":true,"policyId":10}
+      }
+      ,
+      {"name":"DENY test_01B_wildcard_true_recursive_false",
+        "request":{
+          "resource":{"elements":{"path":"/test1/test11"}},
+          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/test11"
+        },
+        "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+      }
+      ,
+      {"name":"DENY test_01C_wildcard_true_recursive_false",
+        "request":{
+          "resource":{"elements":{"path":"/test12"}},
+          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12"
+        },
+        "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+      }
+    ],
+    "updatedPolicies": {
+      "policyDeltas": [
+        {"changeType": 2,
+          "policy": {
+            "id": 10,
+            "version": 1,
+            "policyType": 0,
+            "serviceType": "hdfs"
+          }
+        }
+      ,
+        {"changeType": 0,
+          "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+            "id":20,"name":"user1_/test?","isEnabled":true,"isAuditEnabled":true,
+            "resources":{"path":{"values":["/test?"],"isRecursive":true}},
+            "policyItems":[
+              {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+            ]
+          }
+        }
+      ]
+    },
+    "updatedTestsInfo" : {
+      "tests": [
+        {"name":"ALLOW test_02A_wildcard_true_recursive_true",
+          "request":{
+            "resource":{"elements":{"path":"/test1/test11"}},
+            "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/test11"
+          },
+          "result":{"isAudited":true,"isAllowed":true,"policyId":20}
+        }
+      ],
+      "updatedPolicies": {
+        "policyDeltas": [
+          {"changeType": 2,
+            "policy": {
+              "id": 20,
+              "version": 1,
+              "policyType": 0,
+              "serviceType": "hdfs"
+            }
+          }
+        ,
+          {"changeType": 0,
+            "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+              "id":30,"name":"user1_/test?a?_notrecursive","isEnabled":true,"isAuditEnabled":true,
+              "resources":{"path":{"values":["/test?a?"],"isRecursive":false}},
+              "policyItems":[
+                {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+              ]
+            }
+          }
+        ]
+      },
+      "updatedTestsInfo" : {
+        "tests": [
+          {"name":"ALLOW test_03A_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test1a1"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1a1"
+            },
+            "result":{"isAudited":true,"isAllowed":true,"policyId":30}
+          }
+          ,
+          {"name":"DENY test_03B_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test2A2"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test2A2"
+            },
+            "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+          }
+        ,
+          {"name":"DENY test_03C_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test1a12"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1a12"
+            },
+            "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+          }
+        ,
+          {"name":"DENY test_03D_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test12a1"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12a1"
+            },
+            "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+          }
+        ,
+          {"name":"DENY test_03E_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test12a12"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12a12"
+            },
+            "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+          }
+        ,
+          {"name":"DENY test_03F_wildcard_true_recursive_false",
+            "request":{
+              "resource":{"elements":{"path":"/test1a"}},
+              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1a"
+            },
+            "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+          }
+        ],
+        "updatedPolicies": {
+          "policyDeltas": [
+            {"changeType": 2,
+              "policy": {
+                "id": 30,
+                "version": 1,
+                "policyType": 0,
+                "serviceType": "hdfs"
+              }
+            }
+          ,
+            {"changeType": 0,
+              "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+                "id":40,"name":"user1_/test?a?_recursive","isEnabled":true,"isAuditEnabled":true,
+                "resources":{"path":{"values":["/test?a?"],"isRecursive":true}},
+                "policyItems":[
+                  {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                ]
+              }
+            }
+          ]
+        },
+        "updatedTestsInfo" : {
+          "tests": [
+            {"name":"ALLOW test_04A_wildcard_true_recursive_true",
+              "request":{
+                "resource":{"elements":{"path":"/test1a1/test11a1"}},
+                "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1a1/test11a1"
+              },
+              "result":{"isAudited":true,"isAllowed":true,"policyId":40}
+            }
+          ]
+          ,
+          "updatedPolicies": {
+            "policyDeltas": [
+              {"changeType": 2,
+                "policy": {
+                  "id": 40,
+                  "version": 1,
+                  "policyType": 0,
+                  "serviceType": "hdfs"
+                }
+              }
+            ,
+              {"changeType": 0,
+                "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+                  "id":50,"name":"user1_/test??_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                  "resources":{"path":{"values":["/test??"],"isRecursive":false}},
+                  "policyItems":[
+                    {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                  ]
+                }
+              }
+            ]
+          },
+          "updatedTestsInfo" : {
+            "tests": [
+              {"name":"ALLOW test_05A_wildcard_true_recursive_false",
+                "request":{
+                  "resource":{"elements":{"path":"/test12"}},
+                  "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12"
+                },
+                "result":{"isAudited":true,"isAllowed":true,"policyId":50}
+              },
+              {"name":"ALLOW test_05B_wildcard_true_recursive_false",
+                "request":{
+                  "resource":{"elements":{"path":"/test1"}},
+                  "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1"
+                },
+                "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+              },
+              {"name":"ALLOW test_05C_wildcard_true_recursive_false",
+                "request":{
+                  "resource":{"elements":{"path":"/test1a1"}},
+                  "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1a1"
+                },
+                "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+              }
+            ],
+            "updatedPolicies": {
+              "policyDeltas": [
+                {"changeType": 2,
+                  "policy": {
+                    "id": 50,
+                    "version": 1,
+                    "policyType": 0,
+                    "serviceType": "hdfs"
+                  }
+                }
+              ,
+                {"changeType": 0,
+                  "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+                    "id":60,"name":"user1_/test???_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                    "resources":{"path":{"values":["/test???"],"isRecursive":false}},
+                    "policyItems":[
+                      {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                    ]
+                  }
+                }
+              ]
+            },
+            "updatedTestsInfo" : {
+              "tests": [
+                {"name":"DENY test_06A_wildcard_true_recursive_false",
+                  "request":{
+                    "resource":{"elements":{"path":"/test12"}},
+                    "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12"
+                  },
+                  "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                },
+                {"name":"ALLOW test_06B_wildcard_true_recursive_false",
+                  "request":{
+                    "resource":{"elements":{"path":"/test1/1"}},
+                    "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1"
+                  },
+                  "result":{"isAudited":true,"isAllowed":true,"policyId":60}
+                },
+                {"name":"ALLOW test_06C_wildcard_true_recursive_false",
+                  "request":{
+                    "resource":{"elements":{"path":"/test123"}},
+                    "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test123"
+                  },
+                  "result":{"isAudited":true,"isAllowed":true,"policyId":60}
+                }
+              ],
+              "updatedPolicies": {
+                "policyDeltas": [
+                  {"changeType": 2,
+                    "policy": {
+                      "id": 60,
+                      "version": 1,
+                      "policyType": 0,
+                      "serviceType": "hdfs"
+                    }
+                  }
+                ,
+                  {"changeType": 0,
+                    "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+                      "id":70,"name":"user1_/test1/?_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                      "resources":{"path":{"values":["/test1/?"],"isRecursive":false}},
+                      "policyItems":[
+                        {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                      ]
+                    }
+                  }
+                ]
+              },
+              "updatedTestsInfo" : {
+                "tests": [
+                  {"name":"DENY test_07A_wildcard_true_recursive_false",
+                    "request":{
+                      "resource":{"elements":{"path":"/test1"}},
+                      "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1"
+                    },
+                    "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                  },
+                  {"name":"DENY test_07B_wildcard_true_recursive_false",
+                    "request":{
+                      "resource":{"elements":{"path":"/test1/test11"}},
+                      "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/test11"
+                    },
+                    "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                  },
+                  {"name":"ALLOW test_07C_wildcard_true_recursive_false",
+                    "request":{
+                      "resource":{"elements":{"path":"/test1/a"}},
+                      "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/a"
+                    },
+                    "result":{"isAudited":true,"isAllowed":true,"policyId":70}
+                  }
+                ],
+                "updatedPolicies": {
+                  "policyDeltas": [
+                    {"changeType": 2,
+                      "policy": {
+                        "id": 70,
+                        "version": 1,
+                        "policyType": 0,
+                        "serviceType": "hdfs"
+                      }
+                    }
+                  ,
+                    {"changeType": 0,
+                      "policy": {"serviceType": "hdfs", "policyType": 0, "version": 1,
+                        "id":80,"name":"user1_/test*_/test_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                        "resources":{"path":{"values":["/test*", "/test"],"isRecursive":false}},
+                        "policyItems":[
+                          {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                        ]
+                      }
+                    }
+                  ]
+                },
+                "updatedTestsInfo" : {
+                  "tests": [
+                    {"name":"ALLOW test_08A_wildcard_true_recursive_false",
+                      "request":{
+                        "resource":{"elements":{"path":"/test12"}},
+                        "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12"
+                      },
+                      "result":{"isAudited":true,"isAllowed":true,"policyId":80}
+                    }
+                  ,
+                    {"name":"ALLOW test_08B_wildcard_true_recursive_false",
+                      "request":{
+                        "resource":{"elements":{"path":"/test1/1"}},
+                        "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1"
+                      },
+                      "result":{"isAudited":true,"isAllowed":true,"policyId":80}
+                    }
+                  ,
+                    {"name":"ALLOW test_08C_wildcard_true_recursive_false",
+                      "request":{
+                        "resource":{"elements":{"path":"/test1/1/2"}},
+                        "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1/2"
+                      },
+                      "result":{"isAudited":true,"isAllowed":true,"policyId":80}
+                    }
+                  ,
+                    {"name":"ALLOW test_08D_wildcard_true_recursive_false",
+                      "request":{
+                        "resource":{"elements":{"path":"/test1/1/2/a.txt"}},
+                        "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1/2/a.txt"
+                      },
+                      "result":{"isAudited":true,"isAllowed":true,"policyId":80}
+                    }
+                  ],
+                  "updatedPolicies": {
+                    "policyDeltas": [
+                      {"changeType": 2,
+                        "policy": {
+                          "id": 80,
+                          "version": 1,
+                          "policyType": 0,
+                          "serviceType": "hdfs"
+                        }
+                      }
+                    ,
+                      {"changeType": 0,
+                        "policy": { "serviceType": "hdfs", "policyType": 0, "version": 1,
+                          "id":90,"name":"user1_/test*1*_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                          "resources":{"path":{"values":["/test*1*"],"isRecursive":false}},
+                          "policyItems":[
+                            {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                          ]
+                        }
+                      }
+                    ]
+                  },
+                  "updatedTestsInfo" : {
+                    "tests": [
+                      {"name":"ALLOW test_09A_wildcard_true_recursive_false ",
+                        "request":{
+                          "resource":{"elements":{"path":"/test1"}},
+                          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1"
+                        },
+                        "result":{"isAudited":true,"isAllowed":true,"policyId":90}
+                      },
+                      {"name":"ALLOW test_09B_wildcard_true_recursive_false ",
+                        "request":{
+                          "resource":{"elements":{"path":"/test1/1"}},
+                          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1"
+                        },
+                        "result":{"isAudited":true,"isAllowed":true,"policyId":90}
+                      },
+                      {"name":"ALLOW test_09C_wildcard_true_recursive_false ",
+                        "request":{
+                          "resource":{"elements":{"path":"/test1/1/2"}},
+                          "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1/2"
+                        },
+                        "result":{"isAudited":true,"isAllowed":true,"policyId":90}
+                      }
+                    ],
+                    "updatedPolicies": {
+                      "policyDeltas": [
+                        {"changeType": 2,
+                          "policy": {
+                            "id": 90,
+                            "version": 1,
+                            "policyType": 0,
+                            "serviceType": "hdfs"
+                          }
+                        }
+                      ,
+                        {"changeType": 0,
+                          "policy": { "serviceType": "hdfs", "policyType": 0, "version": 1,
+                            "id":100,"name":"user1_/test*1*2_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                            "resources":{"path":{"values":["/test*1*2"],"isRecursive":false}},
+                            "policyItems":[
+                              {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                            ]
+                          }
+                        }
+                      ]
+                    },
+                    "updatedTestsInfo" : {
+                      "tests": [
+                        {"name":"ALLOW test_10A_wildcard_true_recursive_false ",
+                          "request":{
+                            "resource":{"elements":{"path":"/test12"}},
+                            "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test12"
+                          },
+                          "result":{"isAudited":true,"isAllowed":true,"policyId":100}
+                        },
+                        {"name":"DENY test_10B_wildcard_true_recursive_false ",
+                          "request":{
+                            "resource":{"elements":{"path":"/test123"}},
+                            "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test123"
+                          },
+                          "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                        },
+                        {"name":"ALLOW test_10C_wildcard_true_recursive_false ",
+                          "request":{
+                            "resource":{"elements":{"path":"/test12a12"}},
+                            "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /testa12"
+                          },
+                          "result":{"isAudited":true,"isAllowed":true,"policyId":100}
+                        },
+                        {"name":"ALLOW test_10D_wildcard_true_recursive_false ",
+                          "request":{
+                            "resource":{"elements":{"path":"/test2/1/2"}},
+                            "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test2/1/2"
+                          },
+                          "result":{"isAudited":true,"isAllowed":true,"policyId":100}
+                        }
+                      ],
+                      "updatedPolicies": {
+                        "policyDeltas": [
+                          {"changeType": 2,
+                            "policy": {
+                              "id": 100,
+                              "version": 1,
+                              "policyType": 0,
+                              "serviceType": "hdfs"
+                            }
+                          }
+                        ,
+                          {"changeType": 0,
+                            "policy": { "serviceType": "hdfs", "policyType": 0, "version": 1,
+                              "id":110,"name":"user1_/test1/b*y.txt_/test2_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                              "resources":{"path":{"values":["/test1/b*y.txt", "/test2"],"isRecursive":false}},
+                              "policyItems":[
+                                {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                              ]
+                            }
+                          }
+                        ]
+                      },
+                      "updatedTestsInfo" : {
+                        "tests": [
+                          {"name":"ALLOW test_11A_wildcard_true_recursive_false ",
+                            "request":{
+                              "resource":{"elements":{"path":"/test1/boy.txt"}},
+                              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/boy.txt"
+                            },
+                            "result":{"isAudited":true,"isAllowed":true,"policyId":110}
+                          },
+                          {"name":"ALLOW test_11B_wildcard_true_recursive_false ",
+                            "request":{
+                              "resource":{"elements":{"path":"/test1/b1/a2/any.txt"}},
+                              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/b1/a1/any.txt"
+                            },
+                            "result":{"isAudited":true,"isAllowed":true,"policyId":110}
+                          },
+                          {"name":"ALLOW test_11C_wildcard_true_recursive_false ",
+                            "request":{
+                              "resource":{"elements":{"path":"/test1/by.txt"}},
+                              "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/by.txt"
+                            },
+                            "result":{"isAudited":true,"isAllowed":true,"policyId":110}
+                          }
+                        ],
+                        "updatedPolicies": {
+                          "policyDeltas": [
+                            {"changeType": 2,
+                              "policy": {
+                                "id": 110,
+                                "version": 1,
+                                "policyType": 0,
+                                "serviceType": "hdfs"
+                              }
+                            }
+                          ,
+                            {"changeType": 0,
+                              "policy": { "serviceType": "hdfs", "policyType": 0, "version": 1,
+                                "id":120,"name":"user1_/test1/*/a.txt_/test2_notrecursive","isEnabled":true,"isAuditEnabled":true,
+                                "resources":{"path":{"values":["/test1/*/a.txt", "/test2"],"isRecursive":false}},
+                                "policyItems":[
+                                  {"accesses":[{"type":"read","isAllowed":true}, {"type":"write","isAllowed":true}, {"type":"execute","isAllowed":true}],"users":["hrt_21"],"groups":[],"delegateAdmin":false}
+                                ]
+                              }
+                            }
+                          ]
+                        },
+                        "updatedTestsInfo" : {
+                          "tests": [
+                            {"name":"ALLOW test_12A_wildcard_true_recursive_false_target_dir ",
+                              "request":{
+                                "resource":{"elements":{"path":"/test2"}},
+                                "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test2"
+                              },
+                              "result":{"isAudited":true,"isAllowed":true,"policyId":120}
+                            },
+                            {"name":"DENY test_12A_wildcard_true_recursive_false ",
+                              "request":{
+                                "resource":{"elements":{"path":"/test1/a.txt"}},
+                                "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/a.txt"
+                              },
+                              "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                            },
+                            {"name":"ALLOW test_12B_wildcard_true_recursive_false ",
+                              "request":{
+                                "resource":{"elements":{"path":"/test1/1/2/a.txt"}},
+                                "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1/2/a.txt"
+                              },
+                              "result":{"isAudited":true,"isAllowed":true,"policyId":120}
+                            },
+                            {"name":"DENY test_12C_wildcard_true_recursive_false ",
+                              "request":{
+                                "resource":{"elements":{"path":"/test1/1/2/ba.txt"}},
+                                "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test1/1/2/ba.txt"
+                              },
+                              "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                            }
+                          ],
+                          "updatedPolicies": {
+                            "policyDeltas": [
+                              {"changeType": 2,
+                                "policy": {
+                                  "id": 120,
+                                  "version": 1,
+                                  "policyType": 0,
+                                  "serviceType": "hdfs"
+                                }
+                              }
+                            ]
+                          },
+                          "updatedTestsInfo" : {
+                            "tests": [
+                              {"name":"DENY test_13_wildcard_true_recursive_false ",
+                                "request":{
+                                  "resource":{"elements":{"path":"/test2"}},
+                                  "accessType":"write","user":"hrt_21","userGroups":[],"requestData":"write /test2"
+                                },
+                                "result":{"isAudited":true,"isAllowed":false,"policyId":-1}
+                              }
+                            ],
+                            "updatedPolicies": {
+                              "policyDeltas": [
+                                {"changeType": 2,
+                                  "policy": {
+                                    "id": 1,
+                                    "version": 1,
+                                    "policyType": 0,
+                                    "serviceType": "hdfs"
+                                  }
+                                }
+                              ]
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index f6951f6..d026dec 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -1555,7 +1555,7 @@
     <named-query name="XXPolicyChangeLog.findSinceVersion">
         <query>
             select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
-            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.policyVersion >= :version order by
+            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.serviceType != 'tag' and obj.policyVersion >= :version order by
             obj.policyVersion
         </query>
     </named-query>
@@ -1563,7 +1563,7 @@
     <named-query name="XXPolicyChangeLog.findGreaterThan">
         <query>
             select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
-            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.id > :id order by obj.id
+            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.serviceType = 'tag' and obj.id > :id order by obj.id
         </query>
     </named-query>