Skip to content

Commit

Permalink
RANGER-4655: Execute and read permissions granted to a user in differ…
Browse files Browse the repository at this point in the history
…ent HDFS policies does not take effect
  • Loading branch information
kulkabhay committed Jan 16, 2024
1 parent 9e92583 commit a664de5
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,22 @@ private RangerAccessResult evaluatePoliciesForOneAccessTypeNoAudit(RangerAccessR
}
}

if (!request.isAccessTypeAny()) {
Set<String> allRequestedAccesses = RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
if (CollectionUtils.size(allRequestedAccesses) > 1 && !RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
Map<String, RangerAccessResult> accessTypeResults = RangerAccessRequestUtil.getAccessTypeResults(request.getContext());
if (accessTypeResults != null) {
if (accessTypeResults.keySet().containsAll(allRequestedAccesses)) {
// Allow
RangerAccessResult result = accessTypeResults.values().iterator().next(); // Pick one result randomly
ret.setAccessResultFrom(result);
ret.setIsAccessDetermined(true);
}
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);
}
}
}

if (!ret.getIsAccessDetermined()) {
if (isDeniedByTags) {
ret.setIsAllowed(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -818,11 +818,29 @@ protected void evaluatePolicyItems(RangerAccessRequest request, RangerPolicyReso
} else {
Set<String> allRequestedAccesses = RangerAccessRequestUtil.getAllRequestedAccessTypes(request);

if (CollectionUtils.isNotEmpty(allRequestedAccesses)) {
if (CollectionUtils.size(allRequestedAccesses) > 1) {
for (String accessType : allRequestedAccesses) {
accessResult = lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), request.getUserRoles(), accessType);
if (accessResult == null) {
break;
Integer oneAccessResult = lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), request.getUserRoles(), accessType);
if (oneAccessResult != null) {
if (oneAccessResult.equals(RangerPolicyEvaluator.ACCESS_DENIED)) {
accessResult = oneAccessResult;
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);

break;
}
if (oneAccessResult.equals(RangerPolicyEvaluator.ACCESS_ALLOWED)) {
if (!result.getIsAllowed()) { // if access is not yet allowed by another policy
if (matchType != RangerPolicyResourceMatcher.MatchType.ANCESTOR) {
RangerAccessResult oneResult = new RangerAccessResult(result.getPolicyType(), result.getServiceName(), result.getServiceDef(), result.getAccessRequest());
oneResult.setIsAllowed(true);
oneResult.setPolicyPriority(getPolicyPriority());
oneResult.setPolicyId(getPolicyId());
oneResult.setPolicyVersion(getPolicy().getVersion());

RangerAccessRequestUtil.setAccessTypeResult(request.getContext(), accessType, oneResult);
}
}
}
}
}
} else {
Expand Down Expand Up @@ -865,7 +883,7 @@ protected void evaluatePolicyItems(RangerAccessRequest request, RangerPolicyReso
updateAccessResult(oneResult, matchType, false, "matched deny-all-else policy");
}

if (request.isAccessTypeAny() || RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
if (request.isAccessTypeAny() || allRequestedAccesses.size() == 1 || RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) {
// Implement OR logic
if (oneResult.getIsAllowed()) {
allowResult = oneResult;
Expand All @@ -886,14 +904,11 @@ protected void evaluatePolicyItems(RangerAccessRequest request, RangerPolicyReso
// Implement AND logic
if (oneResult.getIsAccessDetermined() && !oneResult.getIsAllowed()) {
denyResult = oneResult;
allowResult = null;
RangerAccessRequestUtil.setAccessTypeResults(request.getContext(), null);

break;
} else if (oneResult.getIsAllowed()) {
allowResult = noResult ? null : oneResult;
} else {
noResult = true;
allowResult = null;
RangerAccessRequestUtil.setAccessTypeResult(request.getContext(), accessType, oneResult);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
import org.apache.ranger.plugin.policyengine.gds.GdsAccessResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -51,6 +52,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";
public static final String KEY_CONTEXT_ACCESS_TYPE_RESULTS = "_ACCESS_TYPE_RESULTS";

public static void setRequestTagsInContext(Map<String, Object> context, Set<RangerTagForEval> tags) {
if(CollectionUtils.isEmpty(tags)) {
Expand Down Expand Up @@ -322,4 +324,41 @@ public static String getResourceZoneNameFromContext(Map<String, Object> context)

return ret != null && ret.size() == 1 ? ret.iterator().next() : null;
}

public static void setAccessTypeResults(Map<String, Object> context, Map<String, RangerAccessResult> accessTypeResults) {
if (context != null) {
if (accessTypeResults != null) {
context.put(KEY_CONTEXT_ACCESS_TYPE_RESULTS, accessTypeResults);
} else {
context.remove(KEY_CONTEXT_ACCESS_TYPE_RESULTS);
}
}
}

public static Map<String, RangerAccessResult> getAccessTypeResults(Map<String, Object> context) {
Map<String, RangerAccessResult> ret = null;

if (context != null) {
Object o = context.get(KEY_CONTEXT_ACCESS_TYPE_RESULTS);
if (o != null) {
ret = (Map<String, RangerAccessResult>)o;
}
}

return ret;
}

public static void setAccessTypeResult(Map<String, Object> context, String accessType, RangerAccessResult result) {
if (context != null) {
Map<String, RangerAccessResult> results = getAccessTypeResults(context);

if (results == null) {
results = new HashMap<>();

setAccessTypeResults(context, results);
}

results.putIfAbsent(accessType, result);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,13 @@ public void testResourceHierarchyTags() throws Exception {
runTestsFromResourceFiles(resourceFiles);
}

@Test
public void testMultipleAccessAuthorization() throws Exception {
String[] resourceFiles = {"/policyengine/test_policyengine_hdfs_multiple_accesses.json"};

runTestsFromResourceFiles(resourceFiles);
}

private void runTestsFromResourceFiles(String[] resourceNames) {
for(String resourceName : resourceNames) {
InputStream inStream = this.getClass().getResourceAsStream(resourceName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"serviceName":"hdfsdev",

"serviceDef":{
"name":"hdfs",
"id":1,
"resources":[
{"name":"path","type":"path","level":1,"mandatory":true,"lookupSupported":true,"matcher":"org.apache.ranger.plugin.resourcematcher.RangerPathResourceMatcher","matcherOptions":{"wildCard":true, "ignoreCase":true},"label":"Resource Path","description":"HDFS file or directory path"}
],
"accessTypes":[
{"name":"read","label":"Read"},
{"name":"write","label":"Write"},
{"name":"execute","label":"Execute"}
],
"contextEnrichers":
[
{
"itemId":1,
"name" : "GeolocationEnricher",
"enricher" : "org.apache.ranger.plugin.contextenricher.RangerFileBasedGeolocationProvider",
"enricherOptions" : {
"FilePath":"/etc/ranger/geo/geo.txt", "ForceRead":"false", "IPInDotFormat":"true"
,"geolocation.meta.prefix": "TEST_"
}
}
],
"policyConditions": [
{
"itemId":1,
"name":"ScriptConditionEvaluator",
"evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
"evaluatorOptions" : {"engineName":"JavaScript"},
"label":"Script",
"description": "Script to execute"
}
]
},

"policies":[
{"id":1,"name":"audit-all-access under /public","isEnabled":true,"isAuditEnabled":true,
"resources":{"path":{"values":["/public"],"isRecursive":true}},
"policyItems":[
{"accesses":[],"users":[],"groups":["public"],"delegateAdmin":false}
]
}
,
{"id":2,"name":"allow-execute-to-all under /public/","isEnabled":true,"isAuditEnabled":false,
"resources":{"path":{"values":["/public/*"],"isRecursive":true}},
"policyItems":[
{"accesses":[{"type":"execute","isAllowed":true}],"users":[],"groups":["public"],"delegateAdmin":false}
]
}
,
{"id":3,"name":"allow-read-to-finance under /public/finance","isEnabled":true,"isAuditEnabled":true,
"resources":{"path":{"values":["/public/finance"],"isRecursive":true}},
"policyItems":[
{"accesses":[{"type":"read","isAllowed":true}],"users":["finance"],"groups":[],"delegateAdmin":false}
]
}
],

"tests":[
{"name":"ALLOW 'read_execute /public/finance' for user finance",
"request":{
"resource":{"elements":{"path":"/public/finance"}},
"accessType":"read","user":"finance","userGroups":[],"requestData":"read_execute /public/finance",
"context": {"ACCESSTYPES": [ "read", "execute" ]}

},
"result":{"isAudited":true,"isAllowed":true,"policyId":3}
}
,
{"name":"DENY 'read_execute /public/finance' for user hr",
"request":{
"resource":{"elements":{"path":"/public/finance"}},
"accessType":"read","user":"hr","userGroups":[],"requestData":"read_execute /public/finance",
"context": {"ACCESSTYPES": [ "read", "execute" ]}

},
"result":{"isAudited":true,"isAllowed":false,"policyId":-1}
}
,
{"name":"ALLOW 'execute /public/finance' for user hr",
"request":{
"resource":{"elements":{"path":"/public/finance"}},
"accessType":"execute","user":"hr","userGroups":[],"requestData":"execute /public/finance"
},
"result":{"isAudited":true,"isAllowed":true,"policyId":2}
}
]
}

0 comments on commit a664de5

Please sign in to comment.