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

madhan 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 6138a418e RANGER-5369: introduce inline-policy to support 
service-managed ACLs (#743)
6138a418e is described below

commit 6138a418e882566e238e4a918aea075cf08c9e93
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Mon Dec 1 17:03:25 2025 -0800

    RANGER-5369: introduce inline-policy to support service-managed ACLs (#743)
---
 agents-common/pom.xml                              |   5 +
 .../plugin/audit/RangerDefaultAuditHandler.java    |   2 +-
 .../ranger/plugin/model/RangerInlinePolicy.java    | 178 ++++++++++++
 .../ranger/plugin/model/RangerPrincipal.java       |  19 ++
 .../ranger/plugin/model/RangerServiceDef.java      |   3 +
 .../model/validation/RangerServiceDefHelper.java   |  83 ++++--
 .../plugin/policyengine/RangerAccessRequest.java   |   6 +
 .../policyengine/RangerAccessRequestImpl.java      |  12 +
 .../policyengine/RangerAccessRequestReadOnly.java  |   7 +
 .../policyengine/RangerAccessRequestWrapper.java   |   6 +
 .../policyengine/RangerPolicyEngineImpl.java       |  20 ++
 .../RangerInlinePolicyEvaluator.java               | 307 +++++++++++++++++++++
 .../plugin/resourcematcher/ResourceMatcher.java    | 162 +++++------
 .../plugin/util/RangerAccessRequestUtil.java       |  20 +-
 .../policyevaluator/TestInlinePolicyEvaluator.java | 145 ++++++++++
 .../test_inline_policies_ozone.json                | 233 ++++++++++++++++
 .../authz/util/RangerResourceNameParser.java       |  46 +--
 .../authz/util/TestRangerResourceNameParser.java   |  59 ++--
 distro/src/main/assembly/admin-web.xml             |   1 +
 distro/src/main/assembly/hbase-agent.xml           |   1 +
 distro/src/main/assembly/hdfs-agent.xml            |   1 +
 distro/src/main/assembly/hive-agent.xml            |   1 +
 distro/src/main/assembly/kms.xml                   |   1 +
 distro/src/main/assembly/knox-agent.xml            |   1 +
 distro/src/main/assembly/plugin-atlas.xml          |   1 +
 distro/src/main/assembly/plugin-elasticsearch.xml  |   1 +
 distro/src/main/assembly/plugin-kafka.xml          |   1 +
 distro/src/main/assembly/plugin-kms.xml            |   1 +
 distro/src/main/assembly/plugin-kylin.xml          |   1 +
 distro/src/main/assembly/plugin-ozone.xml          |   1 +
 distro/src/main/assembly/plugin-presto.xml         |   1 +
 distro/src/main/assembly/plugin-solr.xml           |   1 +
 distro/src/main/assembly/plugin-sqoop.xml          |   1 +
 distro/src/main/assembly/plugin-trino.xml          |   1 +
 distro/src/main/assembly/plugin-yarn.xml           |   1 +
 distro/src/main/assembly/ranger-tools.xml          |   1 +
 distro/src/main/assembly/sample-client.xml         |   1 +
 distro/src/main/assembly/storm-agent.xml           |   1 +
 distro/src/main/assembly/tagsync.xml               |   1 +
 distro/src/main/assembly/usersync.xml              |   1 +
 40 files changed, 1185 insertions(+), 150 deletions(-)

diff --git a/agents-common/pom.xml b/agents-common/pom.xml
index 6b82eb49f..bb2a87a19 100644
--- a/agents-common/pom.xml
+++ b/agents-common/pom.xml
@@ -160,6 +160,11 @@
             <artifactId>ranger-audit-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.ranger</groupId>
+            <artifactId>ranger-authz-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.ranger</groupId>
             <artifactId>ranger-plugin-classloader</artifactId>
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
index 3132a75cd..a9fb1863a 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/audit/RangerDefaultAuditHandler.java
@@ -128,7 +128,7 @@ public AuthzAuditEvent getAuthzEvents(RangerAccessResult 
result) {
             ret.setClientIP(request.getClientIPAddress());
             ret.setClientType(request.getClientType());
             ret.setSessionId(request.getSessionId());
-            ret.setAclEnforcer(moduleName);
+            
ret.setAclEnforcer(RangerAccessRequestUtil.getAclEnforcerOrDefault(request.getContext(),
 moduleName));
 
             Set<String> tags = getTags(request);
             if (tags != null) {
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerInlinePolicy.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerInlinePolicy.java
new file mode 100644
index 000000000..d33eddbd3
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerInlinePolicy.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class RangerInlinePolicy implements java.io.Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public enum Mode {
+        INLINE,            // default: request must be allowed by this inline 
policy
+        RANGER_AND_INLINE, // request must be allowed by both Ranger policies 
and this inline policy
+        RANGER_OR_INLINE   // request must be allowed by either Ranger 
policies or this inline policy
+    }
+
+    private String      grantor;  // example: "r:role1"; when non-empty, 
request must be allowed for grantor principal as well
+    private Mode        mode;
+    private List<Grant> grants;
+    private String      createdBy;
+    private long        createTime;
+
+    public RangerInlinePolicy() {
+        this.mode = Mode.INLINE;
+    }
+
+    public RangerInlinePolicy(String grantor, Mode mode, List<Grant> grants, 
String createdBy) {
+        this.grantor    = grantor;
+        this.mode       = mode;
+        this.grants     = grants;
+        this.createdBy  = createdBy;
+        this.createTime = System.currentTimeMillis();
+    }
+
+    public String getGrantor() {
+        return grantor;
+    }
+
+    public void setGrantor(String grantor) {
+        this.grantor = grantor;
+    }
+
+    public Mode getMode() {
+        return mode;
+    }
+
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    public List<Grant> getGrants() {
+        return grants;
+    }
+
+    public void setGrants(List<Grant> grants) {
+        this.grants = grants;
+    }
+
+    public String getCreatedBy() {
+        return createdBy;
+    }
+
+    public void setCreatedBy(String createdBy) {
+        this.createdBy = createdBy;
+    }
+
+    public long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(long createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return "RangerInlinePolicy{" +
+                "grantor=" + grantor + "," +
+                "mode=" + mode + "," +
+                "grants=" + grants + "," +
+                "createdBy=" + createdBy + "," +
+                "createTime=" + createTime +
+                "}";
+    }
+
+    public static class Grant {
+        private Set<String> principals;  // example: [ "u:user1, "g:group1", 
"r:role1" ]; if empty, means public grant
+        private Set<String> resources;   // example: [ 
"key:vol1/bucket1/db1/tbl1/*", "key:vol1/bucket1/db1/tbl2/*" ]; if empty, means 
all resources
+        private Set<String> permissions; // example: [ "read", "write" ]; if 
empty, means no permission
+
+        public Grant() {
+        }
+
+        public Grant(Set<String> principals, Set<String> resources, 
Set<String> permissions) {
+            this.principals  = principals;
+            this.resources   = resources;
+            this.permissions = permissions;
+        }
+
+        public Set<String> getPrincipals() {
+            return principals;
+        }
+
+        public void setPrincipals(Set<String> principals) {
+            this.principals = principals;
+        }
+
+        public Set<String> getResources() {
+            return resources;
+        }
+
+        public void setResources(Set<String> resources) {
+            this.resources = resources;
+        }
+
+        public Set<String> getPermissions() {
+            return permissions;
+        }
+
+        public void setPermissions(Set<String> permissions) {
+            this.permissions = permissions;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            } else if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            Grant that = (Grant) o;
+
+            return Objects.equals(principals, that.principals) &&
+                   Objects.equals(resources, that.resources) &&
+                   Objects.equals(permissions, that.permissions);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(principals, resources, permissions);
+        }
+
+        @Override
+        public String toString() {
+            return "Grant{" +
+                    "principals=" + principals +
+                    ", resources=" + resources +
+                    ", permissions=" + permissions +
+                    '}';
+        }
+    }
+}
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
index 0dc8b4201..1c3de565b 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerPrincipal.java
@@ -22,6 +22,7 @@
 import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.commons.lang3.StringUtils;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
@@ -37,6 +38,10 @@
 public class RangerPrincipal implements java.io.Serializable {
     private static final long serialVersionUID = 1L;
 
+    public static final String PREFIX_USER  = "u:";
+    public static final String PREFIX_GROUP = "g:";
+    public static final String PREFIX_ROLE  = "r:";
+
     private PrincipalType type;
     private String        name;
 
@@ -95,4 +100,18 @@ public String toString() {
     }
 
     public enum PrincipalType { USER, GROUP, ROLE }
+
+    public static RangerPrincipal toPrincipal(String name) {
+        if (StringUtils.isBlank(name)) {
+            return null;
+        } else if (name.startsWith(PREFIX_USER)) {
+            return new RangerPrincipal(PrincipalType.USER, 
name.substring(PREFIX_USER.length()));
+        } else if (name.startsWith(PREFIX_GROUP)) {
+            return new RangerPrincipal(PrincipalType.GROUP, 
name.substring(PREFIX_GROUP.length()));
+        } else if (name.startsWith(PREFIX_ROLE)) {
+            return new RangerPrincipal(PrincipalType.ROLE, 
name.substring(PREFIX_ROLE.length()));
+        } else {
+            return new RangerPrincipal(PrincipalType.USER, name);
+        }
+    }
 }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
index 71a578b8f..573c485ff 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceDef.java
@@ -42,6 +42,9 @@ public class RangerServiceDef extends RangerBaseModelObject 
implements java.io.S
     public static final String OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES = 
"enableDenyAndExceptionsInPolicies";
     public static final String OPTION_ENABLE_IMPLICIT_CONDITION_EXPRESSION   = 
"enableImplicitConditionExpression";
     public static final String OPTION_ENABLE_TAG_BASED_POLICIES              = 
