ory / keto

Open Source (Go) implementation of "Zanzibar: Google's Consistent, Global Authorization System". Ships gRPC, REST APIs, newSQL, and an easy and granular permission language. Supports ACL, RBAC, and other access models.
https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=keto
Apache License 2.0
4.78k stars 347 forks source link

Allow defining ABAC relation tuples #319

Open zepatrik opened 3 years ago

zepatrik commented 3 years ago

Is your feature request related to a problem? Please describe.

ABAC rules can not be added simply with relation tuples as the attributes have to be checked.

Describe the solution you'd like

In general, the database will not be the only source of relation tuples. For subject set rewrites we will have to dynamically generate relation tuples that are used for evaluation of requests.

ABAC rules can be added dynamically the same way depending on the actual attributes of the request context.

An example ABAC rule: allow write access to repository form sub net 192.168.2.0/24

This would translate to the following relation tuples (omitting namespaces):

repository#write@<192.168.2.0/24#accessing-from>    <- fixed tuple always present
192.168.2.0/24#accessing-from@user                  <- dynamic tuple added based on attributes of the requests

These dynamic tuples only have to be computed initially on request. It would be best to have the client define them so that Keto does not have to support parsing 1000 different data formats and queries on them.

In essence, the client would translate any attributes it likes into relation tuples that then are used by keto for evaluation. In general, the client can add relation tuples dynamically only for single requests.

The check/expand API would have to get an additional parameter for dynamic relation tuples.

Describe alternatives you've considered

Keto should not support a complex language with an even more complex engine like OPA. Any other idea for implementing ABAC should be collected in this issue.

robinbraemer commented 3 years ago

So, having Open Policy Agent already there to be able to do all the complex attribute based authorization control...

