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 2020/12/23 20:23:34 UTC

[ranger] branch master updated: RANGER-3122: Support delegate-admin for specific permissions

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 9d459e0  RANGER-3122: Support delegate-admin for specific permissions
9d459e0 is described below

commit 9d459e0255484277d802b5d8e9fcdd936f3aed04
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Wed Dec 23 12:06:56 2020 -0800

    RANGER-3122: Support delegate-admin for specific permissions
---
 .../RangerDefaultPolicyEvaluator.java              | 66 +++++++++++-----
 .../RangerOptimizedPolicyEvaluator.java            | 26 +++---
 .../policyevaluator/RangerPolicyEvaluator.java     |  8 +-
 .../ranger/plugin/service/RangerBasePlugin.java    |  2 +-
 .../apache/ranger/plugin/util/ServiceDefUtil.java  | 27 +++++++
 .../org/apache/ranger/biz/RangerPolicyAdmin.java   |  7 +-
 .../apache/ranger/biz/RangerPolicyAdminImpl.java   | 92 +++++++++++++++++-----
 .../java/org/apache/ranger/rest/ServiceREST.java   | 42 +++++-----
 8 files changed, 195 insertions(+), 75 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
index d64d226..45774b9 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java
@@ -28,6 +28,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
@@ -335,54 +336,72 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 	}
 
 	@Override
-	public boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, Set<String> roles, String accessType) {
+	public Set<String> getAllowedAccesses(RangerAccessResource resource, String user, Set<String> userGroups, Set<String> roles, Set<String> accessTypes) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.getAllowedAccesses(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ")");
+		}
+
+		Set<String> ret = null;
+
+		if (isMatch(resource, null)) {
+			ret = new HashSet<>();
+			for (String accessType : accessTypes) {
+				if (isAccessAllowed(user, userGroups, roles, resource.getOwnerUser(), accessType)) {
+					ret.add(accessType);
+				}
+			}
 		}
 
-		boolean ret = isAccessAllowed(user, userGroups, roles, resource.getOwnerUser(), accessType) && isMatch(resource, null);
-		
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.getAllowedAccesses(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + "): " + ret);
 		}
 
 		return ret;
 	}
 
-	/*
-	 * This is used only by test code
-	 */
-
 	@Override
-	public boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType) {
+	public Set<String> getAllowedAccesses(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles,  Set<String> accessTypes, Map<String, Object> evalContext) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.getAllowedAccesses(" + getPolicy().getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ", " + evalContext + ")");
 		}
 
-		boolean ret = isAccessAllowed(user, userGroups, null, null, accessType) && isMatch(resources, null);
+		Set<String> ret = null;
+
+		if (isMatch(resources, evalContext)) {
+			ret = new HashSet<>();
+			for (String accessType : accessTypes) {
+				if (isAccessAllowed(user, userGroups, roles, null, accessType)) {
+					ret.add(accessType);
+				}
+			}
+		}
 
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.getAllowedAccesses(" + getPolicy().getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ", " + evalContext + "): " + ret);
 		}
 
 		return ret;
 	}
+	/*
+	 * This is used only by test code
+	 */
 
 	@Override
-	public boolean isAccessAllowed(Long policyId, Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles,  String accessType, Map<String, Object> evalContext) {
+	public boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType) {
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + policyId + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + ")");
+			LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")");
 		}
 
-		boolean ret = isAccessAllowed(user, userGroups, roles, null, accessType) && isMatch(resources, evalContext);
-		
+		boolean ret = isAccessAllowed(user, userGroups, null, null, accessType) && isMatch(resources, null);
+
 		if(LOG.isDebugEnabled()) {
-			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + policyId + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + "): " + ret);
+			LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
 		}
 
 		return ret;
 	}
 
+
 	@Override
 	public void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result) {
 		if (LOG.isDebugEnabled()) {
@@ -867,6 +886,8 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 			return;
 		}
 
+		prunePolicyItems(policy);
+
 		preprocessPolicyItems(policy.getPolicyItems(), impliedAccessGrants);
 		preprocessPolicyItems(policy.getDenyPolicyItems(), impliedAccessGrants);
 		preprocessPolicyItems(policy.getAllowExceptions(), impliedAccessGrants);
@@ -936,6 +957,15 @@ public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator
 		return ret;
 	}
 