"enableTagBasedPolicies";
+    public static final String OPTION_RRN_RESOURCE_SEP_CHAR                  = 
"rrnResourceSepChar";
+
+    public static final char DEFAULT_RRN_RESOURCE_SEP_CHAR = '/';
 
     private String                         name;
     private String                         displayName;
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
index 208ba100a..18b66159f 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java
@@ -23,7 +23,11 @@
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.thirdparty.com.google.common.collect.Lists;
 import org.apache.hadoop.thirdparty.com.google.common.collect.Sets;
+import org.apache.ranger.authz.api.RangerAuthzApiErrorCode;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.authz.util.RangerResourceNameParser;
 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.model.RangerServiceDef.RangerAccessTypeDef;
 import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef;
@@ -45,11 +49,12 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
+import static 
org.apache.ranger.authz.util.RangerResourceNameParser.RRN_RESOURCE_TYPE_SEP;
+import static 
org.apache.ranger.plugin.model.RangerServiceDef.OPTION_RRN_RESOURCE_SEP_CHAR;
+
 public class RangerServiceDefHelper {
     private static final Logger LOG = 
LoggerFactory.getLogger(RangerServiceDefHelper.class);
 
-    public static final String RRN_RESOURCE_SEP = "/";
-
     static final Map<String, Delegate> cache = new ConcurrentHashMap<>();
     final        Delegate              delegate;
 
@@ -218,10 +223,18 @@ public Set<Set<String>> getResourceHierarchyKeys(Integer 
policyType) {
         return delegate.getResourceHierarchyKeys(policyType);
     }
 
+    public char getRrnResourceSep() {
+        return delegate.getRrnResourceSepChar();
+    }
+
     public String getRrnTemplate(String resourceName) {
         return delegate.getRrnTemplate(resourceName);
     }
 
+    public RangerResourceNameParser getRrnParser(String resourceName) {
+        return delegate.getRrnParser(resourceName);
+    }
+
     public boolean isDataMaskSupported() {
         return delegate.isDataMaskSupported();
     }
@@ -429,6 +442,24 @@ public Set<String> expandImpliedAccessGrants(Set<String> 
accessTypes) {
         return ret;
     }
 
+    public Map<String, String> parseResourceToMap(String resource) throws 
RangerAuthzException {
+        int                      sepPos       = 
resource.indexOf(RRN_RESOURCE_TYPE_SEP);
+        String                   resourceType = sepPos < 1 ? "" : 
resource.substring(0, sepPos);
+        RangerResourceNameParser parser       = 
this.getRrnParser(resourceType);
+
+        if (parser == null) {
+            throw new 
RangerAuthzException(RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID, 
resource, resourceType);
+        }
+
+        return parser.parseToMap(resource.substring(sepPos + 1));
+    }
+
+    public Map<String, RangerPolicyResource> 
parseResourceToPolicyResources(String resource) throws RangerAuthzException {
+        Map<String, String> resourceMap = parseResourceToMap(resource);
+
+        return 
resourceMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e 
-> new RangerPolicyResource(e.getValue())));
+    }
+
     /**
      * Not designed for public access.  Package level only for testability.
      */
