Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursion or transitive closure use case: supergroups #947

Open
eamsden opened this issue Sep 14, 2018 · 3 comments

Comments

@eamsden
Copy link

@eamsden eamsden commented Sep 14, 2018

I have some groups, some of which specify another group as their supergroup:

# auth/groups/data.json
[ { "gid": 0
   , "name": "$corp admin"
   , "members": ["sam", "fred", "lisa"]
  }
, { "gid": 1
   , "name": "client 1 admin"
   , "members": "lucy, jim"
   , "supergroup": 0
   }
, { "gid": 2
  , "name": "client 1 users"
  , "members": "steve, ralph"
  , "supergroup": 1
  }
]

I want to write a policy such that if a group has read permission on an entity, then their supergroup has read, write, and delete permission on that entity.

package auth.policies
import data.auth.groups

superPermissions = {"read","write","delete"}

groupHasPermission[[group,entity,permission]] {
  group = groups[_]
  subgroup = groups[_]
  subgroup.supergroup = group.gid
  groupHasPermission[[subgroup,entity,"read"]] # Error: recursive!
  permission = superPermissions[_]
}

This would be very difficult to encode clearly without recursion. Perhaps transitive closure would work, though I haven't thought how that might work yet.

@srenatus

This comment has been minimized.

Copy link
Contributor

@srenatus srenatus commented Oct 9, 2018

💭 I wonder if in some use cases, restricting the level of nesting could make sense. If so, we should be able to create simple rules enumerating the separate levels of nesting -- see this simplified example:

  • data.json:
{
  "$corp admin": {
    "members": ["sam", "fred", "lisa"]
  },
  "client 1 admin": {
    "members": ["lucy", "jim"],
    "supergroup":  "$corp admin"
  },
  "client 1 users": {
    "members": ["steve", "ralph"],
    "supergroup":  "client 1 admin"
  }
}
  • pol.rego:
package auth.policies
import data.auth.groups

member[[group_id, user]] {
  groups[group_id].members[_] = user # direct member
} {
  groups[groups[group_id].supergroup].members[_] = user # one level
} {
  groups[groups[groups[group_id].supergroup].supergroup].members[_] = user # two levels
}
  • opa run auth.groups:data.json pol.rego:
OPA 0.9.3-dev (commit 73d46a85-dirty, built at 2018-10-04T07:02:04Z)
Run 'help' to see a list of commands.
> data.auth.policies.member[["client 1 users", u]]
+---------+------------------------------------+
|    u    | data.auth.policies.member[["client |
|         |           1 users", u]]            |
+---------+------------------------------------+
| "steve" | ["client 1 users","steve"]         |
| "ralph" | ["client 1 users","ralph"]         |
| "lucy"  | ["client 1 users","lucy"]          |
| "jim"   | ["client 1 users","jim"]           |
| "sam"   | ["client 1 users","sam"]           |
| "fred"  | ["client 1 users","fred"]          |
| "lisa"  | ["client 1 users","lisa"]          |
+---------+------------------------------------+

I'm not arguing that there's no use for recursion, just offering the simple way out for some use cases, maybe 😄

@tsandall tsandall added this to To do in Open Policy Agent via automation Jun 20, 2019
@tsandall

This comment has been minimized.

Copy link
Member

@tsandall tsandall commented Jun 26, 2019

Google recently published a related paper on one of their authorization systems: https://ai.google/research/pubs/pub48190.

@charlieegan3

This comment has been minimized.

Copy link
Contributor

@charlieegan3 charlieegan3 commented Oct 31, 2019

Much of this is a little beyond me but I'm interested in this use case - partly for fun, but it's also one of the Datalog value adds over (most?) SQL-like query languages (as I understand it).

While Google can build a special indexing system (Leopard?) for set computations, I'm interested to know what the options (with some work) might be to get this functionality in OPA - even at the risk of poor performance.

On the 'What is Rego' page here Rego is introduced as being inspired by Datalog. Is there anywhere I can read about this and other differences with Datalog and the design decisions behind them?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
4 participants
You can’t perform that action at this time.