You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by rm...@apache.org on 2019/10/10 00:53:29 UTC

[ranger] branch master updated: RANGER-2512:RangerRolesRESTClient for serving user group roles to the plugins for evaluation -part3

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

rmani 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 3eef840  RANGER-2512:RangerRolesRESTClient for serving user group roles to the plugins for evaluation -part3
3eef840 is described below

commit 3eef84032aa7b2a55fa0ae5383739b2336d5de6c
Author: rmani <rm...@hortonworks.com>
AuthorDate: Wed Oct 9 16:58:48 2019 -0700

    RANGER-2512:RangerRolesRESTClient for serving user group roles to the plugins for evaluation -part3
    
    Signed-off-by: rmani <rm...@hortonworks.com>
---
 .../policyengine/RangerPolicyEngineCache.java      |  88 +++++++++++++---
 .../RangerPolicyEngineCacheForEngineOptions.java   |   9 +-
 .../org/apache/ranger/plugin/store/RoleStore.java  |   5 +
 .../java/org/apache/ranger/biz/RoleDBStore.java    |  63 +++++++-----
 .../java/org/apache/ranger/biz/ServiceDBStore.java | 112 +++++++++++++++++----
 .../java/org/apache/ranger/db/XXPolicyDao.java     |   8 +-
 .../main/java/org/apache/ranger/db/XXRoleDao.java  |  13 +++
 .../java/org/apache/ranger/rest/ServiceREST.java   |  10 +-
 .../apache/ranger/service/RangerRoleService.java   |  20 ++++
 .../main/resources/META-INF/jpa_named_queries.xml  |   8 +-
 10 files changed, 265 insertions(+), 71 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
index 251a0ec..33152e6 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCache.java
@@ -33,8 +33,10 @@ import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicyDelta;
 import org.apache.ranger.plugin.model.RangerSecurityZone;
 import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.store.RoleStore;
 import org.apache.ranger.plugin.store.SecurityZoneStore;
 import org.apache.ranger.plugin.store.ServiceStore;