+	private void prunePolicyItems(RangerPolicy policy) {
+		if (getPluginContext().getConfig().getPolicyEngineOptions().evaluateDelegateAdminOnly) {
+			policy.setPolicyItems(policy.getPolicyItems().stream().filter(RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()));
+			policy.setDenyPolicyItems(policy.getDenyPolicyItems().stream().filter(RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()));
+			policy.setAllowExceptions(policy.getAllowExceptions().stream().filter(RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()));
+			policy.setDenyExceptions(policy.getDenyExceptions().stream().filter(RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()));
+		}
+	}
+
 	private RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) {
 		RangerPolicyItemAccess ret = null;
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
index bac076c..e69e45f 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java
@@ -253,13 +253,16 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
         boolean ret = false;
 
         if (hasPublicGroup || hasCurrentUser || isOwnerMatch(request) || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups()) || (CollectionUtils.isNotEmpty(roles) && CollectionUtils.containsAny(roles, RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext())))) {
-            if(request.isAccessTypeDelegatedAdmin()) {
-                ret = delegateAdmin;
-            } else if(hasAllPerms) {
+           if (hasAllPerms || request.isAccessTypeAny()) {
                 ret = true;
             } else {
-                ret = request.isAccessTypeAny() || accessPerms.contains(request.getAccessType());
-            }
+               ret = accessPerms.contains(request.getAccessType());
+               if (!ret) {
+                   if (request.isAccessTypeDelegatedAdmin()) {
+                       ret = delegateAdmin;
+                   }
+               }
+           }
         }
 
         return ret;
@@ -292,16 +295,17 @@ public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator
         }
 
         if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups) || hasRole || (hasResourceOwner && StringUtils.equals(user, owner))) {
-            boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS);
-
-            if(isAdminAccess) {
-	            ret = delegateAdmin;
-            } else if(hasAllPerms) {
+            if (hasAllPerms) {
                 ret = true;
             } else {
                 boolean isAccessTypeAny = StringUtils.isEmpty(accessType) || StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS);
+                ret = isAccessTypeAny || accessPerms.contains(accessType);
 
-	            ret = isAccessTypeAny || accessPerms.contains(accessType);
+                if (!ret) {
+                    if (StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS)) {
+                        ret = delegateAdmin;
+                    }
+                }
             }
         }
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
index 236f998..c611b5e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerPolicyEvaluator.java
@@ -94,16 +94,16 @@ public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator {
 
 	boolean isCompleteMatch(Map<String, RangerPolicyResource> resources, Map<String, Object> evalContext);
 
-	boolean isAccessAllowed(RangerAccessResource resource, String user, Set<String> userGroups, Set<String> roles, String accessType);
-
 	boolean isAccessAllowed(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, String accessType);
 
-	boolean isAccessAllowed(Long policyId, Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext);
-
 	void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, boolean isAllowed, String reason);
 
 	void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result);
 
