Skip to content

Commit bc596e6

Browse files
committed
RANGER-4820: Support authorization of multiple accesses grouped by access groups in one policy engine call - #2
1 parent 7ba69cb commit bc596e6

File tree

3 files changed

+108
-61
lines changed

3 files changed

+108
-61
lines changed

agents-common/src/main/java/org/apache/ranger/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ protected void evaluatePolicyItems(RangerAccessRequest request, RangerPolicyReso
887887
}
888888
}
889889

890-
RangerAccessResult compositeAccessResult = getCompositeAccessResult(request);
890+
RangerAccessResult compositeAccessResult = getCompositeAccessResult(request, result);
891891
if (compositeAccessResult != null) {
892892
result.setAccessResultFrom(compositeAccessResult);
893893
}
@@ -937,39 +937,54 @@ private RangerAccessResult deriveAccessResultFromGroup(RangerAccessRequest reque
937937
return ret;
938938
}
939939

940-
private RangerAccessResult getCompositeAccessResult(RangerAccessRequest request) {
941-
RangerAccessResult ret = null;
942-
Set<Set<String>> allAccessTypeGroups = RangerAccessRequestUtil.getAllRequestedAccessTypeGroups(request);
943-
Set<String> allAccessTypes = RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
940+
private RangerAccessResult getCompositeAccessResult(RangerAccessRequest request, RangerAccessResult result) {
941+
RangerAccessResult ret = null;
942+
Set<Set<String>> allAccessTypeGroups = RangerAccessRequestUtil.getAllRequestedAccessTypeGroups(request);
943+
Set<String> allAccessTypes = RangerAccessRequestUtil.getAllRequestedAccessTypes(request);
944+
Set<String> ignoreIfNotDeniedAccessTypes = RangerAccessRequestUtil.getIgnoreIfNotDeniedAccessTypes(request);
944945

945946
if (CollectionUtils.isEmpty(allAccessTypeGroups)) {
946947
ret = deriveAccessResultFromGroup(request, allAccessTypes);
948+
if (ret == null && CollectionUtils.isNotEmpty(ignoreIfNotDeniedAccessTypes) && ignoreIfNotDeniedAccessTypes.containsAll(allAccessTypes)) {
949+
// group does not allow/deny access and this group's all access-types are also in the ignore-if-not-denied access-type list
950+
ret = new RangerAccessResult(result.getPolicyType(), result.getServiceName(), result.getServiceDef(), request);
951+
ret.setAuditResultFrom(result);
952+
ret.setIsAllowed(true);
953+
}
947954
} else {
948-
boolean isAccessDetermined = true;
949-
boolean isAccessAllowed = false;
950-
RangerAccessResult allowResult = null;
955+
boolean isAccessDetermined = true;
956+
boolean isAccessAllowed = false;
957+
RangerAccessResult allowResult = null;
951958

952959
for (Set<String> accessesInGroup : allAccessTypeGroups) {
953960
RangerAccessResult groupResult = deriveAccessResultFromGroup(request, accessesInGroup);
954961
if (groupResult != null) {
955962
if (!groupResult.getIsAllowed()) {
956963
// Deny
957-
isAccessAllowed = false;
958-
ret = groupResult;
964+
isAccessAllowed = false;
965+
ret = groupResult;
959966
break;
960967
} else {
961-
isAccessAllowed = true;
968+
isAccessAllowed = true;
962969
if (allowResult == null) {
963970
allowResult = groupResult;
964971
}
965972
}
966973
} else {
967974
// Some group is not completely authorized yet
968-
isAccessDetermined = false;
975+
if (!(CollectionUtils.isNotEmpty(ignoreIfNotDeniedAccessTypes) && ignoreIfNotDeniedAccessTypes.containsAll(accessesInGroup))) {
976+
// group does not allow/deny access and this group's all access-types are also in the ignore-if-not-denied access-type list
977+
isAccessDetermined = false;
978+
}
969979
}
970980
}
981+
971982
if (isAccessDetermined && isAccessAllowed) {
972983
ret = allowResult;
984+
} else if (isAccessDetermined && ret == null) { // If none of the groups allowed/denied access and every group's all access-type results are to be ignored unless denied
985+
ret = new RangerAccessResult(result.getPolicyType(), result.getServiceName(), result.getServiceDef(), request);
986+
ret.setAuditResultFrom(result);
987+
ret.setIsAllowed(true);
973988
}
974989
}
975990
return ret;

agents-common/src/main/java/org/apache/ranger/plugin/util/RangerAccessRequestUtil.java

Lines changed: 75 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -34,29 +34,30 @@
3434
public class RangerAccessRequestUtil {
3535
private static final Logger LOG = LoggerFactory.getLogger(RangerAccessRequestUtil.class);
3636

37-
public static final String KEY_CONTEXT_TAGS = "TAGS";
38-
public static final String KEY_CONTEXT_TAG_OBJECT = "TAG_OBJECT";
39-
public static final String KEY_CONTEXT_RESOURCE = "RESOURCE";
40-
public static final String KEY_CONTEXT_REQUESTED_RESOURCES = "REQUESTED_RESOURCES";
41-
public static final String KEY_CONTEXT_USERSTORE = "USERSTORE";
42-
public static final String KEY_TOKEN_NAMESPACE = "token:";
43-
public static final String KEY_USER = "USER";
44-
public static final String KEY_OWNER = "OWNER";
45-
public static final String KEY_ROLES = "ROLES";
46-
public static final String KEY_CONTEXT_IS_ANY_ACCESS = "ISANYACCESS";
47-
public static final String KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS = "ALLACCESSTYPEGROUPS";
48-
public static final String KEY_CONTEXT_ALL_ACCESSTYPES = "ALLACCESSTYPES";
49-
public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS = "ALL_ACCESS_TYPE_RESULTS";
50-
public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS = "ALL_ACCESS_TYPE_ACL_RESULTS";
51-
52-
public static final String KEY_CONTEXT_REQUEST = "_REQUEST";
53-
public static final String KEY_CONTEXT_GDS_RESULT = "_GDS_RESULT";
54-
public static final String KEY_CONTEXT_IS_REQUEST_PREPROCESSED = "ISREQUESTPREPROCESSED";
55-
public static final String KEY_CONTEXT_RESOURCE_ZONE_NAMES = "RESOURCE_ZONE_NAMES";
56-
public static final String KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS = "_IS_SKIP_CHAINED_PLUGINS";
37+
public static final String KEY_CONTEXT_TAGS = "TAGS";
38+
public static final String KEY_CONTEXT_TAG_OBJECT = "TAG_OBJECT";
39+
public static final String KEY_CONTEXT_RESOURCE = "RESOURCE";
40+
public static final String KEY_CONTEXT_REQUESTED_RESOURCES = "REQUESTED_RESOURCES";
41+
public static final String KEY_CONTEXT_USERSTORE = "USERSTORE";
42+
public static final String KEY_TOKEN_NAMESPACE = "token:";
43+
public static final String KEY_USER = "USER";
44+
public static final String KEY_OWNER = "OWNER";
45+
public static final String KEY_ROLES = "ROLES";
46+
public static final String KEY_CONTEXT_IS_ANY_ACCESS = "ISANYACCESS";
47+
public static final String KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS = "ALLACCESSTYPEGROUPS";
48+
public static final String KEY_CONTEXT_ALL_ACCESSTYPES = "ALLACCESSTYPES";
49+
public static final String KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES = "IGNOREIFNOTDENIEDACCESSTYPES";
50+
public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS = "ALL_ACCESS_TYPE_RESULTS";
51+
public static final String KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS = "ALL_ACCESS_TYPE_ACL_RESULTS";
52+
53+
public static final String KEY_CONTEXT_REQUEST = "_REQUEST";
54+
public static final String KEY_CONTEXT_GDS_RESULT = "_GDS_RESULT";
55+
public static final String KEY_CONTEXT_IS_REQUEST_PREPROCESSED = "ISREQUESTPREPROCESSED";
56+
public static final String KEY_CONTEXT_RESOURCE_ZONE_NAMES = "RESOURCE_ZONE_NAMES";
57+
public static final String KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS = "_IS_SKIP_CHAINED_PLUGINS";
5758

5859
public static void setRequestTagsInContext(Map<String, Object> context, Set<RangerTagForEval> tags) {
59-
if(CollectionUtils.isEmpty(tags)) {
60+
if (CollectionUtils.isEmpty(tags)) {
6061
context.remove(KEY_CONTEXT_TAGS);
6162
} else {
6263
context.put(KEY_CONTEXT_TAGS, tags);
@@ -65,12 +66,11 @@ public static void setRequestTagsInContext(Map<String, Object> context, Set<Rang
6566

6667
public static Set<RangerTagForEval> getRequestTagsFromContext(Map<String, Object> context) {
6768
Set<RangerTagForEval> ret = null;
68-
Object val = context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
69+
Object val = context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS);
6970

7071
if (val instanceof Set<?>) {
7172
try {
72-
@SuppressWarnings("unchecked")
73-
Set<RangerTagForEval> tags = (Set<RangerTagForEval>) val;
73+
@SuppressWarnings("unchecked") Set<RangerTagForEval> tags = (Set<RangerTagForEval>) val;
7474

7575
ret = tags;
7676
} catch (Throwable t) {
@@ -87,10 +87,10 @@ public static void setCurrentTagInContext(Map<String, Object> context, RangerTag
8787

8888
public static RangerTagForEval getCurrentTagFromContext(Map<String, Object> context) {
8989
RangerTagForEval ret = null;
90-
Object val = context.get(KEY_CONTEXT_TAG_OBJECT);
90+
Object val = context.get(KEY_CONTEXT_TAG_OBJECT);
9191

92-
if(val instanceof RangerTagForEval) {
93-
ret = (RangerTagForEval)val;
92+
if (val instanceof RangerTagForEval) {
93+
ret = (RangerTagForEval) val;
9494
}
9595

9696
return ret;
@@ -104,8 +104,8 @@ public static RangerRequestedResources getRequestedResourcesFromContext(Map<Stri
104104
RangerRequestedResources ret = null;
105105
Object val = context.get(KEY_CONTEXT_REQUESTED_RESOURCES);
106106

107-
if(val instanceof RangerRequestedResources) {
108-
ret = (RangerRequestedResources)val;
107+
if (val instanceof RangerRequestedResources) {
108+
ret = (RangerRequestedResources) val;
109109
}
110110

111111
return ret;
@@ -119,8 +119,8 @@ public static RangerAccessResource getCurrentResourceFromContext(Map<String, Obj
119119
RangerAccessResource ret = null;
120120
Object val = MapUtils.isNotEmpty(context) ? context.get(KEY_CONTEXT_RESOURCE) : null;
121121

122-
if(val instanceof RangerAccessResource) {
123-
ret = (RangerAccessResource)val;
122+
if (val instanceof RangerAccessResource) {
123+
ret = (RangerAccessResource) val;
124124
}
125125

126126
return ret;
@@ -129,7 +129,7 @@ public static RangerAccessResource getCurrentResourceFromContext(Map<String, Obj
129129
public static Map<String, Object> copyContext(Map<String, Object> context) {
130130
final Map<String, Object> ret;
131131

132-
if(MapUtils.isEmpty(context)) {
132+
if (MapUtils.isEmpty(context)) {
133133
ret = new HashMap<>();
134134
} else {
135135
ret = new HashMap<>(context);
@@ -145,6 +145,7 @@ public static Map<String, Object> copyContext(Map<String, Object> context) {
145145
ret.remove(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
146146
ret.remove(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
147147
ret.remove(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
148+
ret.remove(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES);
148149
// don't remove REQUESTED_RESOURCES
149150
}
150151

@@ -154,9 +155,11 @@ public static Map<String, Object> copyContext(Map<String, Object> context) {
154155
public static void setCurrentUserInContext(Map<String, Object> context, String user) {
155156
setTokenInContext(context, KEY_USER, user);
156157
}
158+
157159
public static void setOwnerInContext(Map<String, Object> context, String owner) {
158160
setTokenInContext(context, KEY_OWNER, owner);
159161
}
162+
160163
public static String getCurrentUserFromContext(Map<String, Object> context) {
161164
Object ret = getTokenFromContext(context, KEY_USER);
162165
return ret != null ? ret.toString() : "";
@@ -166,21 +169,22 @@ public static void setTokenInContext(Map<String, Object> context, String tokenNa
166169
String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
167170
context.put(tokenNameWithNamespace, tokenValue);
168171
}
172+
169173
public static Object getTokenFromContext(Map<String, Object> context, String tokenName) {
170174
String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName;
171175
return MapUtils.isNotEmpty(context) ? context.get(tokenNameWithNamespace) : null;
172176
}
173177

174-
public static void setCurrentUserRolesInContext(Map<String, Object> context, Set<String> roles) {
175-
setTokenInContext(context, KEY_ROLES, roles);
176-
}
178+
public static void setCurrentUserRolesInContext(Map<String, Object> context, Set<String> roles) {
179+
setTokenInContext(context, KEY_ROLES, roles);
180+
}
177181

178-
public static Set<String> getCurrentUserRolesFromContext(Map<String, Object> context) {
179-
Object ret = getTokenFromContext(context, KEY_ROLES);
180-
return ret != null ? (Set<String>) ret : Collections.EMPTY_SET;
181-
}
182+
public static Set<String> getCurrentUserRolesFromContext(Map<String, Object> context) {
183+
Object ret = getTokenFromContext(context, KEY_ROLES);
184+
return ret != null ? (Set<String>) ret : Collections.EMPTY_SET;
185+
}
182186

183-
public static Set<String> getUserRoles(RangerAccessRequest request) {
187+
public static Set<String> getUserRoles(RangerAccessRequest request) {
184188
Set<String> ret = Collections.EMPTY_SET;
185189

186190
if (request != null) {
@@ -200,9 +204,9 @@ public static void setRequestUserStoreInContext(Map<String, Object> context, Ran
200204

201205
public static RangerUserStore getRequestUserStoreFromContext(Map<String, Object> context) {
202206
RangerUserStore ret = null;
203-
Object val = context.get(KEY_CONTEXT_USERSTORE);
207+
Object val = context.get(KEY_CONTEXT_USERSTORE);
204208

205-
if(val instanceof RangerUserStore) {
209+
if (val instanceof RangerUserStore) {
206210
ret = (RangerUserStore) val;
207211
}
208212

@@ -214,7 +218,7 @@ public static void setIsAnyAccessInContext(Map<String, Object> context, Boolean
214218
}
215219

216220
public static boolean getIsAnyAccessInContext(Map<String, Object> context) {
217-
Boolean value = (Boolean)context.get(KEY_CONTEXT_IS_ANY_ACCESS);
221+
Boolean value = (Boolean) context.get(KEY_CONTEXT_IS_ANY_ACCESS);
218222
return value != null && value;
219223
}
220224

@@ -223,14 +227,36 @@ public static void setIsRequestPreprocessed(Map<String, Object> context, Boolean
223227
}
224228

225229
public static boolean getIsRequestPreprocessed(Map<String, Object> context) {
226-
Boolean value = (Boolean)context.get(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
230+
Boolean value = (Boolean) context.get(KEY_CONTEXT_IS_REQUEST_PREPROCESSED);
227231
return value != null && value;
228232
}
229233

230234
public static void setAllRequestedAccessTypes(Map<String, Object> context, Set<String> accessTypes) {
231235
context.put(KEY_CONTEXT_ALL_ACCESSTYPES, accessTypes);
232236
}
233237

238+
public static void setIgnoreIfNotDeniedAccessTypes(Map<String, Object> context, Set<String> accessTypes) {
239+
context.put(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES, accessTypes);
240+
}
241+
242+
public static Set<String> getIgnoreIfNotDeniedAccessTypes(RangerAccessRequest request) {
243+
Set<String> ret = Collections.emptySet();
244+
245+
Object val = request.getContext().get(KEY_CONTEXT_IGNORE_IF_NOT_DENIED_ACCESSTYPES);
246+
247+
if (val != null) {
248+
if (val instanceof Set<?>) {
249+
ret = (Set<String>) val;
250+
} else if (val instanceof List<?>) {
251+
ret = new TreeSet<>((List<String>) val);
252+
} else {
253+
LOG.error("getNotDeniedRequestedAccessTypes(): failed to get NOTDENIEDACCESSTYPES from context");
254+
}
255+
}
256+
return ret;
257+
}
258+
259+
234260
@SuppressWarnings("unchecked")
235261
public static Set<String> getAllRequestedAccessTypes(RangerAccessRequest request) {
236262
Set<String> ret = null;
@@ -251,7 +277,7 @@ public static Set<String> getAllRequestedAccessTypes(RangerAccessRequest request
251277
}
252278

253279
public static Set<Set<String>> getAllRequestedAccessTypeGroups(RangerAccessRequest request) {
254-
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS);
280+
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESSTYPE_GROUPS);
255281
return (Set<Set<String>>) val;
256282
}
257283

@@ -265,7 +291,7 @@ public static void setAllRequestedAccessTypeGroups(RangerAccessRequest request,
265291

266292
public static Map<String, RangerAccessResult> getAccessTypeResults(RangerAccessRequest request) {
267293
Map<String, RangerAccessResult> ret;
268-
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
294+
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
269295
if (val == null) {
270296
ret = new HashMap<>();
271297
request.getContext().put(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS, ret);
@@ -277,7 +303,7 @@ public static Map<String, RangerAccessResult> getAccessTypeResults(RangerAccessR
277303

278304
public static Map<String, Integer> getAccessTypeACLResults(RangerAccessRequest request) {
279305
Map<String, Integer> ret;
280-
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
306+
Object val = request.getContext().get(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS);
281307
if (val == null) {
282308
ret = new HashMap<>();
283309
request.getContext().put(KEY_CONTEXT_ALL_ACCESS_TYPE_ACL_RESULTS, ret);
@@ -400,7 +426,7 @@ public static Map<String, RangerAccessResult> getAccessTypeResults(Map<String, O
400426
if (context != null) {
401427
Object o = context.get(KEY_CONTEXT_ALL_ACCESS_TYPE_RESULTS);
402428
if (o != null) {
403-
ret = (Map<String, RangerAccessResult>)o;
429+
ret = (Map<String, RangerAccessResult>) o;
404430
}
405431
}
406432

@@ -426,7 +452,7 @@ public static void setIsSkipChainedPlugins(Map<String, Object> context, Boolean
426452
}
427453

428454
public static boolean getIsSkipChainedPlugins(Map<String, Object> context) {
429-
Boolean value = (Boolean)context.get(KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS);
455+
Boolean value = (Boolean) context.get(KEY_CONTEXT_IS_SKIP_CHAINED_PLUGINS);
430456
return value != null && value;
431457
}
432458
}

hdfs-agent/src/main/java/org/apache/ranger/authorization/hadoop/RangerHdfsAuthorizer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,9 @@ private AuthzStatus isAccessAllowed(INode inode, INodeAttributes inodeAttribs, S
899899

900900
RangerAccessRequestUtil.setAllRequestedAccessTypeGroups(request, allAccessTypeGroups);
901901
RangerAccessRequestUtil.setAllRequestedAccessTypes(request.getContext(), accessTypes);
902+
if (accessTypes.contains(EXECUTE_ACCCESS_TYPE)) {
903+
RangerAccessRequestUtil.setIgnoreIfNotDeniedAccessTypes(request.getContext(), access2ActionListMapper.get(FsAction.EXECUTE));
904+
}
902905
}
903906

904907
// if the request was already allowed by a Ranger policy (for ancestor/parent/node/child), skip chained plugin evaluations in subsequent calls
@@ -979,6 +982,9 @@ private AuthzStatus isAccessAllowedForHierarchy(INode inode, INodeAttributes ino
979982

980983
RangerAccessRequestUtil.setAllRequestedAccessTypeGroups(request, allAccessTypeGroups);
981984
RangerAccessRequestUtil.setAllRequestedAccessTypes(request.getContext(), accessTypes);
985+
if (accessTypes.contains(EXECUTE_ACCCESS_TYPE)) {
986+
RangerAccessRequestUtil.setIgnoreIfNotDeniedAccessTypes(request.getContext(), access2ActionListMapper.get(FsAction.EXECUTE));
987+
}
982988
}
983989

984990
RangerAccessResult result = context.plugin.isAccessAllowed(request, null);

0 commit comments

Comments
 (0)