how to find multiple simular relstionships

37 views
Skip to first unread message

koen

unread,
Jan 3, 2018, 5:08:24 AM1/3/18
to Neo4j
Hi, a cypher question. How can you check if 2 (or more) different nodes in a graph have relationships to multiple other (shared) nodes in the graph.

Attached is  a graph (the result of below cypher query) that i created based on the sample provided in the NIST / INCITS NGAC 499 / 525 (Next Generation Access Control) specification (graph.png). I also included the diagram of the complete sample graph.

BLUE        --- : u1 is a :User node
GREEN    --- a11, a21, l11, l12 are :Object nodes
YELLOW --- branch-constrants, position-constraints are :PolicyClass nodes
GREY      --- all other nodes are attribute nodes

In the sample provided "u1" has a relationship with the 2 policy classes (branch and position constraints) and it has an ASSOCIATED_TO relation ship to both "products1" and "accounts" Attribute Nodes
Looking from the :Object side only "a11"  has a relationship to both the 2 PolicyClasses and to the "products1" and "accounts" attribute nodes --   simular to what u1 has "u1"

All other Objects (a21, l12 and l11) do not have these 4 relation ships but only some of these (meaning u1 has no acces to these objects)

How can i further filter this out in cypher ?  So i would like to further refine the result so that only "u1" and "a11"  (meaning user u1 has access to object a11) are part of the end result set.

  it seems straightforward but it looks like i am running on some constraints where some nodes are visited only once and no results are returned (for example going from "a11" you have to visit "accounts1" node multiple times)

This is the cypher code used to create the graph as speficied in attached diagram.

MATCH p1 = (u:User)-[:ASSIGNED_TO*]->(pc:PolicyClass)
WHERE u.name = "u1"
WITH *
MATCH p2 = (u)-[:ASSIGNED_TO*]->(a:Attribute)-[:ASSOCIATED_TO]->(a1:Attribute)
WITH *
MATCH p3 = (o:Object)-[:ASSIGNED_TO*]->(pc:PolicyClass)
WITH *
MATCH p4 = (o)-[:ASSIGNED_TO*]->(a1:Attribute)
WITH *
RETURN p1,p2,p3,p4

Any help is welcome !

Thanks regards Koen
graph.png
ngac sample incits 499 525.png

koen

unread,
Jan 4, 2018, 12:39:24 AM1/4/18
to Neo4j
Hi, below a reference to the document i referred to : "INCITS 525: Information technology - Next Generation Access Control - Implementation Requirements, Protocols and API Definitions (NGAC-IRPADS)"    -  https://standards.incits.org/apps/group_public/document.php?document_id=93250

This contains the sample ABAC (Attribute Based Access Control) setup that i turned into a neo4j graph.and now try to use as basis for querying ABAC  access decisions..

IMHO this is really interesting stuff to see how a graph database can be used to store and validate  Access Policies   for ABAC implementation as opposite to the XACML based impementations for which a few commercial products exist

I also created a sample graph at :    http://console.neo4j.org/?id=q9frmo

Which should reflect the setup from the incits 525 document

Still trying to write the query to detect presence of multiple paths from different nodes to a set of shared nodes in the middle.. any help is appreciated..

reg koen


Op woensdag 3 januari 2018 11:08:24 UTC+1 schreef koen:

Craig Taverner

unread,
Jan 4, 2018, 8:23:15 AM1/4/18
to Neo4j
Hi Koen,

As I see it one problem with your query is that it is performing multiple matches that will build on each other, and that is not what you are asking for. The first match will return two rows, one for each of the two paths that match that pattern. Then for each of these rows Cypher will run the second match, leading to four rows (with duplications), and so on. There is nothing in the query to say that you want a correlation between the first match and any other match.

One simple change that might be closer to what you want would be to remove all the intermediate WITH *, and MATCH statements, and make a single, comma-separated MATCH, like this:

MATCH p = (u:User)-[:ASSIGNED_TO*]->(pc:PolicyClass),
  (u)-[:ASSIGNED_TO*]->(:Attribute)-[:ASSOCIATED_TO]->(a1:Attribute),
  (o:Object)-[:ASSIGNED_TO*]->(pc),
  (o)-[:ASSIGNED_TO*]->(a1),
RETURN p

This single MATCH clause now describes a single complete pattern, which should be matched twice only. Try this and perhaps simplified versions of it, and see if that works.

Regards, Craig

Koen Kleingeld

unread,
Jan 4, 2018, 8:47:21 AM1/4/18
to ne...@googlegroups.com
Hi Craig, thanks, yes i know i could have combined my query into one but this was just to split things out.  Its only purpose was to create the initial subset of the bigger graph that would be input for the actual query.. I tried your query but it does not give any results back  but with some help from stackoverflow i learned that the ALL clause did the trick..

A working version of the cypher query  ( i.e. a simplified version for only looking at the attribute relationship  and not yet at the policyclass relation) is :

MATCH (u:User)-[:ASSIGNED_TO]->(ua:Attribute)-[:ASSOCIATED_TO]->(oa:Attribute)
  WHERE u.name = "u1"
WITH u, COLLECT(oa) AS Attributes
MATCH (o:Object)
  WHERE ALL( x IN Attributes WHERE (o)-[*]->(x) )
RETURN u, Collect(o) AS Objects

Thanks for you reply !

regards koen




--
You received this message because you are subscribed to a topic in the Google Groups "Neo4j" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/neo4j/94ULtuII4g4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to neo4j+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Groeten / Best Regards,

Koen

Kamal Murthy

unread,
Jan 5, 2018, 12:10:26 AM1/5/18
to Neo4j
Hi Koen,

Try these scripts:
MATCH (o:Object)-[]->(c)-[]-(d)-[]-(e)-[]-(f)
WHERE o.name = "a11" and f.name <> "a21" and f.name <> "l11" and f.name <> "l12" and f.name <> "u2"
RETURN o, c, d, e, f;


MATCH (o:Object)-[]->(c)-[]-(d)-[]-(e)-[]-(f)
WHERE o.name = "a11" or f.name = "u1"
RETURN o, c, d, e, f;

Hope this works for you.

-Kamal

koen

unread,
Jan 5, 2018, 2:09:58 AM1/5/18
to Neo4j
Hi Kamal, thanks. This also gives a nice result but i was also looking for a more generic approach answering for example the question: what are all objects that a specific user has access to.. or which users have access to what object.. I think the combination of a COLLECTc and ALL clause did the job there. I am now trying to combine 2 lookups since in the NGAG / ABAC case there must noy only be an Attribute match yo derive authorizations but also a PolicyClass matxh shared by the user and objects

This is really a nice appliance of graph technology within the IAM / ABAC domain   (see the mentiones ansi-incits docs  499 and 525)

Thanks for all reactions

regards koen

Op woensdag 3 januari 2018 11:08:24 UTC+1 schreef koen:
Hi, a cypher question. How can you check if 2 (or more) different nodes in a graph have relationships to multiple other (shared) nodes in the graph.
Reply all
Reply to author
Forward
0 new messages