Modeling an Access Control Layer graph
I’m trying to model an ACL graph in dgraph, but I’m struggling to find the the right combination of schema and queries to make it work.
Entities
Agent
-
Organization
(effectively a super-Agent
) -
Group
(owned by exactly 1Organization
) - Owned objects, let’s call them
Widget
s
Relationships
-
Organizations
andAgents
can both own 0+Widgets
. -
Agent
s can be in 0+Group
s - The Groups owned by an organization can have various access levels,
READ
,WRITE
,ADMIN
, that grants that level of access to theWidgets
owned by thatOrganization
of theGroup
.- The access levels are hierarchical:
ADMIN
impliesWRITE
, andWRITE
impliesREAD
- The access levels are hierarchical:
-
Organizations
(since they’re super-Agent
s) can also be in 0+Group
s. In other words,Organizations
can be hierarchical. I think the simplest way to explain this is to imagine how you’d structure something like a franchise that has various levels of organization:Org-Store
,Org-Region
,Org-Country
,Org-Global
whereOrg-Store
is part of the appropriateOrg-Region
, which is part of the appropriateOrg-Country
, which is part ofOrg-Global
. Realistically this hiearchy of orgs will be shallow (10 or less), but may be deeper for more rare cases.
Query
- Find the paths from
Agent
toWidget
where one of the following is true- either
Agent
directly owns theWidget
-
Agent
is a member of aGroup
(remember, owned by anOrganization
) that owns theWidget
-
Agent
is a member of aGroup
, that’s a member of aGroup
, …, that owns theWidget
Currently, I’d prefer to return each hop of the path and the access levels of each hop in the path. It’s possible that we could simply live with answering a “path exists?” query.. This path traversal would need to filtered by 1+ attributes of the group membership, like the level of access that theGroup
has in theOrganization
.
- either
Example (note that this structure doesn’t actually support all of the relationships defined above)
_:org0 <has> _:org0_group0
_:org0 <owns> _:org0_widget1
_:org0 <xid> "org0"
_:org0_widget1 <xid> "widget:org0/widget1"
_:org1 <has> _:org1_group1
_:org1 <owns> _:org1_widget2
_:org1 <xid> "org1"
_:org1_widget2 <xid> "widget:org1/widget2"
_:agent0 <owns> _:agent0_widget0
_:agent0 <admin> _:org0_group0
_:agent0 <xid> "agent0"
_:org0 <reader> _:org1_group1
The question I’d like to answer here is, given “agent0”, find all the widgets that it can READ
. Should yield:
-
_:agent0_widget0
- because it’s the owner -
_:org0_widget1
- because it’s anADMIN
of a group (_:org0_group0
) in_:org0
, and_:org0
owns the widget -
_:org1_widget2
- because it’s anADMIN
of_:org0_group0
in_:org0
, which isREAD
er member of the group (_:org1_group1
) in_:org1
, and_:org1
owns the widget
Modeling issues, so far
- Based on the predicate-shard storage model for dgraph, I’d want to expand any
<admin>
predicates into the implied<reader>
and<writer>
predicates. I’m perfectly happy doing that expansion on our side, so this one isn’t a blocker, just simply a comment - Dgraph doesn’t allow me to represent vertex/edge combos where
<S> <P>
are the same. With the data model above, I’d need_:agent0
to potentiall have multiple<owns>
relationships for all the widgets it owns, and similarly would need to express multiple<admin>
/<reader>
relationships for a given agent/organization. If dgraph allowed duplicate<S> <P>
relationships, I think I could effectively model my ACL with a faceted<agent> <member>
relationship. The facets would be the authorization level and the potentially things like the uid of the org that owns the group, along with any other metadata we’d need to associate with the authorization for future filtering. - I’ve also tried modeling the group membership where the membership itself is a unique blank node with edges that points to the agent that’s authorized and and the org that owns it. The blank node would also have an edge that indicates the access level of the authorization. This model would have a lot of back and forth hops between predicate shards to effectively recurse and traverse that graph while trying to answer the question of "what widgets can I read/write/administer"
Question
Does anyone have an idea on a schema and data-model that would let us quickly and efficiently query this data?
At the end of the day, I think I need to find a model that can represent the chained authorizations and answer the question of, “given the staring point, agent0, I need the 0+ organizations that agent0 can either READ/WRITE/ADMIN”, and then I could feed those uids into a subsequent query to finds widgets owned by that set of uids.