Modeling an Access Control Layer graph

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.


  • Agent
  • Organization (effectively a super-Agent)
  • Group (owned by exactly 1 Organization)
  • Owned objects, let’s call them Widgets


  • Organizations and Agents can both own 0+ Widgets.
  • Agents can be in 0+ Groups
  • The Groups owned by an organization can have various access levels, READ, WRITE, ADMIN, that grants that level of access to the Widgets owned by that Organization of the Group.
    • The access levels are hierarchical: ADMIN implies WRITE, and WRITE implies READ
  • Organizations (since they’re super-Agents) can also be in 0+ Groups. 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 where Org-Store is part of the appropriate Org-Region, which is part of the appropriate Org-Country, which is part of Org-Global. Realistically this hiearchy of orgs will be shallow (10 or less), but may be deeper for more rare cases.


  • Find the paths from Agent to Widget where one of the following is true
    • either Agent directly owns the Widget
    • Agent is a member of a Group (remember, owned by an Organization) that owns the Widget
    • Agent is a member of a Group, that’s a member of a Group, …, that owns the Widget
      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 the Group has in the Organization.

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 an ADMIN of a group (_:org0_group0) in _:org0, and _:org0 owns the widget
  • _:org1_widget2 - because it’s an ADMIN of _:org0_group0 in _:org0, which is READer 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"


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.

Hi Adam,

We are add support for ACL Search · ACL · GitHub
Soon you’ll be able to use it. See also Our 2019 Roadmap Product Roadmap 2019 · Issue #2894 · dgraph-io/dgraph · GitHub


Thanks @MichelDiz. I’ve seen the roadmap, but as far as I understand it, the ACL features are for controlling who can access dgraph, rather than modeling our own domain’s entities ACL logic as a unified graph within dgraph. Have I misunderstood the upcoming ACL feature’s intent?

Well the ACL will be to rule who can use* Dgraph. All other access will be considered “anonymous” usage. It’s not about who can access or control the Dgraph. But who can read, write or modify something in Dgraph.

You will be able to create groups and virtually all features that you mentioned above.

I looked at the current state of the enterprise-focused ACL work, but it still doesn’t seem like what I’m currently asking about. Mapping our domain’s access control rules to the perimeter access control of seems very awkward. In the current form, as far as I see in the repo, all of our user/group management would have to be done via dgraph acl ... commands. Also, having the domain’s authorizations model as part of the graph of entities in our system would allow us to do a lot of interesting ad-hoc analysis.

One day, I’d want to have both a network-level and auth-level protection on who can access our dgraph instances. To get there, though, I need to model our domain’s ACL in dgraph.

There can be multiple <S> <P> * where each outgoing edge goes to a different node. Think of something like _:me <friend> _:him and _:me <friend> _:her. The _:me node has multiple outgoing <friend> edges.

Your structure looks fine to me. I don’t quite understand the distinction between agents and orgs (both can own widgets and comprise groups). It seems like they’re logically the same thing, but orgs can be further sub-organized.