+import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.ServicePolicies;
 
 public class RangerPolicyEngineCache {
@@ -42,27 +44,69 @@ public class RangerPolicyEngineCache {
 
 	private final Map<String, RangerPolicyEngine> policyEngineCache = new HashMap<String, RangerPolicyEngine>();
 
-	synchronized final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, SecurityZoneStore zoneStore, RangerPolicyEngineOptions options) {
+	synchronized final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, RoleStore roleStore, SecurityZoneStore zoneStore, RangerPolicyEngineOptions options) {
 		RangerPolicyEngine ret = null;
 
 		if(serviceName != null) {
 			ret = policyEngineCache.get(serviceName);
 
-			long policyVersion = ret != null ? ret.getPolicyVersion() : -1;
-
 			if(svcStore != null) {
+				long        policyVersion;
+				long        roleVersion;
+				RangerRoles rangerRoles;
+				boolean     isRolesUpdated = true;
+
 				try {
+					if (ret == null) {
+						policyVersion = -1L;
+						roleVersion = -1L;
+						rangerRoles = roleStore.getRangerRoles(serviceName, roleVersion);
+
+						if (rangerRoles == null) {
+							if (LOG.isDebugEnabled()) {
+								LOG.debug("There are no roles in ranger-admin for service:" + serviceName +"]");
+							}
+						}
+					} else {
+						policyVersion = ret.getPolicyVersion();
+
+						if (ret.getRangerRoles() != null && ret.getRangerRoles().getRoleVersion() != null) {
+							roleVersion = ret.getRangerRoles().getRoleVersion();
+						} else {
+							roleVersion = -1L;
+						}
+
+						rangerRoles = roleStore.getRangerRoles(serviceName, roleVersion);
+
+						if (rangerRoles == null) {
+							rangerRoles = ret.getRangerRoles();
+							isRolesUpdated = false;
+						}
+					}
+
 					ServicePolicies policies = svcStore.getServicePoliciesIfUpdated(serviceName, policyVersion, false);
 
-					if (policies != null && policies.getPolicyVersion() != null && !policies.getPolicyVersion().equals(policyVersion)) {
-						ServicePolicies updatedServicePolicies = policies;
-						if (zoneStore != null) {
-							Map<String, RangerSecurityZone.RangerSecurityZoneService> securityZones = zoneStore.getSecurityZonesForService(serviceName);
-							if (MapUtils.isNotEmpty(securityZones)) {
-								updatedServicePolicies = getUpdatedServicePoliciesForZones(policies, securityZones);
+					if (policies != null) {
+						if (policies.getPolicyVersion() != null && !policies.getPolicyVersion().equals(policyVersion)) {
+							ServicePolicies updatedServicePolicies = getUpdatedServicePolicies(serviceName, policies, svcStore, zoneStore);
+
+							if (ret == null) {
+								ret = addPolicyEngine(updatedServicePolicies, rangerRoles, options);
+							} else {
+								ret = updatePolicyEngine(ret, updatedServicePolicies, rangerRoles, options);
+							}
+						} else {
+							LOG.error("policies object is null or its version is null for getPolicyEngine(" + serviceName + ") !!");
+							LOG.error("Returning old policy engine");
+						}
+					} else {
+						if (ret == null) {
+							LOG.error("getPolicyEngine(" + serviceName + "): failed to get any policies from service-store");
+						} else {
+							if (isRolesUpdated) {
+								ret.setRangerRoles(rangerRoles);
 							}
 						}
-						ret = ret == null ? addPolicyEngine(updatedServicePolicies, options) : updatePolicyEngine(ret, updatedServicePolicies, options);
 					}
 
 				} catch(Exception excp) {
@@ -75,24 +119,24 @@ public class RangerPolicyEngineCache {
 	}
 
 
-	private RangerPolicyEngine addPolicyEngine(ServicePolicies policies, RangerPolicyEngineOptions options) {
+	private RangerPolicyEngine addPolicyEngine(ServicePolicies policies, RangerRoles rangerRoles, RangerPolicyEngineOptions options) {
 		RangerServiceDef serviceDef = policies.getServiceDef();
 		String serviceType = (serviceDef != null) ? serviceDef.getName() : "";
 
 		RangerPluginContext rangerPluginContext = new RangerPluginContext(serviceType);
-		RangerPolicyEngine ret = new RangerPolicyEngineImpl("ranger-admin", policies, options, rangerPluginContext);
+		RangerPolicyEngine ret = new RangerPolicyEngineImpl("ranger-admin", policies, options, rangerPluginContext, rangerRoles);
 
 		policyEngineCache.put(policies.getServiceName(), ret);
 
 		return ret;
 	}
 
-	private RangerPolicyEngine updatePolicyEngine(RangerPolicyEngine policyEngine, ServicePolicies policies, RangerPolicyEngineOptions options) {
+	private RangerPolicyEngine updatePolicyEngine(RangerPolicyEngine policyEngine, ServicePolicies policies, RangerRoles rangerRoles, RangerPolicyEngineOptions options) {
 		final RangerPolicyEngine ret;
 
 
 		if (CollectionUtils.isNotEmpty(policies.getPolicyDeltas())) {
-			RangerPolicyEngine updatedEngine = policyEngine.cloneWithDelta(policies, policyEngine.getRangerRoles());
+			RangerPolicyEngine updatedEngine = policyEngine.cloneWithDelta(policies, rangerRoles);
 			if (updatedEngine != null) {
 				policyEngineCache.put(policies.getServiceName(), updatedEngine);
 				ret = updatedEngine;
@@ -102,13 +146,27 @@ public class RangerPolicyEngineCache {
 				ret = policyEngine;
 			}
 		} else {
-			ret = addPolicyEngine(policies, options);
+			ret = addPolicyEngine(policies, rangerRoles, options);
 			((RangerPolicyEngineImpl)policyEngine).setIsShared(false);
 		}
 
 		return ret;
 	}
 
+	private ServicePolicies getUpdatedServicePolicies(String serviceName, ServicePolicies policies, ServiceStore svcStore, SecurityZoneStore zoneStore) throws  Exception{
+		ServicePolicies ret = policies;
+		if (ret == null) {
+			ret = svcStore.getServicePoliciesIfUpdated(serviceName, -1L, false);
+		}
+		if (zoneStore != null) {
+			Map<String, RangerSecurityZone.RangerSecurityZoneService> securityZones = zoneStore.getSecurityZonesForService(serviceName);
+			if (MapUtils.isNotEmpty(securityZones)) {
+				ret = getUpdatedServicePoliciesForZones(ret, securityZones);
+			}
+		}
+		return ret;
+	}
+
 	public static ServicePolicies getUpdatedServicePoliciesForZones(ServicePolicies servicePolicies, Map<String, RangerSecurityZone.RangerSecurityZoneService> securityZones) {
 
 		final ServicePolicies ret;
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCacheForEngineOptions.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCacheForEngineOptions.java
index 5cd82d8..11450ae 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCacheForEngineOptions.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineCacheForEngineOptions.java
@@ -19,6 +19,7 @@
 
 package org.apache.ranger.plugin.policyengine;
 
+import org.apache.ranger.plugin.store.RoleStore;
 import org.apache.ranger.plugin.store.SecurityZoneStore;
 import org.apache.ranger.plugin.store.ServiceStore;
 
@@ -46,11 +47,11 @@ public class RangerPolicyEngineCacheForEngineOptions {
         return ret;
     }
 
-    public final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, RangerPolicyEngineOptions options) {
-        return getPolicyEngine(serviceName, svcStore, null, options);
+    public final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, RoleStore roleStore, RangerPolicyEngineOptions options) {
+        return getPolicyEngine(serviceName, svcStore, roleStore, null, options);
     }
 
-    public final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, SecurityZoneStore zoneStore, RangerPolicyEngineOptions options) {
+    public final RangerPolicyEngine getPolicyEngine(String serviceName, ServiceStore svcStore, RoleStore roleStore, SecurityZoneStore zoneStore, RangerPolicyEngineOptions options) {
 
         RangerPolicyEngineCache policyEngineCache;
 
@@ -61,7 +62,7 @@ public class RangerPolicyEngineCacheForEngineOptions {
                 policyEngineCacheForEngineOptions.put(options, policyEngineCache);
             }
         }
-        return policyEngineCache.getPolicyEngine(serviceName, svcStore, zoneStore, options);
+        return policyEngineCache.getPolicyEngine(serviceName, svcStore, roleStore, zoneStore, options);
     }
 }
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/RoleStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/RoleStore.java
index 2fec9a0..8bf4603 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/RoleStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/RoleStore.java
@@ -22,6 +22,7 @@ package org.apache.ranger.plugin.store;
 import java.util.List;
 
 import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.SearchFilter;
 
 public interface RoleStore {
@@ -43,5 +44,9 @@ public interface RoleStore {
     List<RangerRole> getRoles(SearchFilter filter) throws Exception;
 
     List<String>     getRoleNames(SearchFilter filter) throws Exception;
+
+    RangerRoles getRangerRoles(String serviceName, Long lastKnownRoleVersion) throws Exception;
+
+    Long getRoleVersion(String serviceName);
 }
 
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
index 9151a72..dfc5be8 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
@@ -136,7 +136,9 @@ public class RoleDBStore implements RoleStore {
 
         roleService.updatePolicyVersions(updatedRole.getId());
 
-        roleService.updateRoleVersions(updatedRole.getId());
+        if (ServiceDBStore.isSupportsRolesDownloadByService()) {
+            roleService.updateRoleVersions(updatedRole.getId());
+        }
 
         List<XXTrxLog> trxLogList = roleService.getTransactionLog(updatedRole, oldRole, "update");
         bizUtil.createTrxLog(trxLogList);
@@ -213,6 +215,40 @@ public class RoleDBStore implements RoleStore {
         return daoMgr.getXXRole().getAllNames();
     }
 
+    @Override
+    public RangerRoles getRangerRoles(String serviceName, Long lastKnownRoleVersion) throws Exception {
+        RangerRoles ret                   = null;
+        Long        rangerRoleVersionInDB = getRoleVersion(serviceName);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB);
+        }
+
+        if (rangerRoleVersionInDB != null) {
+            ret = RangerRoleCache.getInstance().getLatestRangerRoleOrCached(serviceName, this, lastKnownRoleVersion, rangerRoleVersionInDB);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<= RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB + " RangerRoles= " + ret);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public Long getRoleVersion(String serviceName) {
+        Long ret = null;
+
+        if (ServiceDBStore.isSupportsRolesDownloadByService()) {
+            XXServiceVersionInfo xxServiceVersionInfo = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
+            ret = (xxServiceVersionInfo != null) ? xxServiceVersionInfo.getRoleVersion() : null;
+        } else {
+            ret = daoMgr.getXXGlobalState().getRoleVersion(RANGER_ROLE_GLOBAL_STATE_NAME);
+        }
+
+        return ret;
+    }
+
     public Set<RangerRole> getRoleNames(String userName, Set<String> userGroups) throws Exception{
         Set<RangerRole> ret = new HashSet<>();
         if (StringUtils.isNotEmpty(userName)) {
@@ -276,30 +312,5 @@ public class RoleDBStore implements RoleStore {
     public List<RangerRole> getRoles(XXService service) {
         return service == null ? ListUtils.EMPTY_LIST : getRoles(service.getId());
     }
-
-    public RangerRoles getRangerRoles(String serviceName, Long lastKnownRoleVersion) throws Exception {
-        RangerRoles ret                   = null;
-        Long        rangerRoleVersionInDB = getRoleVersion(serviceName);
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("==> RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB);
-        }
-
-        if (rangerRoleVersionInDB != null) {
-            ret = RangerRoleCache.getInstance().getLatestRangerRoleOrCached(serviceName, this, lastKnownRoleVersion, rangerRoleVersionInDB);
-        }
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("<= RoleDBStore.getRangerRoles() lastKnownRoleVersion= " + lastKnownRoleVersion + " rangerRoleVersionInDB= " + rangerRoleVersionInDB + " RangerRoles= " + ret);
-        }
-
-        return ret;
-    }
-
-    public Long getRoleVersion(String serviceName) {
-        XXServiceVersionInfo xxServiceVersionInfo =  daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
-        return (xxServiceVersionInfo != null) ? xxServiceVersionInfo.getRoleVersion():null;
-    }
-
 }
 
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 edc886c..ec44aa1 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
@@ -231,6 +231,8 @@ public class ServiceDBStore extends AbstractServiceStore {
     private static final String AMBARI_SERVICE_CHECK_USER = "ambari.service.check.user";
 	private static final String SERVICE_ADMIN_USERS     = "service.admin.users";
 
+	private static boolean isRolesDownloadedByService = false;
+
 	public static final String  CRYPT_ALGO      = PropertiesUtil.getProperty("ranger.password.encryption.algorithm", PasswordUtils.DEFAULT_CRYPT_ALGO);
 	public static final String  ENCRYPT_KEY     = PropertiesUtil.getProperty("ranger.password.encryption.key", PasswordUtils.DEFAULT_ENCRYPT_KEY);
 	public static final String  SALT            = PropertiesUtil.getProperty("ranger.password.salt", PasswordUtils.DEFAULT_SALT);
@@ -370,6 +372,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 					RETENTION_PERIOD_IN_DAYS     = RangerConfiguration.getInstance().getInt("ranger.admin.delta.retention.time.in.days", 7);
 					TAG_RETENTION_PERIOD_IN_DAYS = 	RangerConfiguration.getInstance().getInt("ranger.admin.tag.delta.retention.time.in.days", 3);
 
+					isRolesDownloadedByService = RangerConfiguration.getInstance().getBoolean("ranger.support.for.service.specific.role.download", false);
 
 					TransactionTemplate txTemplate = new TransactionTemplate(txManager);
 
@@ -1933,7 +1936,10 @@ public class ServiceDBStore extends AbstractServiceStore {
 		policy.setVersion(Long.valueOf(1));
 		updatePolicySignature(policy);
 
-		boolean updateServiceInfoRoleVersion = isRoleDownloadRequired(policy, service.getId());
+		boolean updateServiceInfoRoleVersion = false;
+		if (isSupportsRolesDownloadByService()) {
+			updateServiceInfoRoleVersion = isRoleDownloadRequired(policy, service);
+		}
 
 		if(populateExistingBaseFields) {
 			assignedIdPolicyService.setPopulateExistingBaseFields(true);
@@ -2072,7 +2078,10 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 		updatePolicySignature(policy);
 
-		boolean updateServiceInfoRoleVersion = isRoleDownloadRequired(policy, service.getId());
+		boolean updateServiceInfoRoleVersion = false;
+		if (isSupportsRolesDownloadByService()) {
+			updateServiceInfoRoleVersion = isRoleDownloadRequired(policy, service);
+		}
 
 		policy = policyService.update(policy);
 		XXPolicy newUpdPolicy = daoMgr.getXXPolicy().getById(policy.getId());
@@ -3330,6 +3339,9 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 					Runnable tagServiceVersionUpdater = new ServiceVersionUpdater(daoManager, referringServiceId, tagServiceversionType, policy != null ? policy.getZoneName() : null, policyDeltaType, policy);
 					transactionSynchronizationAdapter.executeOnTransactionCommit(tagServiceVersionUpdater);
+
+					Runnable roleVersionUpdater = new ServiceVersionUpdater(daoManager, referringServiceId, VERSION_TYPE.ROLE_VERSION, policy != null ? policy.getZoneName() : null, policyDeltaType, policy);
+					transactionSynchronizationAdapter.executeOnTransactionCommit(roleVersionUpdater);
 				}
 			}
 		}
@@ -3403,28 +3415,24 @@ public class ServiceDBStore extends AbstractServiceStore {
 		}
 	}
 
-	private boolean isRoleDownloadRequired(RangerPolicy policy, Long serviceId) {
+	private boolean isRoleDownloadRequired(RangerPolicy policy, RangerService service) {
 		// Role Download to plugin is required if some role in the policy created/updated is not present in any other
 		// policy for that service.
 		boolean ret = false;
 
 		if (policy != null) {
-			List<RangerPolicy.RangerPolicyItem> rangerPolicyItems = policy.getPolicyItems();
-			if (CollectionUtils.isNotEmpty(rangerPolicyItems)) {
-				for (RangerPolicyItem rangerPolicyItem : rangerPolicyItems) {
-					List<String> roleNames = rangerPolicyItem.getRoles();
-					if (CollectionUtils.isNotEmpty(roleNames)) {
-						for (String roleName : roleNames) {
-							List<Long> policyIds = daoMgr.getXXPolicy().findPolicyIdsByRoleNameAndServiceId(roleName, serviceId);
-							if (CollectionUtils.isEmpty(policyIds)) {
-								ret = true;
-								break;
-							}
+			Set<String> roleNames = getAllPolicyItemRoleNames(policy);
+			if (CollectionUtils.isNotEmpty(roleNames)) {
+				Long serviceId = service.getId();
+				checkAndFilterRoleNames(roleNames, service);
+				if (CollectionUtils.isNotEmpty(roleNames)) {
+					for (String roleName : roleNames) {
+						long roleRefPolicyCount = daoMgr.getXXPolicy().findRoleRefPolicyCount(roleName, serviceId);
+						if (roleRefPolicyCount == 0) {
+							ret = true;
+							break;
 						}
 					}
-					if (ret) {
-						break;
-					}
 				}
 			}
 		}
@@ -3432,6 +3440,72 @@ public class ServiceDBStore extends AbstractServiceStore {
 		return ret;
 	}
 
+	private void checkAndFilterRoleNames(Set<String> roleNames, RangerService service) {
+		//remove all roles which are already in DB for this serviceId, so we just download roles if there are new roles added.
+		Set<String>  rolesToRemove = new HashSet<>();
+		Long 		 serviceId     = service.getId();
+		List<String> rolesFromDb   = daoMgr.getXXRole().findRoleNamesByServiceId(serviceId);
+		if(CollectionUtils.isNotEmpty(rolesFromDb)) {
+			rolesToRemove.addAll(rolesFromDb);
+		}
+
+		String    tagService   = service.getTagService();
+		XXService serviceDbObj = daoMgr.getXXService().findByName(tagService);
+		if (serviceDbObj != null) {
+			List<String> rolesFromServiceTag = daoMgr.getXXRole().findRoleNamesByServiceId(serviceDbObj.getId());
+			if (CollectionUtils.isNotEmpty(rolesFromServiceTag)) {
+				rolesToRemove.addAll(rolesFromServiceTag);
+			}
+		}
+
+		roleNames.removeAll(rolesToRemove);
+	}
+
+	private Set<String> getAllPolicyItemRoleNames(RangerPolicy policy) {
+		Set<String> ret = new HashSet<>();
+
+		List<? extends RangerPolicy.RangerPolicyItem> policyItems = policy.getPolicyItems();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		policyItems = policy.getDenyPolicyItems();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		policyItems = policy.getAllowExceptions();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		policyItems = policy.getDenyExceptions();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		policyItems = policy.getDataMaskPolicyItems();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		policyItems = policy.getRowFilterPolicyItems();
+		if (CollectionUtils.isNotEmpty(policyItems)) {
+			collectRolesFromPolicyItems(policyItems, ret);
+		}
+
+		return ret;
+	}
+
+	private void collectRolesFromPolicyItems(List<? extends RangerPolicyItem> rangerPolicyItems, Set<String> roleNames) {
+		for (RangerPolicyItem rangerPolicyItem : rangerPolicyItems) {
+			List<String> rangerPolicyItemRoles = rangerPolicyItem.getRoles();
+			if (CollectionUtils.isNotEmpty(rangerPolicyItemRoles)) {
+				roleNames.addAll(rangerPolicyItemRoles);
+			}
+		}
+	}
+
 	private static void persistChangeLog(ServiceVersionUpdater serviceVersionUpdater) {
 		XXServiceVersionInfoDao serviceVersionInfoDao = serviceVersionUpdater.daoManager.getXXServiceVersionInfo();
 
@@ -5127,6 +5201,10 @@ public class ServiceDBStore extends AbstractServiceStore {
 		return SUPPORTS_POLICY_DELTAS;
 	}
 
+	public static boolean isSupportsRolesDownloadByService() {
+		return isRolesDownloadedByService;
+	}
+
 	public static class ServiceVersionUpdater implements Runnable {
 		final Long 			   serviceId;
 		final RangerDaoManager daoManager;
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
index 0d46ca8..b242171 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyDao.java
@@ -222,13 +222,13 @@ public class XXPolicyDao extends BaseDao<XXPolicy> {
 		return ret;
 	}
 
-	public List<Long> findPolicyIdsByRoleNameAndServiceId(String roleName, Long serviceId) {
-		List<Long> ret = null;
+	public long findRoleRefPolicyCount(String roleName, Long serviceId) {
+		long ret = -1;
 		try {
 			return getEntityManager()
-					.createNamedQuery("XXPolicy.findPolicyIdsByRoleNameAndServiceId", Long.class)
+					.createNamedQuery("XXPolicy.findRoleRefPolicyCount", Long.class)
 					.setParameter("serviceId", serviceId)
-					.setParameter("roleName", roleName).getResultList();
+					.setParameter("roleName", roleName).getSingleResult();
 		} catch (Exception e) {
 		}
 		return ret;
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
index c1ec629..8528652 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXRoleDao.java
@@ -76,6 +76,19 @@ public class XXRoleDao extends BaseDao<XXRole> {
         return ret;
     }
 
+    public List<String> findRoleNamesByServiceId(Long serviceId) {
+        List<String> ret;
+        try {
+            ret = getEntityManager()
+                    .createNamedQuery("XXRole.findRoleNamesByServiceId", String.class)
+                    .setParameter("serviceId", serviceId)
+                    .getResultList();
+        } catch (NoResultException e) {
+            ret = ListUtils.EMPTY_LIST;
+        }
+        return ret;
+    }
+
     public List<String> getAllNames() {
         try {
             return getEntityManager().createNamedQuery("XXRole.getAllNames", String.class).getResultList();
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
index 12b78f0..5b38033 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/ServiceREST.java
@@ -62,6 +62,7 @@ import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
 import org.apache.ranger.authorization.utils.StringUtil;
 import org.apache.ranger.biz.AssetMgr;
 import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.biz.RoleDBStore;
 import org.apache.ranger.biz.SecurityZoneDBStore;
 import org.apache.ranger.biz.ServiceDBStore;
 import org.apache.ranger.biz.ServiceMgr;
@@ -191,6 +192,9 @@ public class ServiceREST {
 	ServiceDBStore svcStore;
 
 	@Autowired
+	RoleDBStore roleDBStore;
+
+	@Autowired
 	SecurityZoneDBStore zoneStore;
 
 	@Autowired
@@ -3657,15 +3661,15 @@ public class ServiceREST {
 	}
 
 	public RangerPolicyEngine getDelegatedAdminPolicyEngine(String serviceName) {
-		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, delegateAdminOptions);
+		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, roleDBStore, delegateAdminOptions);
 	}
 
 	private RangerPolicyEngine getPolicySearchPolicyEngine(String serviceName) throws Exception {
-		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, policySearchAdminOptions);
+		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, roleDBStore, policySearchAdminOptions);
 	}
 
 	private RangerPolicyEngine getPolicyEngine(String serviceName) throws Exception {
-		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, defaultAdminOptions);
+		return RangerPolicyEngineCacheForEngineOptions.getInstance().getPolicyEngine(serviceName, svcStore, roleDBStore, defaultAdminOptions);
 	}
 
 	@GET
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
index e168278..ce2dc35 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerRoleService.java
@@ -34,12 +34,16 @@ import org.apache.ranger.biz.ServiceDBStore;
 import org.apache.ranger.common.AppConstants;
 import org.apache.ranger.common.RangerConstants;
 import org.apache.ranger.common.view.VTrxLogAttr;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXServiceDao;
 import org.apache.ranger.entity.XXPortalUser;
 import org.apache.ranger.entity.XXRole;
+import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXTrxLog;
 import org.apache.ranger.entity.XXUser;
 import org.apache.ranger.plugin.model.RangerPolicyDelta;
 import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.util.RangerEnumUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;
@@ -360,10 +364,16 @@ public class RangerRoleService extends RangerRoleServiceBase<XXRole, RangerRole>
                 allAffectedServiceIds.addAll(affectedServiceIds);
             }
 
+            XXServiceDao serviceDao = daoMgr.getXXService();
             if (CollectionUtils.isNotEmpty(allAffectedServiceIds)) {
                 for (final Long serviceId : allAffectedServiceIds) {
                     Runnable serviceVersionUpdater = new ServiceDBStore.ServiceVersionUpdater(daoMgr, serviceId, ServiceDBStore.VERSION_TYPE.ROLE_VERSION, null, RangerPolicyDelta.CHANGE_TYPE_ROLE_UPDATE, null);
                     daoMgr.getRangerTransactionSynchronizationAdapter().executeOnTransactionCommit(serviceVersionUpdater);
+                    XXService serviceDbObj = serviceDao.getById(serviceId);
+                    boolean   isTagService = serviceDbObj.getType() == EmbeddedServiceDefsUtil.instance().getTagServiceDefId();
+                    if (isTagService) {
+                        updateRoleVersionOfAllServicesRefferingTag(daoMgr, serviceDao, serviceId);
+                    }
                 }
             }
         }
@@ -373,5 +383,15 @@ public class RangerRoleService extends RangerRoleServiceBase<XXRole, RangerRole>
         }
     }
 
+    private void updateRoleVersionOfAllServicesRefferingTag(RangerDaoManager daoManager, XXServiceDao serviceDao, Long serviceId) {
+        List<XXService> referringServices = serviceDao.findByTagServiceId(serviceId);
+        if(CollectionUtils.isNotEmpty(referringServices)) {
+            for(XXService referringService : referringServices) {
+                final Long referringServiceId = referringService.getId();
+                Runnable   roleVersionUpdater = new ServiceDBStore.ServiceVersionUpdater(daoManager, referringServiceId, ServiceDBStore.VERSION_TYPE.ROLE_VERSION, null, RangerPolicyDelta.CHANGE_TYPE_ROLE_UPDATE, null);
+                daoMgr.getRangerTransactionSynchronizationAdapter().executeOnTransactionCommit(roleVersionUpdater);
+            }
+        }
+    }
 }
 
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 1a6b0bd..7e21399 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
@@ -312,8 +312,8 @@
 		<query>select DISTINCT(obj.service) from XXPolicy obj, XXPolicyRefRole policyRefRole where policyRefRole.roleId = :roleId and policyRefRole.policyId = obj.id</query>
 	</named-query>
 
-	<named-query name="XXPolicy.findPolicyIdsByRoleNameAndServiceId">
-		<query>select roleRef.policyId
+	<named-query name="XXPolicy.findRoleRefPolicyCount">
+		<query>select count(roleRef.policyId)
 			from XXPolicy policy, XXPolicyRefRole roleRef
 			where policy.service  = :serviceId
 			and roleRef.policyId  = policy.id
@@ -1500,6 +1500,10 @@
 		<query>select obj from XXRole obj, XXPolicyRefRole policyRefRole, XXPolicy policy where obj.id = policyRefRole.roleId and policyRefRole.policyId = policy.id and policy.service = :serviceId </query>
 	</named-query>
 
+	<named-query name="XXRole.findRoleNamesByServiceId">
+		<query>select obj.name from XXRole obj, XXPolicyRefRole policyRefRole, XXPolicy policy where obj.id = policyRefRole.roleId and policyRefRole.policyId = policy.id and policy.service = :serviceId </query>
+	</named-query>
+
     <named-query name="XXRole.getAllNames">
         <query>select obj.name from XXRole obj</query>
     </named-query>