open-policy-agentrego

Rego graph.reachable not printing leaf nodes


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?


Solution

  • 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.