This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.8
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.8 by this push:
new 80fd1bd40 RANGER-5369: introduce inline-policy to support
service-managed ACLs (#743)
80fd1bd40 is described below
commit 80fd1bd40a4da450642e3eb9094430fe7617ef5e
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Mon Dec 1 17:57:02 2025 -0800
RANGER-5369: introduce inline-policy to support service-managed ACLs (#743)
(cherry picked from commit 6138a418e882566e238e4a918aea075cf08c9e93)
---
agents-common/pom.xml | 5 +
.../plugin/audit/RangerDefaultAuditHandler.java | 2 +-
.../ranger/plugin/model/RangerInlinePolicy.java | 178 ++++++++++++
.../ranger/plugin/model/RangerPrincipal.java | 21 +-
.../ranger/plugin/model/RangerServiceDef.java | 5 +-
.../model/validation/RangerServiceDefHelper.java | 109 ++++++--
.../plugin/policyengine/RangerAccessRequest.java | 6 +
.../policyengine/RangerAccessRequestImpl.java | 12 +
.../policyengine/RangerAccessRequestReadOnly.java | 6 +
.../policyengine/RangerAccessRequestWrapper.java | 5 +
.../policyengine/RangerPolicyEngineImpl.java | 20 ++
.../RangerInlinePolicyEvaluator.java | 307 +++++++++++++++++++++
.../plugin/util/RangerAccessRequestUtil.java | 18 +-
.../policyevaluator/TestInlinePolicyEvaluator.java | 145 ++++++++++
.../test_inline_policies_ozone.json | 232 ++++++++++++++++
.../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 | 2 +
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 +
39 files changed, 1128 insertions(+), 71 deletions(-)
diff --git a/agents-common/pom.xml b/agents-common/pom.xml
index 95cf2557f..1b811a8be 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 58f003d0a..d6ec7a177 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
@@ -131,7 +131,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) {
ret.setTags(tags);
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..f9144d265
--- /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 +
+ '}';
+ }
+ }
+}
\ No newline at end of file
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 bf9692259..5202108c0 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;
@@ -36,7 +37,9 @@
public class RangerPrincipal implements java.io.Serializable {
private static final long serialVersionUID = 1L;
- public enum PrincipalType { USER, GROUP, ROLE }
+ 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;
@@ -94,4 +97,20 @@ public boolean equals(Object obj) {
public String toString() {
return "{type=" + type + ", name=" + name + "}";
}
+
+ 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 eeabde089..46b0f5867 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,7 +42,10 @@ 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_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 e163f0ffb..afc9019f9 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
@@ -36,7 +36,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;
@@ -46,6 +50,9 @@
import org.apache.ranger.plugin.resourcematcher.RangerAbstractResourceMatcher;
import org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher;
+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);
@@ -203,10 +210,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();
}
@@ -385,6 +400,50 @@ public Map<String, Collection<String>>
getImpliedAccessGrants() {
return _delegate.getImpliedAccessGrants();
}
+ public Set<String> expandImpliedAccessGrants(Set<String> accessTypes) {
+ final Set<String> ret;
+
+ if (CollectionUtils.isNotEmpty(accessTypes)) {
+ Map<String, Collection<String>> impliedGrants =
getImpliedAccessGrants();
+
+ if (CollectionUtils.containsAny(impliedGrants.keySet(),
accessTypes)) {
+ ret = new HashSet<>(accessTypes);
+
+ for (String accessType : accessTypes) {
+ Collection<String> impliedAccessTypes =
impliedGrants.get(accessType);
+
+ if
(CollectionUtils.isNotEmpty(impliedAccessTypes)) {
+ ret.addAll(impliedAccessTypes);
+ }
+ }
+ } else {
+ ret = accessTypes;
+ }
+ } else {
+ ret = Collections.emptySet();
+ }
+
+ 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.
*/
@@ -402,7 +461,9 @@ static class Delegate {
final Set<String> _allAccessTypes;
final boolean isDataMaskSupported;
final boolean isRowFilterSupported;
- final Map<String, String> rrnTemplates = new
HashMap<>();
+ final char rrnResourceSepChar;
+ final Map<String, String> rrnTemplates = new
HashMap<>();
+ final Map<String, RangerResourceNameParser> rrnParsers = new
HashMap<>();
final static Set<List<RangerResourceDef>>
EMPTY_RESOURCE_HIERARCHY = Collections.unmodifiableSet(new
HashSet<List<RangerResourceDef>>());
@@ -442,16 +503,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<>();
@@ -525,10 +596,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;
}
@@ -856,26 +935,14 @@ private List<String> buildSortedResourceNames() {
// 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 2f3e51d33..bd2b11708 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;
@@ -72,6 +74,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 8da19b63d..1a267c11f 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
@@ -30,6 +30,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);
@@ -201,6 +203,11 @@ public boolean isAccessTypeDelegatedAdmin() {
return isAccessTypeDelegatedAdmin;
}
+ @Override
+ public RangerInlinePolicy getInlinePolicy() {
+ return inlinePolicy;
+ }
+
public void setResource(RangerAccessResource resource) {
this.resource = resource;
if (context != null) {
@@ -307,6 +314,10 @@ public void setContext(Map<String, Object> context) {
}
}
+ public void setInlinePolicy(RangerInlinePolicy inlinePolicy) {
+ this.inlinePolicy = inlinePolicy;
+ }
+
public void extractAndSetClientIPAddress(boolean useForwardedIPAddress,
String[] trustedProxyAddresses) {
String ip = getRemoteIPAddress();
if (ip == null) {
@@ -389,6 +400,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 1669efb1c..5d8ed60fc 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;
@@ -110,4 +112,8 @@ public class RangerAccessRequestReadOnly implements
RangerAccessRequest {
@Override
public String getClusterType() { return source.getClusterType();
}
+ @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 702fbe0b6..f07985721 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;
@@ -107,5 +108,9 @@ public RangerAccessRequestWrapper(RangerAccessRequest
request, String accessType
@Override
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 7067d72c1..3c69fae40 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
@@ -27,9 +27,11 @@
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.policyevaluator.RangerInlinePolicyEvaluator;
import org.apache.ranger.plugin.policyevaluator.RangerPolicyEvaluator;
import
org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType;
import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor;
@@ -672,6 +674,8 @@ private RangerAccessResult
zoneAwareAccessEvaluationWithNoAudit(RangerAccessRequ
}
}
+ evaluateInlinePolicy(request, ret);
+
if (LOG.isDebugEnabled()) {
LOG.debug("<==
RangerPolicyEngineImpl.zoneAwareAccessEvaluationWithNoAudit(" + request + ",
policyType =" + policyType + "): " + ret);
}
@@ -1154,6 +1158,22 @@ private boolean getIsFallbackSupported() {
return
policyEngine.getPluginContext().getConfig().getIsFallbackSupported();
}
+ 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..05e372c48
--- /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;
+ }
+ }
+}
\ No newline at end of file
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 f76f91275..f1e85774b 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
@@ -51,7 +51,7 @@ public class RangerAccessRequestUtil {
public static final String KEY_CONTEXT_RESOURCE_ZONE_NAMES
= "RESOURCE_ZONE_NAMES";
public static final String KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS
= "ALLACCESSTYPEGROUPS";
public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS
= "ALL_ACCESS_TYPE_ACL_RESULTS";
-
+ public static final String KEY_CONTEXT_ACL_ENFORCER
= "_ACL_ENFORCER";
public static void setRequestTagsInContext(Map<String, Object> context,
Set<RangerTagForEval> tags) {
if (CollectionUtils.isEmpty(tags)) {
@@ -416,4 +416,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..7e1438eb4
--- /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);
+ }
+ }
+}
\ No newline at end of file
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..809c791a3
--- /dev/null
+++
b/agents-common/src/test/resources/policyevaluator/test_inline_policies_ozone.json
@@ -0,0 +1,232 @@
+{
+ "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 67724991f..dd7c90e53 100644
--- a/distro/src/main/assembly/admin-web.xml
+++ b/distro/src/main/assembly/admin-web.xml
@@ -236,6 +236,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 f45c091d6..5e1dfdefd 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..f8ea94716 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>
@@ -282,6 +283,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/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 d98234ad9..e1b106166 100644
--- a/distro/src/main/assembly/plugin-elasticsearch.xml
+++ b/distro/src/main/assembly/plugin-elasticsearch.xml
@@ -50,6 +50,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 722e36782..4f2a90b92 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 786da9359..8d5c8d5a2 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 2db3de477..d991c5355 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 3b591c836..e57f1ea46 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 d719eb8f7..bfbccfaab 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 78f085afc..c6af0fcbe 100644
--- a/distro/src/main/assembly/ranger-tools.xml
+++ b/distro/src/main/assembly/ranger-tools.xml
@@ -68,6 +68,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 5cbff941a..833f7963a 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 c9d9fe46f..dd6684af7 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..d5cba0101 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 8b0c71cee..c94099675 100644
--- a/distro/src/main/assembly/usersync.xml
+++ b/distro/src/main/assembly/usersync.xml
@@ -55,6 +55,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>