Repository: incubator-ranger Updated Branches: refs/heads/tag-policy 2474fed11 -> 5a022141c
RANGER-513 Policy validation: resource hierarchies check does not work with single-node hierarchies e.g. for HDFS Signed-off-by: Madhan Neethiraj <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/f0a8931a Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/f0a8931a Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/f0a8931a Branch: refs/heads/tag-policy Commit: f0a8931a8c1847470e486ffdf59c70814270ce9d Parents: fb6e94f Author: Alok Lal <[email protected]> Authored: Thu May 28 15:34:15 2015 -0700 Committer: Madhan Neethiraj <[email protected]> Committed: Thu May 28 20:47:54 2015 -0700 ---------------------------------------------------------------------- .../validation/RangerServiceDefHelper.java | 30 +++++++++++--- .../validation/TestRangerServiceDefHelper.java | 42 +++++++++++++++++++- 2 files changed, 66 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f0a8931a/agents-common/src/main/java/org/apache/ranger/plugin/model/validation/RangerServiceDefHelper.java ---------------------------------------------------------------------- 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 91ff16a..d3bcc1a 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,6 +36,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.ranger.plugin.model.RangerServiceDef; import org.apache.ranger.plugin.model.RangerServiceDef.RangerResourceDef; +import com.google.common.collect.Lists; + public class RangerServiceDefHelper { private static final Log LOG = LogFactory.getLog(RangerServiceDefHelper.class); @@ -238,10 +240,20 @@ public class RangerServiceDefHelper { Set<String> sources = graph.getSources(); Set<String> sinks = graph.getSinks(); for (String source : sources) { - for (String sink : sinks) { - List<String> path = graph.getAPath(source, sink, new HashSet<String>()); - if (!path.isEmpty()) { - hierarchies.add(path); + /* + * A disconnected node, i.e. one that does not have any arc coming into or out of it is a hierarchy in itself! + * A source by definition does not have any arcs coming into it. So if it also doesn't have any neighbors then we know + * it is a disconnected node. + */ + if (!graph.hasNeighbors(source)) { + List<String> path = Lists.newArrayList(source); + hierarchies.add(path); + } else { + for (String sink : sinks) { + List<String> path = graph.getAPath(source, sink, new HashSet<String>()); + if (!path.isEmpty()) { + hierarchies.add(path); + } } } } @@ -328,6 +340,14 @@ public class RangerServiceDefHelper { } /** + * Returns true if the node "from" has any neighbor. + * @param from + * @return + */ + boolean hasNeighbors(String from) { + return _nodes.containsKey(from) && _nodes.get(from).size() > 0; + } + /** * Return the set of nodes with in degree of 0, i.e. those that are not in any other nodes' list of neighbors * * @return @@ -339,7 +359,7 @@ public class RangerServiceDefHelper { sources.removeAll(nbrs); // A source in a DAG can't be a neighbor of any other node } if (LOG.isDebugEnabled()) { - LOG.debug("Returning sinks: " + sources); + LOG.debug("Returning sources: " + sources); } return sources; } http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/f0a8931a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java ---------------------------------------------------------------------- diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java index 2703384..883b808 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/model/validation/TestRangerServiceDefHelper.java @@ -149,10 +149,50 @@ public class TestRangerServiceDefHelper { assertTrue(expectedHierarchies.contains(resourceNames)); expectedHierarchies.remove(resourceNames); } - assertTrue(expectedHierarchies.isEmpty()); // make sure we saw got back hierarchies + assertTrue("Missing hierarchies: " + expectedHierarchies.toString(), expectedHierarchies.isEmpty()); // make sure we got back all hierarchies } @Test + public final void test_isResourceGraphValid_forest_singleNodeTrees() { + /* + * Create a service-def which is a forest with a few single node trees + * + * Database + * + * Server + * + * Namespace -> package + * | + * v + * function + * + * Check that helper corrects reports back all of the hierarchies: levels in it and their order. + */ + RangerResourceDef database = createResourceDef("database", ""); + RangerResourceDef server = createResourceDef("server", ""); + RangerResourceDef namespace = createResourceDef("namespace", ""); + RangerResourceDef function = createResourceDef("function", "namespace"); + RangerResourceDef Package = createResourceDef("package", "namespace"); + List<RangerResourceDef> resourceDefs = Lists.newArrayList(database, server, namespace, function, Package); + when(_serviceDef.getResources()).thenReturn(resourceDefs); + _helper = new RangerServiceDefHelper(_serviceDef); + assertTrue(_helper.isResourceGraphValid()); + Set<List<RangerResourceDef>> hierarchies = _helper.getResourceHierarchies(); + + Set<List<String>> expectedHierarchies = new HashSet<List<String>>(); + expectedHierarchies.add(Lists.newArrayList("database")); + expectedHierarchies.add(Lists.newArrayList("server")); + expectedHierarchies.add(Lists.newArrayList("namespace", "package")); + expectedHierarchies.add(Lists.newArrayList("namespace", "function")); + + for (List<RangerResourceDef> aHierarchy : hierarchies) { + List<String> resourceNames = _helper.getAllResourceNames(aHierarchy); + assertTrue(expectedHierarchies.contains(resourceNames)); + expectedHierarchies.remove(resourceNames); + } + assertTrue("Missing hierarchies: " + expectedHierarchies.toString(), expectedHierarchies.isEmpty()); // make sure we got back all hierarchies + } + @Test public final void test_cacheBehavior() { // wipe the cache clean RangerServiceDefHelper._Cache.clear();