+	Set<String> getAllowedAccesses(RangerAccessResource resource, String user, Set<String> userGroups, Set<String> roles, Set<String> accessTypes);
+
+	Set<String> getAllowedAccesses(Map<String, RangerPolicyResource> resources, String user, Set<String> userGroups, Set<String> roles,  Set<String> accessTypes, Map<String, Object> evalContext);
+
 	PolicyACLSummary getPolicyACLSummary();
 
 	default boolean hasContextSensitiveSpecification() {
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 873553a..e1f09b8 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
@@ -705,7 +705,7 @@ public class RangerBasePlugin {
 	
 			accessRequest.setResource(new RangerAccessResourceImpl(StringUtil.toStringObjectMap(request.getResource())));
 			accessRequest.setUser(request.getGrantor());
-			accessRequest.setAccessType(RangerPolicyEngine.ADMIN_ACCESS);
+			accessRequest.setAccessType(RangerPolicyEngine.ANY_ACCESS);
 			accessRequest.setAction(action);
 			accessRequest.setClientIPAddress(request.getClientIPAddress());
 			accessRequest.setClientType(request.getClientType());
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
index cd6c18b..b76c96e 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceDefUtil.java
@@ -34,6 +34,8 @@ import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.HashMap;
 import java.util.Map;
@@ -439,4 +441,29 @@ public class ServiceDefUtil {
         return ret;
     }
 
+    public static Map<String, Collection<String>> getExpandedImpliedGrants(RangerServiceDef serviceDef) {
+        Map<String, Collection<String>> ret = new HashMap<>();
+
+        if(serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) {
+            for(RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) {
+                if(!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) {
+
+                    Collection<String> impliedAccessGrants = ret.get(accessTypeDef.getName());
+
+                    if(impliedAccessGrants == null) {
+                        impliedAccessGrants = new HashSet<>();
+
+                        ret.put(accessTypeDef.getName(), impliedAccessGrants);
+                    }
+
+                    impliedAccessGrants.addAll(accessTypeDef.getImpliedGrants());
+                    impliedAccessGrants.add(accessTypeDef.getName());
+                } else {
+                    ret.put(accessTypeDef.getName(), new HashSet<>(Collections.singleton(accessTypeDef.getName())));
+                }
+            }
+        }
+        return ret;
+    }
+
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java
index 891c800..e2a0884 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdmin.java
@@ -25,15 +25,16 @@ import java.util.Set;
 
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.RangerRoles;
 
 public interface RangerPolicyAdmin {
 
-    boolean isAccessAllowed(RangerAccessResource resource, String zoneName, String user, Set<String> userGroups, String accessType);
+    boolean isDelegatedAdminAccessAllowed(RangerAccessResource resource, String zoneName, String user, Set<String> userGroups, Set<String> accessTypes);
 
-    boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext);
+    boolean isDelegatedAdminAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, Map<String, Object> evalContext);
 
     List<RangerPolicy> getExactMatchPolicies(RangerAccessResource resource, String zoneName, Map<String, Object> evalContext);
 
@@ -49,6 +50,8 @@ public interface RangerPolicyAdmin {
 
     String getServiceName();
 
+    RangerServiceDef getServiceDef();
+
     Set<String> getRolesFromUserAndGroups(String user, Set<String> groups);
 
     String getUniquelyMatchedZoneName(GrantRevokeRequest grantRevokeRequest);
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
index cd566bc..d868e39 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
@@ -20,12 +20,14 @@
 package org.apache.ranger.biz;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.policyengine.PolicyEngine;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
@@ -43,12 +45,14 @@ import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerRoles;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.apache.ranger.plugin.util.ServicePolicies;
 import org.apache.ranger.plugin.util.StringTokenReplacer;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -94,32 +98,36 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
     }
 
     @Override
-    public boolean isAccessAllowed(RangerAccessResource resource, String zoneName, String user, Set<String> userGroups, String accessType) {
+    public boolean isDelegatedAdminAccessAllowed(RangerAccessResource resource, String zoneName, String user, Set<String> userGroups, Set<String> accessTypes) {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + resource + ", " + zoneName + ", " + user + ", " + userGroups + ", " + accessType + ")");
+            LOG.debug("==> RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(" + resource + ", " + zoneName + ", " + user + ", " + userGroups + ", " + accessTypes + ")");
         }
 
         boolean          ret  = false;
         RangerPerfTracer perf = null;
 
         if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) {
-            perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyAdminImpl.isAccessAllowed(user=" + user + ",accessType=" + accessType + "resource=" + resource.getAsString() + ")");
+            perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(user=" + user + ",accessTypes=" + accessTypes + "resource=" + resource.getAsString() + ")");
         }
 
         final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName);
 
         if (matchedRepository != null) {
             Set<String> roles = getRolesFromUserAndGroups(user, userGroups);
+            Set<String> requestedAccesses = new HashSet<>(accessTypes);
 
             for (RangerPolicyEvaluator evaluator : matchedRepository.getLikelyMatchPolicyEvaluators(resource, RangerPolicy.POLICY_TYPE_ACCESS)) {
-                ret = evaluator.isAccessAllowed(resource, user, userGroups, roles, accessType);
 
-                if (ret) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]");
+                Set<String> allowedAccesses = evaluator.getAllowedAccesses(resource, user, userGroups, roles, requestedAccesses);
+                if (CollectionUtils.isNotEmpty(allowedAccesses)) {
+                    requestedAccesses.removeAll(allowedAccesses);
+                    if (CollectionUtils.isEmpty(requestedAccesses)) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]");
+                        }
+                        ret = true;
+                        break;
                     }
-
-                    break;
                 }
             }
 
@@ -128,23 +136,23 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
         RangerPerfTracer.log(perf);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + resource + ", " + zoneName + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret);
+            LOG.debug("<== RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(" + resource + ", " + zoneName + ", " + user + ", " + userGroups + ", " + accessTypes + "): " + ret);
         }
 
         return ret;
     }
 
     @Override