I think the Open Policy Agent +Keto ACL extention pair (OPA+Keto) is just so endlessly powerful 🎉 that pretty much anything, including ABAC, RBAC, etc. can already be configured by users in rego. (...having #318 is just too exciting 😍)

The only thing may be useful Keto could provide in addition to ACL is an API for RBAC (literally just an API) using ACL as backend as planned, but even such opinionated RBAC API might be too constrained and not suffice all users needs as can be self-built with the OPA+Keto combination.

Maybe just provide documentation of how to use OPA+Keto to build highly customized RBAC, ABAC, ... systems for those ORY users that need it? @aeneasr @zepatrik

aeneasr commented 3 years ago

The problem with OPA is that it does not have any persistency, so one problem will definitely be the management of resource definitions in OPA, especially if we're looking at high scale. But I generally agree that we should not try to come up with too much fancy stuff here as it will make everything more complicated and bespoke.

zepatrik commented 3 years ago

This could be achieved also by allowing a check request to pass a list of subjects. A simple case is where * is interpreted as a special subject that anyone can impersonate. Tuples can then be added accordingly to reflect the permissions of anonymous users. A request for user foo would then be transformed by the client to the check request: object#access@(foo|*)?.

This can then be used to add all the states a user can currently impersonate (e.g. by checking for some attributes) to the actual request:

let subject = [user.userId]

if (user.isAtWorkLocation()) {
    subject = [...subject, "special at work user id"]
}

return keto.check({ object, relation, subject })

with the Keto relation tuples in the database:

disclosed_object#access@special_at_work_user
not_disclosed_object#access@user_foo

This could then be leveraged using all the set operators theoretically available in subject set rewrites to build even boolean operations on these subjects. This would probably work way better in a setting where you have many attributes that a user can have, while the first idea would be less complex to set up with view attributes. This would not solve integration with other services (like OPA), I guess.

robinbraemer commented 3 years ago

A am not fully against ABAC support, but yet I think we might are going in an unsuitable direction with builtin ABAC support for ACL or likewise ideas. Zanzibar is not even designed to do this at its lowest level.

I don't quite see the vision of Keto's builtin ABAC system, because of the question:

We know that building a ABAC-supporting system is hard to get right and generic enough that users can highly adjust it to their unique use cases where whatever system they are building, such ABAC provider can output an arbitrary decision given arbitrary request input (not just "He is allowed to do this"). That's why OPA exists.

If I did not miss anything discussed and from my perspective, I see the biggest potential for Keto lays in ACL for the following reasons:

As much as I would like to think that, there can't be done much more improvement and I don't see a successful ABAC implementation within Keto. (Remember: Google's Zanzibar is a base-system - and so should Keto, I think).

aeneasr commented 3 years ago

Hm, I kind of agree with you @robinbraemer . Thinking about ABAC now is a good step forward, but we have yet to specify the user set rewrite configuration layout, figure out the scalability architecture, and more. Bending concepts of the ACL to solve this is maybe not the best path forward for the moment. Maybe we should keep it in the back of our heads and include it when planning new APIs, but not actually implement or talk about it yet.

Also, I would not fixate too hard on OPA. I love the project and the people behind it, but so far the project has been quite disappointing when actually using it. Getting the policies right is hard (learn a new programming language that is quite different from others due to its query structure), it is difficult to make changes persistent at scale (because it is not a concern for OPA), latency has been an issue from day one (and not yet solved unless you have maintainer level knowledge of rego parsing internals), and resource consumption is exorbitant for certain types of operations and datasets because everything is loaded in memory.

zepatrik commented 3 years ago

I am :100: % with you there, I was afraid already that my comments are not clear enough. Basically, both of the ideas presented above try to find an idea of how to integrate Keto with any other service. This would allow ABAC but also many other things. The only thing that would change in Keto would be one of:

  1. accept temporary ACL rules that are just considered for a single request
  2. allow to specify multiple subjects for a request, Keto will return "allowed" if any of the subjects is allowed

Keto would still not have any ABAC related features, it would just be very easy to add another service that allows that.

kirankumargmrur commented 2 years ago

I guess casbin can help here

zepatrik commented 1 year ago

Auth0/openFGA was so kind to implemented the here mentioned approach of contextual tuples for us, so we can play with it already https://docs.fga.dev/modeling/basics/contextual-time-based-authorization The permission function in OPL were specifically designed to take an extensible context to allow adding request attributes later on. Ideally we want to support two cases here:

  1. Attaching attributes to a request. Unlike considered earlier, it probably makes more sense to have a simple string->string or string->bool mapping. A permissions function could then look similar to

    class Document implements Namespace {
    related: {
    owners: User[]
    collaborators: User[]
    }
    
    permits = {
    view: (ctx: Context) => this.related.owners.includes(ctx.subject) || (this.related.collaborators.includes(ctx.subject) && ctx.attributes["is_working_hours"])
    }
    }
  2. Attaching attributes to an object. This would be another table storing the (object, key)->value mapping. The attributes are then exposed in OPL by adding an attributes key to the namespace class and accessing the attributes there to compare them to constants or (more useful) the attributes in the context. IMO the more useful use-case will be to filter/sort results by these attributes.

This approach will be easier to understand for devs, while not being too complex and providing about the same expressiveness as contextual tuples.

github-actions[bot] commented 10 months ago

Hello contributors!

I am marking this issue as stale as it has not received any engagement from the community or maintainers for a year. That does not imply that the issue has no merit! If you feel strongly about this issue

Throughout its lifetime, Ory has received over 10.000 issues and PRs. To sustain that growth, we need to prioritize and focus on issues that are important to the community. A good indication of importance, and thus priority, is activity on a topic.

Unfortunately, burnout has become a topic of concern amongst open-source projects.

It can lead to severe personal and health issues as well as opening catastrophic attack vectors.

The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone.

If this issue was marked as stale erroneously you can exempt it by adding the backlog label, assigning someone, or setting a milestone for it.

Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you!

Thank you 🙏✌️

cmmoran commented 7 months ago

<... snip>

  1. Attaching attributes to an object. This would be another table storing the (object, key)->value mapping. The attributes are then exposed in OPL by adding an attributes key to the namespace class and accessing the attributes there to compare them to constants or (more useful) the attributes in the context. IMO the more useful use-case will be to filter/sort results by these attributes.

With regard to the model surrounding attached attributes, I assume attributes would be governed by the same consistency model as the rest of the tuple model. Would that be a correct assumption or am I missing something obvious?

I ask because there may be an edge case surrounding former access and current access when taking into account attributes.

For example: Bob once had access to Alice's document readme.md. Now, Alice has limited access to readme.md using the attribute is_working_hours. From my understanding of Zanzibar, this would mean that Bob would retain access to readme.md for the versions of that object for which he was Allowed but all versions from the commit_time of the attribute is_working_hours, Bob would only have access to readme.md IFF his access attempt fulfilled the is_working_hours attribute.

I think, in addition to those two cases mentioned by @zepatrik, the implementation would need a third case:

  1. Creating, Modifying or Removing attributes attached to an object would constitute a snapshot action. Resolving access would need to take into account the tuple state and the attribute(s) state for the zookie. Of course, in absence of a zookie the current state would prevail.
grapemix commented 4 months ago

FYI, I just saw another Zanzibar inspired (fully opensource?) projects which offer RBAC, ABAC and ReBAC model. I don't want to comment which one is better. (I haven't had time to evaluate it). I do hope both projects can help and inspire each other.

Ref: https://www.permit.io/abac https://www.permit.io/rebac https://www.permit.io/blog/announcing-abac https://docs.permit.io/category/build-policies

PS: I don't have any relationship w/ the permit project/com/team. I just monitor this ticket for sooo long..... Let me know if anyone want to remove the links. ty.