This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new c96bc8b RANGER-3586: updated script evaluator to support csv of group/tag attributes c96bc8b is described below commit c96bc8b4a7ac1412b43524cce193c5006c90516d Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Sat Jan 15 10:55:16 2022 -0800 RANGER-3586: updated script evaluator to support csv of group/tag attributes --- .../policyengine/RangerRequestScriptEvaluator.java | 326 +++++++++++++++++---- .../RangerRequestScriptEvaluatorTest.java | 20 ++ 2 files changed, 291 insertions(+), 55 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java index 509244c..e3ce559 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java @@ -67,11 +67,21 @@ public final class RangerRequestScriptEvaluator { SCRIPT_VAR_TAGNAMES + "=" + SCRIPT_VAR__CTX + "." + SCRIPT_FIELD_TAG_NAMES + ";"; private static final Pattern JSON_VAR_NAMES_PATTERN = Pattern.compile(getJsonVarNamesPattern()); + private static final Character CHAR_QUOTE = '\''; + private static final Character CHAR_COMMA = ','; private static String[] dateFormatStrings = null; - private final RangerAccessRequest accessRequest; - private Boolean result = false; + private final RangerAccessRequest accessRequest; + private boolean initDone = false; + private Map<String, String> userAttrs = Collections.emptyMap(); + private Map<String, Map<String, String>> groupAttrs = Collections.emptyMap(); + private Map<String, Map<String, Object>> tags = Collections.emptyMap(); + private Map<String, Object> tag = Collections.emptyMap(); + private Collection<String> userGroups = Collections.emptySet(); + private Collection<String> userRoles = Collections.emptySet(); + private Collection<String> tagNames = Collections.emptySet(); + private Boolean result = false; static { init(null); @@ -110,7 +120,6 @@ public final class RangerRequestScriptEvaluator { return ret; } - public RangerRequestScriptEvaluator(final RangerAccessRequest accessRequest) { this.accessRequest = accessRequest.getReadOnlyCopy(); } @@ -187,11 +196,10 @@ public final class RangerRequestScriptEvaluator { Map<String, Object> ret = new HashMap<>(); Map<String, Object> request = new HashMap<>(); - RangerUserStore userStore = RangerAccessRequestUtil.getRequestUserStoreFromContext(accessRequest.getContext()); - Collection<String> userGroups = getSorted(getUserGroups()); - Collection<String> userRoles = getSorted(getUserRoles()); Date accessTime = accessRequest.getAccessTime(); + init(); + if (accessTime != null) { request.put(SCRIPT_FIELD_ACCESS_TIME, accessTime.getTime()); } @@ -220,57 +228,16 @@ public final class RangerRequestScriptEvaluator { request.put(SCRIPT_FIELD_USER_GROUPS, userGroups); request.put(SCRIPT_FIELD_USER_ROLES, userRoles); - Map<String, Map<String, String>> userAttrMapping = userStore != null ? userStore.getUserAttrMapping() : Collections.emptyMap(); - Map<String, Map<String, String>> groupAttrMapping = userStore != null ? userStore.getGroupAttrMapping() : Collections.emptyMap(); - Map<String, String> userAttrs = userAttrMapping.get(accessRequest.getUser()); - Map<String, Map<String, String>> groupAttrs = new HashMap<>(); - - userAttrs = userAttrs != null ? new HashMap<>(userAttrs) : new HashMap<>(); - - userAttrs.put(SCRIPT_FIELD__NAME, getUser()); - request.put(SCRIPT_FIELD_USER_ATTRIBUTES, userAttrs); - if (userGroups != null) { - for (String groupName : userGroups) { - Map<String, String> attrs = groupAttrMapping.get(groupName); - - attrs = attrs != null ? new HashMap<>(attrs) : new HashMap<>(); - - attrs.put(SCRIPT_FIELD__NAME, groupName); - - groupAttrs.put(groupName, attrs); - } - } - request.put(SCRIPT_FIELD_USER_GROUP_ATTRIBUTES, groupAttrs); request.put(SCRIPT_FIELD_UGA, new UserGroupsAttributes(userGroups, groupAttrs).getAttributes()); ret.put(SCRIPT_FIELD_REQUEST, request); - Set<RangerTagForEval> requestTags = RangerAccessRequestUtil.getRequestTagsFromContext(getRequestContext()); - - if (CollectionUtils.isNotEmpty(requestTags)) { - Map<String, Map<String, Object>> tags = new HashMap(); - Set<String> tagNames = new HashSet<>(); - - for (RangerTagForEval tag : requestTags) { - tags.put(tag.getType(), toMap(tag)); - tagNames.add(tag.getType()); - } - - ret.put(SCRIPT_FIELD_TAGS, tags); - ret.put(SCRIPT_FIELD_TAG_NAMES, tagNames); - - RangerTagForEval currentTag = RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext()); - - if (currentTag != null) { - ret.put(SCRIPT_FIELD_TAG, toMap(currentTag)); - } - } else { - ret.put(SCRIPT_FIELD_TAGS, Collections.emptyMap()); - ret.put(SCRIPT_FIELD_TAG_NAMES, Collections.emptySet()); - } + ret.put(SCRIPT_FIELD_TAGS, tags); + ret.put(SCRIPT_FIELD_TAG_NAMES, tagNames); + ret.put(SCRIPT_FIELD_TAG, tag); String strRet = JsonUtils.objectToJson(ret); @@ -589,6 +556,146 @@ public final class RangerRequestScriptEvaluator { return ret; } + public String ugNamesCsv() { + init(); + + return toCsv(userGroups); + } + + public String ugNamesCsvQ() { + init(); + + return toCsvQ(userGroups); + } + + public String urNamesCsv() { + init(); + + return toCsv(userRoles); + } + + public String urNamesCsvQ() { + init(); + + return toCsvQ(userRoles); + } + + public String tagNamesCsv() { + init(); + + return toCsv(tagNames); + } + + public String tagNamesCsvQ() { + init(); + + return toCsvQ(tagNames); + } + + public String userAttrNamesCsv() { + init(); + + return toCsv(getUserAttrNames()); + } + + public String userAttrNamesCsvQ() { + init(); + + return toCsvQ(getUserAttrNames()); + } + + public String ugAttrNamesCsv() { + init(); + + return toCsv(getUgAttrNames()); + } + + public String ugAttrNamesCsvQ() { + return toCsvQ(getUgAttrNames()); + } + + public String tagAttrNamesCsv() { + init(); + + return toCsv(getTagAttrNames()); + } + + public String tagAttrNamesCsvQ() { + init(); + + return toCsvQ(getTagAttrNames()); + } + + public String ugAttrCsv(String attrName) { + init(); + + return toCsv(getUgAttr(attrName)); + } + + public String ugAttrCsvQ(String attrName) { + init(); + + return toCsvQ(getUgAttr(attrName)); + } + + public String tagAttrCsv(String attrName) { + init(); + + return toCsv(getTagAttr(attrName)); + } + + public String tagAttrCsvQ(String attrName) { + init(); + + return toCsvQ(getTagAttr(attrName)); + } + + private void init() { + if (!initDone) { + RangerUserStore userStore = RangerAccessRequestUtil.getRequestUserStoreFromContext(accessRequest.getContext()); + Map<String, Map<String, String>> userAttrMapping = userStore != null ? userStore.getUserAttrMapping() : Collections.emptyMap(); + Map<String, Map<String, String>> groupAttrMapping = userStore != null ? userStore.getGroupAttrMapping() : Collections.emptyMap(); + + userGroups = getSorted(getUserGroups()); + userRoles = getSorted(getUserRoles()); + userAttrs = copyMap(userAttrMapping.get(accessRequest.getUser())); + groupAttrs = new HashMap<>(); + + userAttrs.put(SCRIPT_FIELD__NAME, getUser()); + + for (String groupName : userGroups) { + Map<String, String> attrs = groupAttrMapping.get(groupName); + + attrs = attrs != null ? new HashMap<>(attrs) : new HashMap<>(); + + attrs.put(SCRIPT_FIELD__NAME, groupName); + + groupAttrs.put(groupName, attrs); + } + + Set<RangerTagForEval> requestTags = RangerAccessRequestUtil.getRequestTagsFromContext(getRequestContext()); + + if (CollectionUtils.isNotEmpty(requestTags)) { + RangerTagForEval currentTag = RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext()); + + tags = new HashMap(); + tag = (currentTag != null) ? toMap(currentTag) : Collections.emptyMap(); + + for (RangerTagForEval tag : requestTags) { + tags.put(tag.getType(), toMap(tag)); + } + + tagNames = getSorted(tags.keySet()); + } else { + tags = Collections.emptyMap(); + tagNames = Collections.emptySet(); + tag = Collections.emptyMap(); + } + + initDone = true; + } + } + private Map<String, Object> getRequestContext() { return accessRequest.getContext(); } @@ -619,16 +726,125 @@ public final class RangerRequestScriptEvaluator { return ret; } - private Collection<String> getSorted(Collection<String> coll) { - if (coll != null && coll.size() > 1) { - List<String> lst = new ArrayList<>(coll); + private Collection<String> getSorted(Collection<String> values) { + final Collection<String> ret; + + if (values == null) { + ret = Collections.emptyList(); + } else if (values.size() > 1) { + List lst = new ArrayList<>(values); Collections.sort(lst); - coll = lst; + ret = lst; + } else { + ret = values; + } + + return ret; + } + + private Map<String, String> copyMap(Map<String, String> obj) { return obj == null ? new HashMap<>() : new HashMap<>(obj); } + + private List<Object> getUgAttr(String attrName) { + List<Object> ret = new ArrayList<>(); + + for (String groupName : userGroups) { + Map<String, String> attrs = groupAttrs.get(groupName); + Object val = attrs != null ? attrs.get(attrName) : null; + + if (val != null) { + ret.add(val); + } + } + + return ret; + } + + private List<Object> getTagAttr(String attrName) { + List<Object> ret = new ArrayList<>(); + + for (String tagName : tagNames) { + Map<String, Object> attrs = tags.get(tagName); + Object val = attrs != null ? attrs.get(attrName) : null; + + if (val != null) { + ret.add(val); + } + } + + return ret; + } + + private Collection<String> getUserAttrNames() { + Collection<String> ret = getSorted(userAttrs.keySet()); + + if (ret.contains(SCRIPT_FIELD__NAME)) { + ret.remove(SCRIPT_FIELD__NAME); + } + + return ret; + } + + private Collection<String> getUgAttrNames() { + Set<String> ret = new HashSet<>(); + + for (Map<String, String> attrs : groupAttrs.values()) { + ret.addAll(attrs.keySet()); + } + + ret.remove(SCRIPT_FIELD__NAME); + + return getSorted(ret); + } + + private Collection<String> getTagAttrNames() { + Set<String> ret = new HashSet<>(); + + for (Map<String, Object> attrs : tags.values()) { + ret.addAll(attrs.keySet()); + } + + ret.remove(SCRIPT_FIELD__TYPE); + ret.remove(SCRIPT_FIELD__MATCH_TYPE); + + return getSorted(ret); + } + + private String toCsv(Collection<? extends Object> values) { + StringBuilder sb = new StringBuilder(); + + for (Object value : values) { + if (value == null) { + continue; + } + + if (sb.length() > 0) { + sb.append(CHAR_COMMA); + } + + sb.append(value); + } + + return sb.toString(); + } + + private String toCsvQ(Collection<? extends Object> values) { + StringBuilder sb = new StringBuilder(); + + for (Object value : values) { + if (value == null) { + continue; + } + + if (sb.length() > 0) { + sb.append(CHAR_COMMA); + } + + sb.append(CHAR_QUOTE).append(value).append(CHAR_QUOTE); } - return coll; + return sb.toString(); } private static String getJsonVarNamesPattern() { diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java index ff638b2..2a0b027 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java @@ -55,6 +55,26 @@ public class RangerRequestScriptEvaluatorTest { RangerAccessRequest request = createRequest(Arrays.asList("PII", "PCI")); RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request); + Assert.assertEquals("test: ctx.ugNamesCsv()", "test-group1,test-group2", evaluator.evaluateScript(scriptEngine, "ctx.ugNamesCsv()")); + Assert.assertEquals("test: ctx.urNamesCsv()", "test-role1,test-role2", evaluator.evaluateScript(scriptEngine, "ctx.urNamesCsv()")); + Assert.assertEquals("test: ctx.tagNamesCsv()", "PCI,PII", evaluator.evaluateScript(scriptEngine, "ctx.tagNamesCsv()")); + Assert.assertEquals("test: ctx.userAttrNamesCsv()", "state", evaluator.evaluateScript(scriptEngine, "ctx.userAttrNamesCsv()")); + Assert.assertEquals("test: ctx.ugAttrNamesCsv()", "dept,site", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrNamesCsv()")); + Assert.assertEquals("test: ctx.tagAttrNamesCsv()", "attr1", evaluator.evaluateScript(scriptEngine, "ctx.tagAttrNamesCsv()")); + Assert.assertEquals("test: ctx.ugAttrCsv('dept')", "ENGG,PROD", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrCsv('dept')")); + Assert.assertEquals("test: ctx.ugAttrCsv('site')", "10,20", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrCsv('site')")); + Assert.assertEquals("test: ctx.tagAttrCsv('attr1')", "PCI_value,PII_value", evaluator.evaluateScript(scriptEngine, "ctx.tagAttrCsv('attr1')")); + + Assert.assertEquals("test: ctx.ugNamesCsvQ()", "'test-group1','test-group2'", evaluator.evaluateScript(scriptEngine, "ctx.ugNamesCsvQ()")); + Assert.assertEquals("test: ctx.urNamesCsvQ()", "'test-role1','test-role2'", evaluator.evaluateScript(scriptEngine, "ctx.urNamesCsvQ()")); + Assert.assertEquals("test: ctx.tagNamesCsvQ()", "'PCI','PII'", evaluator.evaluateScript(scriptEngine, "ctx.tagNamesCsvQ()")); + Assert.assertEquals("test: ctx.userAttrNamesCsvQ()", "'state'", evaluator.evaluateScript(scriptEngine, "ctx.userAttrNamesCsvQ()")); + Assert.assertEquals("test: ctx.ugAttrNamesCsvQ()", "'dept','site'", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrNamesCsvQ()")); + Assert.assertEquals("test: ctx.tagAttrNamesCsvQ()", "'attr1'", evaluator.evaluateScript(scriptEngine, "ctx.tagAttrNamesCsvQ()")); + Assert.assertEquals("test: ctx.ugAttrCsvQ('dept')", "'ENGG','PROD'", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrCsvQ('dept')")); + Assert.assertEquals("test: ctx.ugAttrCsvQ('site')", "'10','20'", evaluator.evaluateScript(scriptEngine, "ctx.ugAttrCsvQ('site')")); + Assert.assertEquals("test: ctx.tagAttrCsvQ('attr1')", "'PCI_value','PII_value'", evaluator.evaluateScript(scriptEngine, "ctx.tagAttrCsvQ('attr1')")); + Assert.assertTrue("test: USER._name is 'test-user'", (Boolean) evaluator.evaluateScript(scriptEngine, "USER._name == 'test-user'")); Assert.assertTrue("test: USER['state'] is 'CA'", (Boolean) evaluator.evaluateScript(scriptEngine, "USER['state'] == 'CA'")); Assert.assertTrue("test: USER.state is 'CA'", (Boolean) evaluator.evaluateScript(scriptEngine, "USER.state == 'CA'"));