-    public boolean isAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, String accessType, Map<String, Object> evalContext) {
+    public boolean isDelegatedAdminAccessAllowed(RangerPolicy policy, String user, Set<String> userGroups, Set<String> roles, Map<String, Object> evalContext) {
         if (LOG.isDebugEnabled()) {
-            LOG.debug("==> RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + ")");
+            LOG.debug("==> RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + evalContext + ")");
         }
 
         boolean          ret  = false;
         RangerPerfTracer perf = null;
 
         if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) {
-            perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.isAccessAllowed(user=" + user + "," + userGroups + ", roles=" + roles + ",accessType=" + accessType + ")");
+            perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.isDelegatedAdminAccessAllowed(user=" + user + "," + userGroups + ", roles=" + roles + ")");
         }
 
         final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(policy);
@@ -153,20 +161,27 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
             // RANGER-3082
             // Convert policy resources to by substituting macros with ASTERISK
             Map<String, RangerPolicyResource> modifiedPolicyResources = getPolicyResourcesWithMacrosReplaced(policy.getResources(), wildcardEvalContext);
+            Set<String> accessTypes = getAllAccessTypes(policy, getServiceDef());
 
             for (RangerPolicyEvaluator evaluator : matchedRepository.getPolicyEvaluators()) {
-                ret = evaluator.isAccessAllowed(policy.getId(), modifiedPolicyResources, user, userGroups, roles, accessType, evalContext);
-
-                if (ret) {
-                    break;
+                Set<String> allowedAccesses = evaluator.getAllowedAccesses(modifiedPolicyResources, user, userGroups, roles, accessTypes, evalContext);
+                if (CollectionUtils.isNotEmpty(allowedAccesses)) {
+                    accessTypes.removeAll(allowedAccesses);
+                    if (CollectionUtils.isEmpty(accessTypes)) {
+                        ret = true;
+                        break;
+                    }
                 }
             }
+            if (CollectionUtils.isNotEmpty(accessTypes)) {
+                LOG.info("Accesses : " + accessTypes + " are not authorized for the policy:[" + policy.getId() + "] by any of delegated-admin policies");
+            }
         }
 
         RangerPerfTracer.log(perf);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("<== RangerPolicyAdminImpl.isAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessType + ", " + evalContext + "): " + ret);
+            LOG.debug("<== RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(" + policy.getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + evalContext + "): " + ret);
         }
 
         return ret;
@@ -255,6 +270,11 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
     @Override
     public String getServiceName() { return policyEngine.getServiceName(); }
 
+
+    @Override
+    public RangerServiceDef getServiceDef() {
+        return policyEngine.getServiceDef();
+    }
     @Override
     public void setRoles(RangerRoles roles) {
         policyEngine.setRoles(roles);
@@ -485,5 +505,41 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
 
         return ret;
     }
+
+    private Set<String> getAllAccessTypes(RangerPolicy policy, RangerServiceDef serviceDef) {
+        Set<String> ret = new HashSet<>();
+
+        Map<String, Collection<String>> expandedAccesses = ServiceDefUtil.getExpandedImpliedGrants(serviceDef);
+
+        if (MapUtils.isNotEmpty(expandedAccesses)) {
+
+            for (RangerPolicy.RangerPolicyItem item : policy.getPolicyItems()) {
+                List<RangerPolicy.RangerPolicyItemAccess> accesses = item.getAccesses();
+                for (RangerPolicy.RangerPolicyItemAccess access : accesses) {
+                    ret.addAll(expandedAccesses.get(access.getType()));
+                }
+            }
+            for (RangerPolicy.RangerPolicyItem item : policy.getDenyPolicyItems()) {
+                List<RangerPolicy.RangerPolicyItemAccess> accesses = item.getAccesses();
+                for (RangerPolicy.RangerPolicyItemAccess access : accesses) {
+                    ret.addAll(expandedAccesses.get(access.getType()));
+                }
+            }
+            for (RangerPolicy.RangerPolicyItem item : policy.getAllowExceptions()) {
+                List<RangerPolicy.RangerPolicyItemAccess> accesses = item.getAccesses();
+                for (RangerPolicy.RangerPolicyItemAccess access : accesses) {
+                    ret.addAll(expandedAccesses.get(access.getType()));
+                }
+            }
+            for (RangerPolicy.RangerPolicyItem item : policy.getDenyExceptions()) {
+                List<RangerPolicy.RangerPolicyItemAccess> accesses = item.getAccesses();
+                for (RangerPolicy.RangerPolicyItemAccess access : accesses) {
+                    ret.addAll(expandedAccesses.get(access.getType()));
+                }
+            }
+        }
+        return ret;
+    }
+
 }
 
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 802abac..8db022e 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
@@ -113,7 +113,6 @@ import org.apache.ranger.plugin.model.validation.RangerServiceValidator;
 import org.apache.ranger.plugin.model.validation.RangerValidator.Action;
 import org.apache.ranger.plugin.policyengine.RangerAccessResource;
 import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