@@ -448,7 +479,9 @@ static class Delegate {
         final Set<String>                                  allAccessTypes;
         final boolean                                      isDataMaskSupported;
         final boolean                                      
isRowFilterSupported;
+        final char                                         rrnResourceSepChar;
         final Map<String, String>                          rrnTemplates = new 
HashMap<>();
+        final Map<String, RangerResourceNameParser>        rrnParsers = new 
HashMap<>();
 
         public Delegate(RangerServiceDef serviceDef, boolean checkForCycles) {
             // NOTE: we assume serviceDef, its name and update time are can 
never by null.
@@ -485,16 +518,26 @@ public Delegate(RangerServiceDef serviceDef, boolean 
checkForCycles) {
                 }
             }
 
-            impliedGrants  = computeImpliedGrants();
-            allAccessTypes = 
Collections.unmodifiableSet(serviceDef.getAccessTypes().stream().map(RangerAccessTypeDef::getName).collect(Collectors.toSet()));
-            isDataMaskSupported = 
CollectionUtils.isNotEmpty(hierarchyKeys.get(RangerPolicy.POLICY_TYPE_DATAMASK));
+            String optRrnResourceSep = serviceDef.getOptions() != null ? 
serviceDef.getOptions().get(OPTION_RRN_RESOURCE_SEP_CHAR) : null;
+
+            impliedGrants        = computeImpliedGrants();
+            allAccessTypes       = 
Collections.unmodifiableSet(serviceDef.getAccessTypes().stream().map(RangerAccessTypeDef::getName).collect(Collectors.toSet()));
+            isDataMaskSupported  = 
CollectionUtils.isNotEmpty(hierarchyKeys.get(RangerPolicy.POLICY_TYPE_DATAMASK));
             isRowFilterSupported = 
CollectionUtils.isNotEmpty(hierarchyKeys.get(RangerPolicy.POLICY_TYPE_ROWFILTER));
+            rrnResourceSepChar   = StringUtils.isEmpty(optRrnResourceSep) ? 
RangerServiceDef.DEFAULT_RRN_RESOURCE_SEP_CHAR : optRrnResourceSep.charAt(0);
 
             if (isValid) {
                 orderedResourceNames = buildSortedResourceNames();
 
                 for (RangerResourceDef resourceDef : 
serviceDef.getResources()) {
-                    this.rrnTemplates.put(resourceDef.getName(), 
getDefaultRrnTemplate(resourceDef));
+                    try {
+                        RangerResourceNameParser rrnParser = 
createRrnParser(resourceDef);
+
+                        this.rrnParsers.put(resourceDef.getName(), rrnParser);
+                        this.rrnTemplates.put(resourceDef.getName(), 
rrnParser.getTemplate());
+                    } catch (RangerAuthzException excp) {
+                        LOG.error("failed to create RRN parser for resource 
[{}]", resourceDef.getName(), excp);
+                    }
                 }
             } else {
                 orderedResourceNames = new ArrayList<>();
@@ -566,10 +609,18 @@ public Set<Set<String>> getResourceHierarchyKeys(Integer 
policyType) {
             return ret != null ? ret : Collections.emptySet();
         }
 
+        public char getRrnResourceSepChar() {
+            return rrnResourceSepChar;
+        }
+
         public String getRrnTemplate(String resourceName) {
             return rrnTemplates.get(resourceName);
         }
 
+        public RangerResourceNameParser getRrnParser(String resourceName) {
+            return rrnParsers.get(resourceName);
+        }
+
         public boolean isDataMaskSupported() {
             return isDataMaskSupported;
         }
@@ -897,26 +948,14 @@ public int compareTo(ResourceNameLevel other) {
         //  column:database/table/column
         //  path:bucket/path
         //  key:volume/bucket/key
-        private String getDefaultRrnTemplate(RangerResourceDef resourceDef) {
-            List<RangerResourceDef> path = new ArrayList<>();
+        private RangerResourceNameParser createRrnParser(RangerResourceDef 
resourceDef) throws RangerAuthzException {
+            List<String> path = new ArrayList<>();
 
             for (RangerResourceDef resource = resourceDef; resource != null; 
resource = getResourceDef(resource.getParent(), 
RangerPolicy.POLICY_TYPE_ACCESS)) {
-                path.add(0, resource);
-            }
-
-            StringBuilder sb = new StringBuilder();
-
-            for (int i = 0; i < path.size(); i++) {
-                RangerResourceDef res = path.get(i);
-
-                if (i > 0) {
-                    sb.append(RRN_RESOURCE_SEP);
-                }
-
-                sb.append(res.getName());
+                path.add(0, resource.getName());
             }
 
-            return sb.toString();
+            return new 
RangerResourceNameParser(path.toArray(RangerResourceNameParser.EMPTY_ARRAY), 
rrnResourceSepChar);
         }
     }
 
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
index 8b7e9b3e4..8736cb4b2 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequest.java
@@ -19,6 +19,8 @@
 
 package org.apache.ranger.plugin.policyengine;
 
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
+
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
@@ -74,6 +76,10 @@ default Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScop
         return Collections.emptyMap();
     }
 
+    default RangerInlinePolicy getInlinePolicy() {
+        return null;
+    }
+
     enum ResourceMatchingScope { SELF, SELF_OR_DESCENDANTS }
 
     enum ResourceElementMatchingScope { SELF, SELF_OR_CHILD, SELF_OR_PREFIX }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
index cac69d52f..29320ae09 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestImpl.java
@@ -21,6 +21,7 @@
 
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,6 +60,7 @@ public class RangerAccessRequestImpl implements 
RangerAccessRequest {
     private boolean                                   
isAccessTypeDelegatedAdmin;
     private ResourceMatchingScope                     resourceMatchingScope    
     = ResourceMatchingScope.SELF;
     private Map<String, ResourceElementMatchingScope> 
resourceElementMatchingScopes = Collections.emptyMap();
+    private RangerInlinePolicy                        inlinePolicy;
 
     public RangerAccessRequestImpl() {
         this(null, null, null, null, null);
@@ -236,6 +238,11 @@ public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScope
         return this.resourceElementMatchingScopes;
     }
 
+    @Override
+    public RangerInlinePolicy getInlinePolicy() {
+        return inlinePolicy;
+    }
+
     public void setResourceElementMatchingScopes(Map<String, 
ResourceElementMatchingScope> resourceElementMatchingScopes) {
         this.resourceElementMatchingScopes = resourceElementMatchingScopes == 
null ? Collections.emptyMap() : resourceElementMatchingScopes;
     }
@@ -313,6 +320,10 @@ public void setIgnoreDescendantDeny(Boolean 
isDescendantDenyIgnored) {
         this.isDescendantDenyIgnored = isDescendantDenyIgnored == null || 
isDescendantDenyIgnored;
     }
 
+    public void setInlinePolicy(RangerInlinePolicy inlinePolicy) {
+        this.inlinePolicy = inlinePolicy;
+    }
+
     public void extractAndSetClientIPAddress(boolean useForwardedIPAddress, 
String[] trustedProxyAddresses) {
         String ip = getRemoteIPAddress();
 
@@ -393,6 +404,7 @@ public StringBuilder toString(StringBuilder sb) {
         
sb.append("resourceElementMatchingScopes={").append(resourceElementMatchingScopes).append("}
 ");
         sb.append("clusterName={").append(clusterName).append("} ");
         sb.append("clusterType={").append(clusterType).append("} ");
+        sb.append("inlinePolicy={").append(inlinePolicy).append("} ");
 
         sb.append("context={");
         if (context != null) {
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
index 2e640d24a..0a4b8b016 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestReadOnly.java
@@ -19,6 +19,8 @@
 
 package org.apache.ranger.plugin.policyengine;
 
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
+
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
@@ -153,4 +155,9 @@ public ResourceMatchingScope getResourceMatchingScope() {
     public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() {
         return source.getResourceElementMatchingScopes();
     }
+
+    @Override
+    public RangerInlinePolicy getInlinePolicy() {
+        return source.getInlinePolicy();
+    }
 }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
index 5cb032d75..ffb289822 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerAccessRequestWrapper.java
@@ -20,6 +20,7 @@
 package org.apache.ranger.plugin.policyengine;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
 
 import java.util.Date;
 import java.util.List;
@@ -148,4 +149,9 @@ public ResourceMatchingScope getResourceMatchingScope() {
     public Map<String, ResourceElementMatchingScope> 
getResourceElementMatchingScopes() {
         return request.getResourceElementMatchingScopes();
     }
+
+    @Override
+    public RangerInlinePolicy getInlinePolicy() {
+        return request.getInlinePolicy();
+    }
 }
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 0238b7e76..e40b72e92 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -26,10 +26,12 @@
 import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
 import org.apache.ranger.authorization.utils.StringUtil;
 import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefHelper;
 import org.apache.ranger.plugin.policyengine.gds.GdsAccessResult;
+import org.apache.ranger.plugin.policyevaluator.RangerInlinePolicyEvaluator;
 import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
 import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType;
 import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor;
@@ -617,6 +619,8 @@ private RangerAccessResult 
zoneAwareAccessEvaluationWithNoAudit(RangerAccessRequ
 
         updateFromGdsResult(ret);
 
+        evaluateInlinePolicy(request, ret);
+
         LOG.debug("<== 
RangerPolicyEngineImpl.zoneAwareAccessEvaluationWithNoAudit({}, policyType 
={}): {}", request, policyType, ret);
 
         return ret;
@@ -1117,6 +1121,22 @@ private void copyFromGdsResult(GdsAccessResult 
gdsResult, RangerAccessResult res
         }
     }
 
+    private void evaluateInlinePolicy(RangerAccessRequest request, 
RangerAccessResult result) {
+        if (request != null && result != null) {
+            RangerInlinePolicy inlinePolicy = request.getInlinePolicy();
+
+            if (inlinePolicy != null) {
+                LOG.debug("Evaluating inline policy: {}", inlinePolicy);
+
+                RangerInlinePolicyEvaluator evaluator = new 
RangerInlinePolicyEvaluator(inlinePolicy, this);
+
+                result.incrementEvaluatedPoliciesCount();
+
+                evaluator.evaluate(request, result);
+            }
+        }
+    }
+
     private static class ServiceConfig {
         private final Set<String> auditExcludedUsers;
         private final Set<String> auditExcludedGroups;
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerInlinePolicyEvaluator.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerInlinePolicyEvaluator.java
new file mode 100644
index 000000000..8f2b319d6
--- /dev/null
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerInlinePolicyEvaluator.java
@@ -0,0 +1,307 @@
+/*
+ * 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.policyevaluator;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.authz.api.RangerAuthzException;
+import org.apache.ranger.plugin.model.RangerInlinePolicy;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyResource;
+import org.apache.ranger.plugin.model.RangerPrincipal;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestWrapper;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import 
org.apache.ranger.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher;
+import 
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher;
+import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class RangerInlinePolicyEvaluator {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RangerInlinePolicyEvaluator.class);
+
+    private static final String PRINCIPAL_G_PUBLIC = 
RangerPrincipal.PREFIX_GROUP + RangerPolicyEngine.GROUP_PUBLIC;
+
+    private final RangerInlinePolicy   policy;
+    private final RangerPolicyEngine   policyEngine;
+    private final List<GrantEvaluator> grants;
+
+    public RangerInlinePolicyEvaluator(RangerInlinePolicy policy, 
RangerPolicyEngine policyEngine) {
+        this.policy       = policy;
+        this.policyEngine = policyEngine;
+        this.grants       = toGrantEvaluators(policy);
+
+        LOG.debug("RangerInlinePolicyEvaluator(policy={})", policy);
+    }
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder()).toString();
+    }
+
+    public void evaluate(RangerAccessRequest request, RangerAccessResult 
result) {
+        LOG.debug("==> RangerInlinePolicyEvaluator.evaluate({}, {}, {})", 
policy, request, result);
+
+        if (request != null && result != null) {
+            boolean isAllowed = result.getIsAccessDetermined() && 
result.getIsAllowed();
+            boolean evalInlinePolicy;
+
+            if (policy.getMode() == null || policy.getMode() == 
RangerInlinePolicy.Mode.INLINE) {
+                evalInlinePolicy = true; // request must be allowed by the 
inline policy
+            } else if (policy.getMode() == 
RangerInlinePolicy.Mode.RANGER_AND_INLINE) {
+                evalInlinePolicy = isAllowed; // if not allowed by Ranger 
policies, no need to evaluate inline policy
+            } else { // RANGER_OR_INLINE
+                evalInlinePolicy = !isAllowed; // if already allowed by Ranger 
policies, no need to evaluate inline policy
+            }
+
+            if (evalInlinePolicy) {
+                isAllowed = isAllowed(request);
+
+                result.setIsAllowed(isAllowed);
+                result.setIsAccessDetermined(true);
+                result.setPolicyId(-1);
+                result.setPolicyVersion(null);
+                result.setReason("inline-policy");
+            }
+        }
+
+        LOG.debug("<== RangerInlinePolicyEvaluator.evaluate({}, {}, {})", 
policy, request, result);
+    }
+
+    private boolean isAllowed(RangerAccessRequest request) {
+        boolean ret = isAllowedForGrantor(request);
+
+        if (ret && !grants.isEmpty()) {
+            for (GrantEvaluator evaluator : grants) {
+                ret = evaluator.isAllowed(request);
+
+                if (ret) {
+                    break;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    private boolean isAllowedForGrantor(RangerAccessRequest request) {
+        final boolean         ret;
+        final RangerPrincipal grantor = 
RangerPrincipal.toPrincipal(policy.getGrantor());
+
+        if (grantor != null) {
+            try (RangerGrantorAccessRequest grantorAccessReq = new 
RangerGrantorAccessRequest(request, grantor)) {
+                RangerAccessResult result = 
policyEngine.evaluatePolicies(grantorAccessReq, 
RangerPolicy.POLICY_TYPE_ACCESS, null);
+
+                ret = result != null && result.getIsAccessDetermined() && 
result.getIsAllowed();
+            }
+        } else {
+            ret = true;
+        }
+
+        return ret;
+    }
+
+    private StringBuilder toString(StringBuilder sb) {
+        sb.append("RangerInlinePolicyEvaluator={");
+
+        sb.append("policy={").append(policy).append("}");
+
+        sb.append("}");
+
+        return sb;
+    }
+
+    private List<GrantEvaluator> toGrantEvaluators(RangerInlinePolicy policy) {
+        if (CollectionUtils.isEmpty(policy.getGrants())) {
+            return Collections.emptyList();
+        }
+
+        List<GrantEvaluator> ret = new ArrayList<>(policy.getGrants().size());
+
+        for (RangerInlinePolicy.Grant grant : policy.getGrants()) {
+            GrantEvaluator evaluator = new GrantEvaluator(grant);
+
+            ret.add(evaluator);
+        }
+
+        return ret;
+    }
+
+    private class GrantEvaluator {
+        private final RangerInlinePolicy.Grant         grant;
+        private final Set<String>                      permissions;
+        private final Set<RangerPolicyResourceMatcher> resourceMatchers = new 
HashSet<>();
+
+        public GrantEvaluator(RangerInlinePolicy.Grant grant) {
+            this.grant       = grant;
+            this.permissions = 
policyEngine.getServiceDefHelper().expandImpliedAccessGrants(grant.getPermissions());
+
+            if (grant.getResources() != null) {
+                for (String resource : grant.getResources()) {
+                    try {
+                        Map<String, RangerPolicyResource> policyResources = 
policyEngine.getServiceDefHelper().parseResourceToPolicyResources(resource);
+
+                        RangerDefaultPolicyResourceMatcher resourceMatcher = 
new RangerDefaultPolicyResourceMatcher();
+
+                        
resourceMatcher.setServiceDef(policyEngine.getServiceDef());
+                        resourceMatcher.setPolicyResources(policyResources, 
RangerPolicy.POLICY_TYPE_ACCESS);
+                        
resourceMatcher.setPluginContext(policyEngine.getPluginContext());
+
+                        
resourceMatcher.setServiceDefHelper(policyEngine.getServiceDefHelper());
+                        resourceMatcher.init();
+
+                        resourceMatchers.add(resourceMatcher);
+                    } catch (RangerAuthzException excp) {
+                        LOG.debug("GrantEvaluator(): invalid resource {}", 
resource);
+                    }
+                }
+            }
+
+            LOG.debug("RangerGrantEvaluator(grant={})", grant);
+        }
+
+        public boolean isAllowed(RangerAccessRequest request) {
+            boolean ret = isPrincipalMatch(request) && 
isPermissionMatch(request) && isResourceMatch(request);
+
+            LOG.debug("isAllowed(grant={}, request={}): ret={}", grant, 
request, ret);
+
+            return ret;
+        }
+
+        private boolean isPrincipalMatch(RangerAccessRequest request) {
+            boolean ret = CollectionUtils.isEmpty(grant.getPrincipals()) || 
grant.getPrincipals().contains(PRINCIPAL_G_PUBLIC); // match all users;
+
+            if (!ret) {
+                if (StringUtils.isNotBlank(request.getUser())) {
+                    ret = 
grant.getPrincipals().contains(RangerPrincipal.PREFIX_USER + request.getUser());
+                }
+
+                if (!ret && 
CollectionUtils.isNotEmpty(request.getUserGroups())) {
+                    for (String groupName : request.getUserGroups()) {
+                        ret = 
grant.getPrincipals().contains(RangerPrincipal.PREFIX_GROUP + groupName);
+
+                        if (ret) {
+                            break;
+                        }
+                    }
+                }
+
+                if (!ret && 
CollectionUtils.isNotEmpty(request.getUserRoles())) {
+                    for (String roleName : request.getUserRoles()) {
+                        ret = 
grant.getPrincipals().contains(RangerPrincipal.PREFIX_ROLE + roleName);
+
+                        if (ret) {
+                            break;
+                        }
+                    }
+                }
+            }
+
+            LOG.debug("isPrincipalMatch(grant={}, request={}): ret={}", grant, 
request, ret);
+
+            return ret;
+        }
+
+        private boolean isPermissionMatch(RangerAccessRequest request) {
+            boolean ret = StringUtils.isNotBlank(request.getAccessType()) &&
+                    CollectionUtils.isNotEmpty(permissions) &&
+                    permissions.contains(request.getAccessType());
+
+            LOG.debug("isPermissionMatch(grant={}, request={}): ret={}", 
grant, request, ret);
+
+            return ret;
+        }
+
+        private boolean isResourceMatch(RangerAccessRequest request) {
+            boolean ret = CollectionUtils.isEmpty(grant.getResources()); // 
match all resources
+
+            if (!ret) {
+                for (RangerPolicyResourceMatcher matcher : resourceMatchers) {
+                    ret = matcher.isMatch(request.getResource(), 
request.getContext());
+
+                    if (ret) {
+                        break;
+                    }
+                }
+            }
+
+            LOG.debug("isResourceMatch(grant={}, request={}): ret={}", grant, 
request, ret);
+
+            return ret;
+        }
+    }
+
+    private static class RangerGrantorAccessRequest extends 
RangerAccessRequestWrapper implements AutoCloseable {
+        private final String      user;
+        private final Set<String> userGroups;
+        private final Set<String> userRoles;
+        private final String      savedUser;
+        private final Set<String> savedUserRoles;
+
+        public RangerGrantorAccessRequest(RangerAccessRequest request, 
RangerPrincipal grantor) {
+            super(request, request.getAccessType());
+
+            user       = grantor.getType() == 
RangerPrincipal.PrincipalType.USER ? grantor.getName() : "";
+            userGroups = grantor.getType() == 
RangerPrincipal.PrincipalType.GROUP ? Collections.singleton(grantor.getName()) 
: Collections.emptySet();
+            userRoles  = grantor.getType() == 
RangerPrincipal.PrincipalType.ROLE ? Collections.singleton(grantor.getName()) : 
Collections.emptySet();
+
+            savedUser      = 
RangerAccessRequestUtil.getCurrentUserFromContext(request.getContext());
+            savedUserRoles = 
RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext());
+
+            RangerAccessRequestUtil.setCurrentUserInContext(getContext(), 
user);
+            RangerAccessRequestUtil.setCurrentUserRolesInContext(getContext(), 
userRoles);
+        }
+
+        @Override
+        public void close() {
+            RangerAccessRequestUtil.setCurrentUserInContext(getContext(), 
savedUser);
+            RangerAccessRequestUtil.setCurrentUserRolesInContext(getContext(), 
savedUserRoles);
+        }
+
+        @Override
+        public String getUser() {
+            return user;
+        }
+
+        @Override
+        public Set<String> getUserGroups() {
+            return userGroups;
+        }
+
+        @Override
+        public Set<String> getUserRoles() {
+            return userRoles;
+        }
+
+        @Override
+        public RangerInlinePolicy getInlinePolicy() {
+            return null;
+        }
+    }
+}
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
index 3462a1662..20278f46d 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/resourcematcher/ResourceMatcher.java
@@ -39,11 +39,13 @@
 import java.util.Stack;
 
 abstract class ResourceMatcher {
-    static final         int                       DYNAMIC_EVALUATION_PENALTY 
= 8;
-    private static final Logger                    LOG                        
= LoggerFactory.getLogger(ResourceMatcher.class);
-    protected final      String                    value;
-    protected final      RangerRequestExprResolver exprResolver;
-    protected            StringTokenReplacer       tokenReplacer;
+    private static final Logger LOG = 
LoggerFactory.getLogger(ResourceMatcher.class);
+
+    static final int DYNAMIC_EVALUATION_PENALTY = 8;
+
+    protected final String                    value;
+    protected final RangerRequestExprResolver exprResolver;
+    protected       StringTokenReplacer       tokenReplacer;
 
     ResourceMatcher(String value, Map<String, String> options) {
         this.value = value;
@@ -55,6 +57,81 @@ abstract class ResourceMatcher {
         }
     }
 
+    abstract boolean isMatch(String resourceValue, Map<String, Object> 
evalContext);
+
+    abstract boolean isPrefixMatch(String resourceValue, Map<String, Object> 
evalContext);
+
+    abstract boolean isChildMatch(String resourceValue, Map<String, Object> 
evalContext);
+
+    abstract int getPriority();
+
+    @Override
+    public String toString() {
+        return this.getClass().getName() + "(" + this.value + ")";
+    }
+
+    final boolean isMatch(String resourceValue, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext) {
+        final ResourceElementMatchType matchType = getMatchType(resourceValue, 
matchingScope, evalContext);
+
+        return isMatch(matchType, matchingScope);
+    }
+
+    final ResourceElementMatchType getMatchType(String resourceValue, 
ResourceElementMatchingScope matchingScope, Map<String, Object> evalContext) {
+        ResourceElementMatchType ret = ResourceElementMatchType.NONE;
+
+        if (isMatch(resourceValue, evalContext)) {
+            ret = ResourceElementMatchType.SELF;
+        } else {
+            if (matchingScope == ResourceElementMatchingScope.SELF_OR_PREFIX) {
+                if (isPrefixMatch(resourceValue, evalContext)) {
+                    ret = ResourceElementMatchType.PREFIX;
+                }
+            } else if (matchingScope == 
ResourceElementMatchingScope.SELF_OR_CHILD) {
+                if (isChildMatch(resourceValue, evalContext)) {
+                    ret = ResourceElementMatchType.CHILD;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    boolean isMatchAny() {
+        return value != null && value.isEmpty();
+    }
+
+    boolean getNeedsDynamicEval() {
+        return exprResolver != null || tokenReplacer != null;
+    }
+
+    void setDelimiters(char startDelimiterChar, char endDelimiterChar, char 
escapeChar, String tokenPrefix) {
+        LOG.debug("==> setDelimiters(value= {}, startDelimiter={}, 
endDelimiter={}, escapeChar={}, prefix={}", value, startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
+
+        if (exprResolver != null || StringTokenReplacer.hasToken(value, 
startDelimiterChar, endDelimiterChar, escapeChar)) {
+            tokenReplacer = new StringTokenReplacer(startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
+        }
+
+        LOG.debug("<== setDelimiters(value= {}, startDelimiter={}, 
endDelimiter={}, escapeChar={}, prefix={}", value, startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
+    }
+
+    String getExpandedValue(Map<String, Object> evalContext) {
+        String ret = value;
+
+        if (exprResolver != null) {
+            RangerAccessRequest accessRequest = 
RangerAccessRequestUtil.getRequestFromContext(evalContext);
+
+            if (accessRequest != null) {
+                ret = exprResolver.resolveExpressions(accessRequest);
+            }
+        }
+
+        if (tokenReplacer != null) {
+            ret = tokenReplacer.replaceTokens(ret, evalContext);
+        }
+
+        return ret;
+    }
+
     public static boolean startsWithAnyChar(String value, String startChars) {
         boolean ret = false;
 
@@ -213,81 +290,6 @@ static List<String> splitOnTokens(String text) {
         }
     }
 
-    @Override
-    public String toString() {
-        return this.getClass().getName() + "(" + this.value + ")";
-    }
-
-    abstract boolean isMatch(String resourceValue, Map<String, Object> 
evalContext);
-
-    abstract boolean isPrefixMatch(String resourceValue, Map<String, Object> 
evalContext);
-
-    abstract boolean isChildMatch(String resourceValue, Map<String, Object> 
evalContext);
-
-    final boolean isMatch(String resourceValue, ResourceElementMatchingScope 
matchingScope, Map<String, Object> evalContext) {
-        final ResourceElementMatchType matchType = getMatchType(resourceValue, 
matchingScope, evalContext);
-
-        return isMatch(matchType, matchingScope);
-    }
-
-    final ResourceElementMatchType getMatchType(String resourceValue, 
ResourceElementMatchingScope matchingScope, Map<String, Object> evalContext) {
-        ResourceElementMatchType ret = ResourceElementMatchType.NONE;
-
-        if (isMatch(resourceValue, evalContext)) {
-            ret = ResourceElementMatchType.SELF;
-        } else {
-            if (matchingScope == ResourceElementMatchingScope.SELF_OR_PREFIX) {
-                if (isPrefixMatch(resourceValue, evalContext)) {
-                    ret = ResourceElementMatchType.PREFIX;
-                }
-            } else if (matchingScope == 
ResourceElementMatchingScope.SELF_OR_CHILD) {
-                if (isChildMatch(resourceValue, evalContext)) {
-                    ret = ResourceElementMatchType.CHILD;
-                }
-            }
-        }
-
-        return ret;
-    }
-
-    abstract int getPriority();
-
-    boolean isMatchAny() {
-        return value != null && value.isEmpty();
-    }
-
-    boolean getNeedsDynamicEval() {
-        return exprResolver != null || tokenReplacer != null;
-    }
-
-    void setDelimiters(char startDelimiterChar, char endDelimiterChar, char 
escapeChar, String tokenPrefix) {
-        LOG.debug("==> setDelimiters(value= {}, startDelimiter={}, 
endDelimiter={}, escapeChar={}, prefix={}", value, startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
-
-        if (exprResolver != null || StringTokenReplacer.hasToken(value, 
startDelimiterChar, endDelimiterChar, escapeChar)) {
-            tokenReplacer = new StringTokenReplacer(startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
-        }
-
-        LOG.debug("<== setDelimiters(value= {}, startDelimiter={}, 
endDelimiter={}, escapeChar={}, prefix={}", value, startDelimiterChar, 
endDelimiterChar, escapeChar, tokenPrefix);
-    }
-
-    String getExpandedValue(Map<String, Object> evalContext) {
-        String ret = value;
-
-        if (exprResolver != null) {
-            RangerAccessRequest accessRequest = 
RangerAccessRequestUtil.getRequestFromContext(evalContext);
-
-            if (accessRequest != null) {
-                ret = exprResolver.resolveExpressions(accessRequest);
-            }
-        }
-
-        if (tokenReplacer != null) {
-            ret = tokenReplacer.replaceTokens(ret, evalContext);
-        }
-
-        return ret;
-    }
-
     public static class PriorityComparator implements 
Comparator<ResourceMatcher>, Serializable {
         @Override
         public int compare(ResourceMatcher me, ResourceMatcher other) {
diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
index 740425ee1..52a643ead 100644
--- 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
+++ 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java
@@ -37,6 +37,8 @@
 import java.util.TreeSet;
 
 public class RangerAccessRequestUtil {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RangerAccessRequestUtil.class);
+
     public static final  String KEY_CONTEXT_TAGS                             = 
"TAGS";
     public static final  String KEY_CONTEXT_TAG_OBJECT                       = 
"TAG_OBJECT";
     public static final  String KEY_CONTEXT_RESOURCE                         = 
"RESOURCE";
@@ -56,7 +58,7 @@ public class RangerAccessRequestUtil {
     public static final  String KEY_CONTEXT_GDS_RESULT                       = 
"_GDS_RESULT";
     public static final  String KEY_CONTEXT_IS_REQUEST_PREPROCESSED          = 
"ISREQUESTPREPROCESSED";
     public static final  String KEY_CONTEXT_RESOURCE_ZONE_NAMES              = 
"RESOURCE_ZONE_NAMES";
-    private static final Logger LOG                                          = 
LoggerFactory.getLogger(RangerAccessRequestUtil.class);
+    public static final  String KEY_CONTEXT_ACL_ENFORCER                     = 
"_ACL_ENFORCER";
 
     private RangerAccessRequestUtil() {
         // to avoid instantiation
@@ -451,4 +453,20 @@ public static void setAccessTypeResult(Map<String, Object> 
context, String acces
             results.putIfAbsent(accessType, result);
         }
     }
+
+    public static String getAclEnforcerOrDefault(Map<String, Object> context, 
String defaultValue) {
+        Object ret = context != null ? context.get(KEY_CONTEXT_ACL_ENFORCER) : 
null;
+
+        return ret instanceof String ? (String) ret : defaultValue;
+    }
+
+    public static void setAclEnforcer(Map<String, Object> context, String 
aclEnforcer) {
+        if (context != null) {
+            if (aclEnforcer != null) {
+                context.put(KEY_CONTEXT_ACL_ENFORCER, aclEnforcer);
+            } else {
+                context.remove(KEY_CONTEXT_ACL_ENFORCER);
+            }
+        }
+    }
 }
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/TestInlinePolicyEvaluator.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/TestInlinePolicyEvaluator.java
new file mode 100644
index 000000000..cffdf7339
--- /dev/null
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/policyevaluator/TestInlinePolicyEvaluator.java
@@ -0,0 +1,145 @@
+/*
+ * 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.policyevaluator;
+
+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 org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
+import org.apache.ranger.plugin.audit.RangerDefaultAuditHandler;
+import org.apache.ranger.plugin.model.RangerPolicy;
+import org.apache.ranger.plugin.model.RangerServiceDef;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
+import org.apache.ranger.plugin.policyengine.RangerAccessRequestImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResource;
+import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
+import org.apache.ranger.plugin.policyengine.RangerAccessResult;
+import org.apache.ranger.plugin.policyengine.RangerAccessResultProcessor;
+import org.apache.ranger.plugin.policyengine.RangerPluginContext;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngine;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineImpl;
+import org.apache.ranger.plugin.policyengine.RangerPolicyEngineOptions;
+import org.apache.ranger.plugin.util.ServiceDefUtil;
+import org.apache.ranger.plugin.util.ServicePolicies;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.util.Date;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestInlinePolicyEvaluator {
+    Gson gsonBuilder;
+
+    @Before
+    public void init() {
+        gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSSZ")
+                .setPrettyPrinting()
+                .registerTypeAdapter(RangerAccessRequest.class, new 
RangerAccessRequestDeserializer())
+                .registerTypeAdapter(RangerAccessResource.class, new 
RangerResourceDeserializer())
+                .create();
+    }
+
+    @After
+    public void cleanup() {
+    }
+
+    @Test
+    public void testOzoneInlinePolicies() throws IOException {
+        runTests("/policyevaluator/test_inline_policies_ozone.json");
+    }
+
+    private void runTests(String resourceName) throws IOException {
+        try (InputStream inStream = 
this.getClass().getResourceAsStream(resourceName)) {
+            assertNotNull("failed to find resource '" + resourceName + "'", 
inStream);
+
+            InputStreamReader reader = new InputStreamReader(inStream);
+
+            runTestCase(gsonBuilder.fromJson(reader, 
PolicyEngineTestCase.class));
+        }
+    }
+
+    private void runTestCase(PolicyEngineTestCase testCase) {
+        ServicePolicies  servicePolicies = testCase.servicePolicies;
+        RangerServiceDef serviceDef      = servicePolicies.getServiceDef();
+
+        ServiceDefUtil.normalize(serviceDef);
+
+        RangerPolicyEngineOptions   policyEngineOptions = new 
RangerPolicyEngineOptions();
+        RangerPluginContext         pluginContext       = new 
RangerPluginContext(new RangerPluginConfig(serviceDef.getName(), 
servicePolicies.getServiceName(), null, "cl1", "on-prem", policyEngineOptions));
+        RangerPolicyEngine          policyEngine        = new 
RangerPolicyEngineImpl(servicePolicies, pluginContext, null);
+        RangerAccessResultProcessor auditHandler        = new 
RangerDefaultAuditHandler(pluginContext.getConfig());
+
+        for (TestData test : testCase.tests) {
+            RangerAccessResult  expected = test.result;
+            RangerAccessRequest request  = test.request;
+
+            RangerAccessResult result = policyEngine.evaluatePolicies(request, 
RangerPolicy.POLICY_TYPE_ACCESS, auditHandler);
+
+            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());
+            assertEquals("policyId mismatched! - " + test.name, 
expected.getPolicyId(), result.getPolicyId());
+        }
+    }
+
+    static class PolicyEngineTestCase {
+        ServicePolicies       servicePolicies;
+        public List<TestData> tests;
+    }
+
+    static class TestData {
+        public String              name;
+        public RangerAccessRequest request;
+        public RangerAccessResult  result;
+    }
+
+    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;
+        }
+    }
+
+    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/policyevaluator/test_inline_policies_ozone.json
 
b/agents-common/src/test/resources/policyevaluator/test_inline_policies_ozone.json
new file mode 100644
index 000000000..bb41f4bbd
--- /dev/null
+++ 
b/agents-common/src/test/resources/policyevaluator/test_inline_policies_ozone.json
@@ -0,0 +1,233 @@
+{
+  "servicePolicies": {
+    "serviceName": "dev_ozone", "serviceId": 1,
+
+    "serviceDef":{
+      "id": 1, "name":"ozone",
+      "resources":[
+        { "name": "volume", "level": 1, "parent": "",       
"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
 "matcherOptions": { "wildCard": true, "ignoreCase": true },  "label": 
"Volume", "description": "Volume" },
+        { "name": "bucket", "level": 2, "parent": "volume", 
"matcher":"org.apache.ranger.plugin.resourcematcher.RangerURLResourceMatcher",  
   "matcherOptions": { "wildCard": true, "ignoreCase": true },  "label": 
"Bucket", "description": "Bucket" },
+        { "name": "key",    "level": 3, "parent": "bucket", 
"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
 "matcherOptions": { "wildCard": true, "ignoreCase": true },  "label": "Key",   
 "description": "Key" },
+        { "name": "role",   "level": 4, "parent": "",       
"matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
 "matcherOptions": { "wildCard": true, "ignoreCase": false }, "label": "Role",  
 "description": "Role" }
+      ],
+      "accessTypes":[
+        { "name": "read",        "label": "Read" },
+        { "name": "write",       "label": "Write" },
+        { "name": "create",      "label": "Create" },
+        { "name": "list",        "label": "List" },
+        { "name": "delete",      "label": "Delete" },
+        { "name": "read_acl",    "label": "Read_ACL" },
+        { "name": "write_acl",   "label": "Write_ACL" },
+        { "name": "all",         "label": "All", "impliedGrants": [ "read", 
"write", "create", "list", "delete", "read_acl", "write_acl" ] },
+        { "name": "assume_role", "label": "Assume_Role" }
+      ]
+    },
+    "policies": [
+      { "id": 100, "name": "role: data-reader", "isEnabled": true, 
"isAuditEnabled": true,
+        "resources": { "role": { "values": [ "data-reader" ] } },
+        "policyItems":[
+          { "accesses": [ { "type": "assume_role" } ], "users":[ 
"svc-iceberg-rest-catalog" ] }
+        ]
+      },
+      { "id": 101, "name": "role: data-all-access", "isEnabled": true, 
"isAuditEnabled": true,
+        "resources": { "role": { "values": [ "data-all-access" ] } },
+        "policyItems":[
+          { "accesses": [ { "type": "assume_role" } ], "users":[ 
"svc-iceberg-rest-catalog" ] }
+        ]
+      },
+      { "id": 200, "name": "iceberg-data", "isEnabled": true, 
"isAuditEnabled": true,
+        "resources": { "volume": { "values": [ "s3v" ] }, "bucket": { 
"values": [ "iceberg" ] }, "key": { "values":  [ "*" ] } },
+        "policyItems":[
+          { "accesses": [ { "type": "read" }, { "type": "list" }, { "type": 
"read_acl" } ], "users": [ "analyst" ], "roles":[ "data-reader" ] },
+          { "accesses": [ { "type": "all" } ], "users":  [ "svc-etl" ], 
"roles":[ "data-all-access" ] }
+        ]
+      }
+    ],
+    "tagPolicies": { },
+    "securityZones": { }
+  },
+
+  "tests":[
+    { "name": "ALLOW 'assume_role data-reader;' for svc-iceberg-rest-catalog",
+      "request": {
+        "resource": { "elements": { "role": "data-reader" } }, "accessType": 
"assume_role", "user": "svc-iceberg-rest-catalog"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 100}
+    },
+    { "name": "ALLOW 'assume_role data-all-access;' for 
svc-iceberg-rest-catalog",
+      "request": {
+        "resource": { "elements": { "role": "data-all-access" } }, 
"accessType": "assume_role", "user": "svc-iceberg-rest-catalog"
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 101}
+    },
+    { "name": "DENY 'assume_role data-reader;' for user1",
+      "request": {
+        "resource": { "elements": { "role": "data-reader" } }, "accessType": 
"assume_role", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "DENY 'assume_role data-all-access;' for user1",
+      "request": {
+        "resource": { "elements": { "role": "data-all-access" } }, 
"accessType": "assume_role", "user": "user1"
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "ALLOW 'read s3v/iceberg/key1;' for inline-policy-reader",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": "INLINE" }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": -1}
+    },
+    { "name": "DENY 'write s3v/iceberg/key1;' for inline-policy-reader",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": "INLINE" }
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "DENY 'write s3v/warehouse/key1;' for inline-policy-reader",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "warehouse", 
"key": "key1" } }, "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": "INLINE" }
+      },
+      "result": { "isAudited": false, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "ALLOW 'read s3v/iceberg/key1;' for inline-policy-all-access",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": "INLINE" }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": -1}
+    },
+    { "name": "ALLOW 'write s3v/iceberg/key1;' for inline-policy-all-access",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": "INLINE" }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": -1}
+    },
+    { "name": "DENY 'write s3v/warehouse/key1;' for inline-policy-all-access",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "warehouse", 
"key": "key1" } }, "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": "INLINE" }
+      },
+      "result": { "isAudited": false, "isAllowed": false, "policyId": -1}
+    },
+
+
+    { "name": "ALLOW 'read s3v/iceberg/key1;' for user=analyst; inline-policy 
for key2 with mode RANGER_OR_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "analyst", "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": 
"RANGER_OR_INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "read", "list", "read_acl" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 200 }
+    },
+    { "name": "DENY 'read s3v/iceberg/key1;' for user=analyst; inline-policy 
for key2 with mode RANGER_AND_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "analyst", "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": 
"RANGER_AND_INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "read", "list", "read_acl" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "DENY 'read s3v/iceberg/key1;' for user=analyst; inline-policy 
for key2 with mode INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "analyst", "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": "INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "read", "list", "read_acl" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "ALLOW 'read s3v/iceberg/key2;' for user=analyst; inline-policy 
for key2 with mode RANGER_AND_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key2" } }, "user": "analyst", "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": 
"RANGER_OR_INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "read", "list", "read_acl" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 200 }
+    },
+    { "name": "ALLOW 'read s3v/iceberg/key2;' for user=analyst; inline-policy 
for key2 with mode INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key2" } }, "user": "analyst", "accessType": "read",
+        "inlinePolicy": { "grantor":  "r:data-reader", "mode": "INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2" ], "permissions": [ "read", "list", "read_acl" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": -1 }
+    },
+
+
+    { "name": "ALLOW 'write s3v/iceberg/key1;' for user=svc-etl; inline-policy 
for key2 with mode RANGER_OR_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "svc-etl", "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": 
"RANGER_OR_INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "all" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 200 }
+    },
+    { "name": "DENY 'write s3v/iceberg/key1;' for user=svc-etl; inline-policy 
for key2 with mode RANGER_AND_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "svc-etl", "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": 
"RANGER_AND_INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "all" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "DENY 'read s3v/iceberg/key1;' for user=svc-etl; inline-policy 
for key2 with mode INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key1" } }, "user": "svc-etl", "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": "INLINE",
+          "grants": [
+            { "principals": [ "u:analyst" ], "resources": [ 
"key:s3v/iceberg/key2"], "permissions": [ "all" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": false, "policyId": -1}
+    },
+    { "name": "ALLOW 'write s3v/iceberg/key2;' for user=svc-etl; inline-policy 
for key2 with mode RANGER_AND_INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key2" } }, "user": "svc-etl", "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": 
"RANGER_OR_INLINE",
+          "grants": [
+            { "principals": [ "u:svc-etl" ], "resources": [ 
"key:s3v/iceberg/key2" ], "permissions": [ "all" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": 200 }
+    },
+    { "name": "ALLOW 'write s3v/iceberg/key2;' for user=svc-etl; inline-policy 
for key2 with mode INLINE",
+      "request": {
+        "resource": { "elements": { "volume": "s3v", "bucket": "iceberg", 
"key": "key2" } }, "user": "svc-etl", "accessType": "write",
+        "inlinePolicy": { "grantor":  "r:data-all-access", "mode": "INLINE",
+          "grants": [
+            { "principals": [ "u:svc-etl" ], "resources": [ 
"key:s3v/iceberg/key2" ], "permissions": [ "all" ] }
+          ]
+        }
+      },
+      "result": { "isAudited": true, "isAllowed": true, "policyId": -1 }
+    }
+  ]
+}
+
diff --git 
a/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
 
b/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
index 5000a5a43..cf789f482 100644
--- 
a/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
+++ 
b/authz-api/src/main/java/org/apache/ranger/authz/util/RangerResourceNameParser.java
@@ -36,24 +36,34 @@
 public class RangerResourceNameParser {
     private static final Logger LOG = 
LoggerFactory.getLogger(RangerResourceNameParser.class);
 
-    public static final char ESCAPE_CHAR    = '\\';
-    public static final char SEPARATOR_CHAR = '/';
+    public static final String[] EMPTY_ARRAY           = new String[0];
+    public static final char     RRN_RESOURCE_TYPE_SEP = ':';
 
-    private static final String   SEPARATOR_STRING  = 
String.valueOf(SEPARATOR_CHAR);
-    private static final String   ESCAPED_SEPARATOR = "\\\\" + 
SEPARATOR_STRING;
-    private static final Pattern  SEPARATOR_PATTERN = 
Pattern.compile(SEPARATOR_STRING);
-    private static final String[] EMPTY_ARRAY       = new String[0];
+    private static final char   ESCAPE_CHAR   = '\\';
+    private static final String ESCAPE_STRING = "\\\\";
 
+    private final char     separatorChar;
+    private final String   separatorString;
+    private final String   escapedSeparator;
+    private final Pattern  separatorPattern;
     private final String   template;   // examples: database/table/column, 
bucket/volume/path
     private final String[] resources;  // examples: [database, table, column], 
  [bucket, volume, path]
 
-    public RangerResourceNameParser(String template) throws 
RangerAuthzException {
+    public RangerResourceNameParser(String[] resourcePath, char separatorChar) 
throws RangerAuthzException {
+        this(StringUtils.join(resourcePath, separatorChar), separatorChar);
+    }
+
+    public RangerResourceNameParser(String template, char separatorChar) 
throws RangerAuthzException {
         if (StringUtils.isBlank(template)) {
             throw new 
RangerAuthzException(INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE);
         }
 
-        this.template  = template;
-        this.resources = template.split(SEPARATOR_STRING); // assumption: '/' 
is not a valid character in resource names
+        this.separatorChar    = separatorChar;
+        this.separatorString  = String.valueOf(separatorChar);
+        this.escapedSeparator = ESCAPE_STRING + separatorString;
+        this.separatorPattern = Pattern.compile(separatorString);
+        this.template         = template;
+        this.resources        = template.split(separatorString); // 
assumption: separatorChar is not a valid character in resource names
     }
 
     public String getTemplate() {
@@ -93,9 +103,9 @@ public String[] parseToArray(final String resourceName) 
throws RangerAuthzExcept
 
                     continue;
                 }
-            } else if (c == SEPARATOR_CHAR) {
+            } else if (c == separatorChar) {
                 if (!isInEscape) {
-                    if (!isLastToken) { // for last token, '/' is not a 
separator
+                    if (!isLastToken) { // for last token, separatorChar is 
not a separator
                         ret[idxToken++] = token.toString();
 
                         token.setLength(0);
@@ -151,12 +161,12 @@ public String toResourceName(String[] values) {
                 value = "";
             }
 
-            if (!isLast) { // escape '/' in all but the last resource
+            if (!isLast) { // escape separatorChar in all but the last resource
                 value = escapeIfNeeded(value);
             }
 
             if (i > 0) {
-                ret.append(SEPARATOR_CHAR);
+                ret.append(separatorChar);
             }
 
             ret.append(value);
@@ -182,12 +192,12 @@ public String toResourceName(Map<String, String> values) {
                 value = "";
             }
 
-            if (!isLast) { // escape '/' in all but the last resource
+            if (!isLast) { // escape separatorChar in all but the last resource
                 value = escapeIfNeeded(value);
             }
 
             if (i > 0) {
-                ret.append(SEPARATOR_CHAR);
+                ret.append(separatorChar);
             }
 
             ret.append(value);
@@ -202,13 +212,13 @@ public String toResourceName(Map<String, String> values) {
     public String toString() {
         return "RangerResourceTemplate{" +
                 "template=" + template +
-                ", resources='" + String.join(SEPARATOR_STRING, resources) + 
"'" +
+                ", resources='" + String.join(separatorString, resources) + 
"'" +
                 "}";
     }
 
     private String escapeIfNeeded(String value) {
-        if (value.contains(SEPARATOR_STRING)) {
-            return 
SEPARATOR_PATTERN.matcher(value).replaceAll(ESCAPED_SEPARATOR);
+        if (value.contains(separatorString)) {
+            return 
separatorPattern.matcher(value).replaceAll(escapedSeparator);
         } else {
             return value;
         }
diff --git 
a/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
 
b/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
index 8c137203b..06e0fe564 100644
--- 
a/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
+++ 
b/authz-api/src/test/java/org/apache/ranger/authz/util/TestRangerResourceNameParser.java
@@ -31,10 +31,13 @@
 import static 
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE;
 import static 
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_TYPE_NOT_VALID;
 import static 
org.apache.ranger.authz.api.RangerAuthzApiErrorCode.INVALID_RESOURCE_VALUE;
+import static 
org.apache.ranger.authz.util.RangerResourceNameParser.RRN_RESOURCE_TYPE_SEP;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
 
 public class TestRangerResourceNameParser {
+    private static final char RRN_RESOURCE_SEP_CHAR = '/';
+
     @Test
     public void testValidTemplates() throws Exception {
         Object[][] testData = {
@@ -59,7 +62,7 @@ public void testValidTemplates() throws Exception {
             String                   template         = (String) test[0];
             String                   resourceType     = (String) test[1];
             int                      resourceCount    = (Integer) test[2];
-            RangerResourceNameParser resourceTemplate = new 
RangerResourceNameParser(template);
+            RangerResourceNameParser resourceTemplate = new 
RangerResourceNameParser(template, RRN_RESOURCE_SEP_CHAR);
 
             assertEquals(resourceType, resourceTemplate.getResourceType(), 
template);
             assertEquals(resourceCount, resourceTemplate.count(), template);
@@ -72,7 +75,7 @@ public void testValidTemplates() throws Exception {
     }
 
     @Test
-    public void testInvalidTemplates() throws Exception {
+    public void testInvalidTemplates() {
         String[] templates = {
                 null,
                 "",
@@ -80,7 +83,7 @@ public void testInvalidTemplates() throws Exception {
         };
 
         for (String template : templates) {
-            RangerAuthzException excp = 
assertThrowsExactly(RangerAuthzException.class, () -> new 
RangerResourceNameParser(template), template);
+            RangerAuthzException excp = 
assertThrowsExactly(RangerAuthzException.class, () -> new 
RangerResourceNameParser(template, RRN_RESOURCE_SEP_CHAR), template);
 
             assertEquals(INVALID_RESOURCE_TEMPLATE_EMPTY_VALUE.getCode(), 
excp.getErrorCode().getCode(), template);
         }
@@ -300,13 +303,13 @@ public void testResourceNameFromArrayS3() throws 
Exception {
     private static Map<String, RangerResourceNameParser> getHiveTemplates() 
throws Exception {
         Map<String, RangerResourceNameParser> ret = new HashMap<>();
 
-        ret.put("database", new RangerResourceNameParser("database"));
-        ret.put("table", new RangerResourceNameParser("database/table"));
-        ret.put("column", new 
RangerResourceNameParser("database/table/column"));
-        ret.put("udf", new RangerResourceNameParser("database/udf"));
-        ret.put("url", new RangerResourceNameParser("url"));
-        ret.put("hiveservice", new RangerResourceNameParser("hiveservice"));
-        ret.put("global", new RangerResourceNameParser("global"));
+        ret.put("database", new RangerResourceNameParser("database", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("table", new RangerResourceNameParser("database/table", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("column", new 
RangerResourceNameParser("database/table/column", RRN_RESOURCE_SEP_CHAR));
+        ret.put("udf", new RangerResourceNameParser("database/udf", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("url", new RangerResourceNameParser("url", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("hiveservice", new RangerResourceNameParser("hiveservice", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("global", new RangerResourceNameParser("global", 
RRN_RESOURCE_SEP_CHAR));
 
         return ret;
     }
@@ -314,8 +317,8 @@ private static Map<String, RangerResourceNameParser> 
getHiveTemplates() throws E
     private static Map<String, RangerResourceNameParser> getS3Templates() 
throws Exception {
         Map<String, RangerResourceNameParser> ret = new HashMap<>();
 
-        ret.put("bucket", new RangerResourceNameParser("bucket"));
-        ret.put("path", new RangerResourceNameParser("bucket/path"));
+        ret.put("bucket", new RangerResourceNameParser("bucket", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("path", new RangerResourceNameParser("bucket/path", 
RRN_RESOURCE_SEP_CHAR));
 
         return ret;
     }
@@ -323,8 +326,8 @@ private static Map<String, RangerResourceNameParser> 
getS3Templates() throws Exc
     private static Map<String, RangerResourceNameParser> 
getAdlsGen2Templates() throws Exception {
         Map<String, RangerResourceNameParser> ret = new HashMap<>();
 
-        ret.put("container", new 
RangerResourceNameParser("storageaccount/container"));
-        ret.put("relativepath", new 
RangerResourceNameParser("storageaccount/container/relativepath"));
+        ret.put("container", new 
RangerResourceNameParser("storageaccount/container", RRN_RESOURCE_SEP_CHAR));
+        ret.put("relativepath", new 
RangerResourceNameParser("storageaccount/container/relativepath", 
RRN_RESOURCE_SEP_CHAR));
 
         return ret;
     }
@@ -332,25 +335,25 @@ private static Map<String, RangerResourceNameParser> 
getAdlsGen2Templates() thro
     private static Map<String, RangerResourceNameParser> getTrinoTemplates() 
throws Exception {
         Map<String, RangerResourceNameParser> ret = new HashMap<>();
 
-        ret.put("catalog", new RangerResourceNameParser("catalog"));
-        ret.put("schema", new RangerResourceNameParser("catalog/schema"));
-        ret.put("table", new RangerResourceNameParser("catalog/schema/table"));
-        ret.put("column", new 
RangerResourceNameParser("catalog/schema/table/column"));
-        ret.put("trinouser", new RangerResourceNameParser("trinouser"));
-        ret.put("systemproperty", new 
RangerResourceNameParser("systemproperty"));
-        ret.put("sessionproperty", new 
RangerResourceNameParser("catalog/sessionproperty"));
-        ret.put("function", new RangerResourceNameParser("function"));
-        ret.put("procedure", new 
RangerResourceNameParser("catalog/schema/procedure"));
-        ret.put("schemafunction", new 
RangerResourceNameParser("catalog/schema/schemafunction"));
-        ret.put("queryid", new RangerResourceNameParser("queryid"));
-        ret.put("sysinfo", new RangerResourceNameParser("sysinfo"));
-        ret.put("role", new RangerResourceNameParser("role"));
+        ret.put("catalog", new RangerResourceNameParser("catalog", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("schema", new RangerResourceNameParser("catalog/schema", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("table", new RangerResourceNameParser("catalog/schema/table", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("column", new 
RangerResourceNameParser("catalog/schema/table/column", RRN_RESOURCE_SEP_CHAR));
+        ret.put("trinouser", new RangerResourceNameParser("trinouser", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("systemproperty", new 
RangerResourceNameParser("systemproperty", RRN_RESOURCE_SEP_CHAR));
+        ret.put("sessionproperty", new 
RangerResourceNameParser("catalog/sessionproperty", RRN_RESOURCE_SEP_CHAR));
+        ret.put("function", new RangerResourceNameParser("function", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("procedure", new 
RangerResourceNameParser("catalog/schema/procedure", RRN_RESOURCE_SEP_CHAR));
+        ret.put("schemafunction", new 
RangerResourceNameParser("catalog/schema/schemafunction", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("queryid", new RangerResourceNameParser("queryid", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("sysinfo", new RangerResourceNameParser("sysinfo", 
RRN_RESOURCE_SEP_CHAR));
+        ret.put("role", new RangerResourceNameParser("role", 
RRN_RESOURCE_SEP_CHAR));
 
         return ret;
     }
 
     private Map<String, String> parseToMap(String resource, Map<String, 
RangerResourceNameParser> templates) throws RangerAuthzException {
-        String[]                 resourceParts = resource.split(":", 2);
+        String[]                 resourceParts = 
resource.split(String.valueOf(RRN_RESOURCE_TYPE_SEP), 2);
         String                   resourceType  = resourceParts.length > 0 ? 
resourceParts[0] : null;
         String                   resourceValue = resourceParts.length > 1 ? 
resourceParts[1] : null;
         RangerResourceNameParser template      = templates.get(resourceType);
diff --git a/distro/src/main/assembly/admin-web.xml 
b/distro/src/main/assembly/admin-web.xml
index 17a4408bb..15c0f0f62 100644
--- a/distro/src/main/assembly/admin-web.xml
+++ b/distro/src/main/assembly/admin-web.xml
@@ -235,6 +235,7 @@
           <include>org.apache.tomcat:tomcat-annotations-api*</include>
           
<include>org.eclipse.jdt.core.compiler:ecj:jar:P20140317-1600</include>
           
<include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
+          <include>org.apache.ranger:ranger-authz-api</include>
           <include>org.apache.ranger:ranger-plugins-common</include>
           <include>org.apache.ranger:ugsync-util</include>
           <include>org.slf4j:slf4j-api:jar:${slf4j.version}</include>
diff --git a/distro/src/main/assembly/hbase-agent.xml 
b/distro/src/main/assembly/hbase-agent.xml
index 3748b371b..27cce24c9 100644
--- a/distro/src/main/assembly/hbase-agent.xml
+++ b/distro/src/main/assembly/hbase-agent.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/hdfs-agent.xml 
b/distro/src/main/assembly/hdfs-agent.xml
index 8432ea895..f88500a0f 100644
--- a/distro/src/main/assembly/hdfs-agent.xml
+++ b/distro/src/main/assembly/hdfs-agent.xml
@@ -72,6 +72,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/hive-agent.xml 
b/distro/src/main/assembly/hive-agent.xml
index f5f8b5bf2..b407ded85 100644
--- a/distro/src/main/assembly/hive-agent.xml
+++ b/distro/src/main/assembly/hive-agent.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/kms.xml b/distro/src/main/assembly/kms.xml
index 1aedfd9b0..1e5e7e0be 100755
--- a/distro/src/main/assembly/kms.xml
+++ b/distro/src/main/assembly/kms.xml
@@ -213,6 +213,7 @@
                     
<include>org.apache.hadoop:hadoop-common:jar:${hadoop.version}</include>
                     
<include>org.apache.hadoop:hadoop-auth:jar:${hadoop.version}</include>
                     
<include>org.apache.solr:solr-solrj:jar:${solr.version}</include>
+                    <include>org.apache.ranger:ranger-authz-api</include>
                     <include>org.apache.ranger:ranger-plugins-common</include>
                     <include>org.apache.ranger:ugsync-util</include>
                     
<include>com.kstruct:gethostname4j:jar:${kstruct.gethostname4j.version}</include>
diff --git a/distro/src/main/assembly/knox-agent.xml 
b/distro/src/main/assembly/knox-agent.xml
index d407777bf..eee995a73 100644
--- a/distro/src/main/assembly/knox-agent.xml
+++ b/distro/src/main/assembly/knox-agent.xml
@@ -45,6 +45,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-atlas.xml 
b/distro/src/main/assembly/plugin-atlas.xml
index 5d6b24adc..44e18cd37 100644
--- a/distro/src/main/assembly/plugin-atlas.xml
+++ b/distro/src/main/assembly/plugin-atlas.xml
@@ -45,6 +45,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-elasticsearch.xml 
b/distro/src/main/assembly/plugin-elasticsearch.xml
index 2f3f84d40..53e99622c 100644
--- a/distro/src/main/assembly/plugin-elasticsearch.xml
+++ b/distro/src/main/assembly/plugin-elasticsearch.xml
@@ -49,6 +49,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-es</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-kafka.xml 
b/distro/src/main/assembly/plugin-kafka.xml
index 4db4b3ede..051cfe9ed 100644
--- a/distro/src/main/assembly/plugin-kafka.xml
+++ b/distro/src/main/assembly/plugin-kafka.xml
@@ -40,6 +40,7 @@
                                 
<include>org.apache.ranger:ranger-audit-core</include>
                                 
<include>org.apache.ranger:ranger-audit-dest-hdfs</include>
                                 
<include>org.apache.ranger:ranger-audit-dest-solr</include>
+                                
<include>org.apache.ranger:ranger-authz-api</include>
                                
<include>org.apache.ranger:ranger-kafka-plugin</include>
                                
<include>org.apache.ranger:ranger-plugins-cred</include>
                                
<include>org.apache.ranger:ranger-plugins-common</include>
diff --git a/distro/src/main/assembly/plugin-kms.xml 
b/distro/src/main/assembly/plugin-kms.xml
index 2d334528c..704a083b0 100755
--- a/distro/src/main/assembly/plugin-kms.xml
+++ b/distro/src/main/assembly/plugin-kms.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-kylin.xml 
b/distro/src/main/assembly/plugin-kylin.xml
index 8b2b73748..be7a3de80 100644
--- a/distro/src/main/assembly/plugin-kylin.xml
+++ b/distro/src/main/assembly/plugin-kylin.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-ozone.xml 
b/distro/src/main/assembly/plugin-ozone.xml
index 4a39b00d7..4c9456afb 100644
--- a/distro/src/main/assembly/plugin-ozone.xml
+++ b/distro/src/main/assembly/plugin-ozone.xml
@@ -79,6 +79,7 @@
                 <include>org.apache.ranger:ranger-audit-core</include>
                 <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
                 <include>org.apache.ranger:ranger-audit-dest-solr</include>
+                <include>org.apache.ranger:ranger-authz-api</include>
                 <include>org.apache.ranger:ranger-plugins-cred</include>
                 <include>org.apache.ranger:ranger-plugins-common</include>
                 <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-presto.xml 
b/distro/src/main/assembly/plugin-presto.xml
index 4d6119771..d0abae771 100644
--- a/distro/src/main/assembly/plugin-presto.xml
+++ b/distro/src/main/assembly/plugin-presto.xml
@@ -56,6 +56,7 @@
                 <include>org.apache.ranger:ranger-audit-core</include>
                 <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
                 <include>org.apache.ranger:ranger-audit-dest-solr</include>
+                <include>org.apache.ranger:ranger-authz-api</include>
                 <include>org.apache.ranger:ranger-plugins-cred</include>
                 <include>org.apache.ranger:ranger-plugins-common</include>
                 <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-solr.xml 
b/distro/src/main/assembly/plugin-solr.xml
index d1b4471a1..27cd5e597 100644
--- a/distro/src/main/assembly/plugin-solr.xml
+++ b/distro/src/main/assembly/plugin-solr.xml
@@ -39,6 +39,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-sqoop.xml 
b/distro/src/main/assembly/plugin-sqoop.xml
index b1ade54bf..3e5c30f53 100644
--- a/distro/src/main/assembly/plugin-sqoop.xml
+++ b/distro/src/main/assembly/plugin-sqoop.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-trino.xml 
b/distro/src/main/assembly/plugin-trino.xml
index 18028ba19..8c63463dc 100644
--- a/distro/src/main/assembly/plugin-trino.xml
+++ b/distro/src/main/assembly/plugin-trino.xml
@@ -29,6 +29,7 @@
                 <include>org.apache.ranger:ranger-audit-core</include>
                 <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
                 <include>org.apache.ranger:ranger-audit-dest-solr</include>
+                <include>org.apache.ranger:ranger-authz-api</include>
                 <include>org.apache.ranger:ranger-plugins-cred</include>
                 <include>org.apache.ranger:ranger-plugins-common</include>
                 <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/plugin-yarn.xml 
b/distro/src/main/assembly/plugin-yarn.xml
index 30534109c..b4bab40a9 100644
--- a/distro/src/main/assembly/plugin-yarn.xml
+++ b/distro/src/main/assembly/plugin-yarn.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/ranger-tools.xml 
b/distro/src/main/assembly/ranger-tools.xml
index 2a8f3b178..689b239ec 100644
--- a/distro/src/main/assembly/ranger-tools.xml
+++ b/distro/src/main/assembly/ranger-tools.xml
@@ -67,6 +67,7 @@
               <include>org.apache.ranger:ranger-audit-core</include>
               <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
               <include>org.apache.ranger:ranger-audit-dest-solr</include>
+              <include>org.apache.ranger:ranger-authz-api</include>
               <include>org.apache.ranger:ranger-plugins-common</include>
               <include>org.apache.ranger:ugsync-util</include>
               <include>org.apache.ranger:ranger-plugins-audit</include>
diff --git a/distro/src/main/assembly/sample-client.xml 
b/distro/src/main/assembly/sample-client.xml
index 65b2f2071..62cd2592a 100644
--- a/distro/src/main/assembly/sample-client.xml
+++ b/distro/src/main/assembly/sample-client.xml
@@ -26,6 +26,7 @@
         <moduleSet>
             <useAllReactorProjects>true</useAllReactorProjects>
             <includes>
+                <include>org.apache.ranger:ranger-authz-api</include>
                 <include>org.apache.ranger:sample-client</include>
                 <include>org.apache.ranger:ranger-intg</include>
                 <include>org.apache.ranger:ranger-plugins-common</include>
diff --git a/distro/src/main/assembly/storm-agent.xml 
b/distro/src/main/assembly/storm-agent.xml
index 8031973a2..ee375aa88 100644
--- a/distro/src/main/assembly/storm-agent.xml
+++ b/distro/src/main/assembly/storm-agent.xml
@@ -44,6 +44,7 @@
         <include>org.apache.ranger:ranger-audit-core</include>
         <include>org.apache.ranger:ranger-audit-dest-hdfs</include>
         <include>org.apache.ranger:ranger-audit-dest-solr</include>
+        <include>org.apache.ranger:ranger-authz-api</include>
         <include>org.apache.ranger:ranger-plugins-cred</include>
         <include>org.apache.ranger:ranger-plugins-common</include>
         <include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/tagsync.xml 
b/distro/src/main/assembly/tagsync.xml
index f3c12fe2d..696dbaddc 100644
--- a/distro/src/main/assembly/tagsync.xml
+++ b/distro/src/main/assembly/tagsync.xml
@@ -55,6 +55,7 @@
                                                        
<include>org.apache.commons:commons-compress</include>
                                                        
<include>org.apache.kafka:kafka-clients:jar:${kafka.version}</include>
                                                        
<include>org.apache.ranger:credentialbuilder</include>
+                                                        
<include>org.apache.ranger:ranger-authz-api</include>
                                                        
<include>org.apache.ranger:ranger-plugins-cred</include>
                                                        
<include>org.apache.ranger:ranger-plugins-common</include>
                                                        
<include>org.apache.ranger:ugsync-util</include>
diff --git a/distro/src/main/assembly/usersync.xml 
b/distro/src/main/assembly/usersync.xml
index a15c2c317..5e7be2bfa 100644
--- a/distro/src/main/assembly/usersync.xml
+++ b/distro/src/main/assembly/usersync.xml
@@ -54,6 +54,7 @@
                                                        
<include>commons-io:commons-io:jar:${commons.io.version}</include>
                                                        
<include>org.apache.httpcomponents:httpclient:jar:${httpcomponents.httpclient.version}</include>
                                                        
<include>commons-codec:commons-codec</include>
+                                                        
<include>org.apache.ranger:ranger-authz-api</include>
                                                        
<include>org.apache.ranger:ranger-plugins-common</include>
                                                        
<include>org.apache.ranger:ugsync-util</include>
                                                        
<include>org.apache.ranger:ranger-common-ha:jar:${project.version}</include>

Reply via email to