I'm trying to get a simple expansion of some relations using Rego's graph.reachable. For some reason this isn't printing leaf nodes and I've not yet figured out why.
inherits_from[role_id] contains other if {
some role_id, role_details in data.relations.roles
some other in role_details.grants
}
effective_subjects = graph.reachable(inherits_from, {"role:admin"})
For data:
{
"relations": {
"roles": {
"role:admin": {
"grants": ["permission:edit", "role:viewer"]
},
"role:viewer": {
"organizations": "organization:acme",
"grants": ["permission:view", "role:other"]
}
}
}
}
I get the result:
{
"effective_subjects": [
"role:admin",
"role:viewer"
]
}
This is missing out the "permission:edit"
and "permission:view"
.
With a bit of experimentation, I can git it to show permissions if I begin making relations and rules for the permissions as well. But always graph.reachable
is failing to produce the leaf nodes.
What am I doing wrong?
Graphs passed to graph.reachable need to be a list of all nodes and the other nodes they have edges to. This list of edges might be an empty list.
I would set it up more like this:
package foo
# nodes is a set of unique roles and grant names
nodes contains node if {
some role, role_data in data.relations.roles
grant_names := {n | some n in role_data.grants}
# a node is both the role itself and all the grant names
some node in (grant_names | {role})
}
inherits_from_graph[node] := edges if {
some node in nodes
edges := {e | some e in data.relations.roles[node].grants}
}
effective_permissions := graph.reachable(inherits_from_graph, {"role:admin"})
I think the desired output is:
"effective_permissions": [
"permission:edit",
"permission:view",
"role:admin",
"role:other",
"role:viewer"
]
Since, "role:other"
is inherited from viewer?
https://play.openpolicyagent.org/p/dmO2UWGA0n
However, I think if you have a lot of work to re-organize your data into a suitable graph structure for OPA, it'd be best to have that work done when building the data bundle rather than in each OPA instance.