-import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
 import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
 import org.apache.ranger.plugin.service.ResourceLookupContext;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
@@ -1224,6 +1223,7 @@ public class ServiceREST {
 					Set<String>          userGroups = CollectionUtils.isNotEmpty(grantRequest.getGrantorGroups()) ? grantRequest.getGrantorGroups() : userMgr.getGroupsForUser(userName);
 					String				 ownerUser  = grantRequest.getOwnerUser();
 					RangerAccessResource resource   = new RangerAccessResourceImpl(StringUtil.toStringObjectMap(grantRequest.getResource()), ownerUser);
+					Set<String>			 accessTypes = grantRequest.getAccessTypes();
 					VXUser               vxUser = xUserService.getXUserByUserName(userName);
 
 					if (vxUser.getUserRoleList().contains(RangerConstants.ROLE_ADMIN_AUDITOR) || vxUser.getUserRoleList().contains(RangerConstants.ROLE_KEY_ADMIN_AUDITOR)) {
@@ -1235,7 +1235,7 @@ public class ServiceREST {
 					RangerService rangerService = svcStore.getServiceByName(serviceName);
 
 					String zoneName = getRangerAdminZoneName(serviceName, grantRequest);
-					boolean isAdmin = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource);
+					boolean isAdmin = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource, accessTypes);
 
 					if(!isAdmin) {
 						throw restErrorUtil.createGrantRevokeRESTException( "User doesn't have necessary permission to grant access");
@@ -1343,6 +1343,7 @@ public class ServiceREST {
 					String				 ownerUser  = grantRequest.getOwnerUser();
 
 					RangerAccessResource resource   = new RangerAccessResourceImpl(StringUtil.toStringObjectMap(grantRequest.getResource()), ownerUser);
+					Set<String>			 accessTypes = grantRequest.getAccessTypes();
 					String               zoneName   = getRangerAdminZoneName(serviceName, grantRequest);
 
 					boolean isAllowed = false;
@@ -1352,7 +1353,7 @@ public class ServiceREST {
 							isAllowed = true;
 						}
 					} else {
-						isAllowed = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource);
+						isAllowed = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource, accessTypes);
 					}
 
 					if (isAllowed) {
@@ -1458,6 +1459,7 @@ public class ServiceREST {
 					Set<String>          userGroups = CollectionUtils.isNotEmpty(revokeRequest.getGrantorGroups()) ? revokeRequest.getGrantorGroups() : userMgr.getGroupsForUser(userName);
 					String				 ownerUser  = revokeRequest.getOwnerUser();
 					RangerAccessResource resource   = new RangerAccessResourceImpl(StringUtil.toStringObjectMap(revokeRequest.getResource()), ownerUser);
+					Set<String>			 accessTypes = revokeRequest.getAccessTypes();
 					VXUser vxUser = xUserService.getXUserByUserName(userName);
 
 					if (vxUser.getUserRoleList().contains(RangerConstants.ROLE_ADMIN_AUDITOR) || vxUser.getUserRoleList().contains(RangerConstants.ROLE_KEY_ADMIN_AUDITOR)) {
@@ -1469,7 +1471,7 @@ public class ServiceREST {
 					RangerService rangerService = svcStore.getServiceByName(serviceName);
 					String        zoneName      = getRangerAdminZoneName(serviceName, revokeRequest);
 
-					boolean isAdmin = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource);
+					boolean isAdmin = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource, accessTypes);
 
 					if(!isAdmin) {
 						throw restErrorUtil.createGrantRevokeRESTException("User doesn't have necessary permission to revoke access");
@@ -1541,6 +1543,7 @@ public class ServiceREST {
 					String ownerUser = revokeRequest.getOwnerUser();
 
 					RangerAccessResource resource = new RangerAccessResourceImpl(StringUtil.toStringObjectMap(revokeRequest.getResource()), ownerUser);
+					Set<String>			 accessTypes = revokeRequest.getAccessTypes();
 					String               zoneName = getRangerAdminZoneName(serviceName, revokeRequest);
 
 
@@ -1551,7 +1554,7 @@ public class ServiceREST {
 							isAllowed = true;
 						}
 					} else {
-						isAllowed = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource);
+						isAllowed = bizUtil.isUserRangerAdmin(userName) || bizUtil.isUserServiceAdmin(rangerService, userName) || hasAdminAccess(serviceName, zoneName, userName, userGroups, resource, accessTypes);
 					}
 
 					if (isAllowed) {
@@ -3511,15 +3514,13 @@ public class ServiceREST {
 				List<RangerPolicy> listToFilter = entry.getValue();
 
 				if (CollectionUtils.isNotEmpty(listToFilter)) {
-					boolean isServiceAdminUser = isAdmin || svcStore.isServiceAdminUser(serviceName, userName);
-					if (isAdmin || isKeyAdmin || isAuditAdmin
-							|| isAuditKeyAdmin) {
-						XXService xService = daoManager.getXXService()
-								.findByName(serviceName);
-						Long serviceDefId = xService.getType();
-						boolean isKmsService = serviceDefId
-								.equals(EmbeddedServiceDefsUtil.instance()
-										.getKmsServiceDefId());
+					boolean isServiceAdminUser = svcStore.isServiceAdminUser(serviceName, userName);
+					if (isServiceAdminUser) {
+						ret.addAll(listToFilter);
+					} else if (isAdmin || isKeyAdmin || isAuditAdmin || isAuditKeyAdmin) {
+						XXService xService     = daoManager.getXXService().findByName(serviceName);
+						Long      serviceDefId = xService.getType();
+						boolean   isKmsService = serviceDefId.equals(EmbeddedServiceDefsUtil.instance().getKmsServiceDefId());
 
 						if (isAdmin) {
 							if (!isKmsService) {
@@ -3551,9 +3552,8 @@ public class ServiceREST {
 						Set<String> roles = policyAdmin.getRolesFromUserAndGroups(userName, userGroups);
 
 						for (RangerPolicy policy : listToFilter) {
-							if (policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS, evalContext)
-									|| (!StringUtils.isEmpty(policy.getZoneName()) && (serviceMgr.isZoneAdmin(policy.getZoneName()) || serviceMgr.isZoneAuditor(policy.getZoneName())))
-									|| isServiceAdminUser) {
+							if ((policyAdmin.isDelegatedAdminAccessAllowed(policy, userName, userGroups, roles, evalContext))
+									|| (!StringUtils.isEmpty(policy.getZoneName()) && (serviceMgr.isZoneAdmin(policy.getZoneName()) || serviceMgr.isZoneAuditor(policy.getZoneName())))) {
 								ret.add(policy);
 							}
 						}
@@ -3567,7 +3567,7 @@ public class ServiceREST {
 
 		return ret;
 	}
-	
+
 	void ensureAdminAccess(RangerPolicy policy) {
 		boolean isAdmin = bizUtil.isAdmin();
 		boolean isKeyAdmin = bizUtil.isKeyAdmin();
@@ -3651,18 +3651,18 @@ public class ServiceREST {
 
 			Set<String> roles = policyAdmin.getRolesFromUserAndGroups(userName, userGroups);
 
-			isAllowed = policyAdmin.isAccessAllowed(policy, userName, userGroups, roles, RangerPolicyEngine.ADMIN_ACCESS, evalContext);
+			isAllowed = policyAdmin.isDelegatedAdminAccessAllowed(policy, userName, userGroups, roles, evalContext);
 		}
 
 		return isAllowed;
 	}
-	private boolean hasAdminAccess(String serviceName, String zoneName, String userName, Set<String> userGroups, RangerAccessResource resource) {
+	private boolean hasAdminAccess(String serviceName, String zoneName, String userName, Set<String> userGroups, RangerAccessResource resource, Set<String> accessTypes) {
 		boolean isAllowed = false;
 
 		RangerPolicyAdmin policyAdmin = getPolicyAdminForDelegatedAdmin(serviceName);
 
 		if(policyAdmin != null) {
-			isAllowed = policyAdmin.isAccessAllowed(resource, zoneName, userName, userGroups, RangerPolicyEngine.ADMIN_ACCESS);
+			isAllowed = CollectionUtils.isNotEmpty(accessTypes) && policyAdmin.isDelegatedAdminAccessAllowed(resource, zoneName, userName, userGroups, accessTypes);
 		}
 
 		return isAllowed;