Hey everybody :wave: I think I have a more of gene...
# help
o
Hey everybody 👋 I think I have a more of general/architectural question rather than technical, policy, related questions. Tried to read through this channel so hopefully it is not a duplicate. For the sake of keeping it short, let’s say I have 2 REST APIs accessible to clients (web or mobile apps) • _identity-api_: provides tokens, password resets, etc general user management. • _business-api_: provides business functionality, CRUD actions on resources, etc. All endpoints are authenticated by JWT from identity-api. My question is that how would I solve authorisation in cases where resources in business-api (or principals in identity-api) do not exist while Cerbos policies are made? For example: Lets say that user-1 creates a resource Foo using API endpoint in business-api
POST /v1/foos
. Now user-1 should be able to to other actions as well with this resource:
GET/DELETE/PUT /v1/foos/{fooResourceId}
. Using Cerbos this could be easily solved with a derived role, if I keep track of the createdBy attribute and pass it as resource attribute. But what happens when user-1 wants to give
GET
and
PUT
access user-2? Or, if Foo has a child resources Bar at
/v1/foos/{fooResourceId}/bars/{barResourceId}
and user-2 should only be allowed to edit Bar resource but not Foo? You could also think of it this way, that user-1 creates a profile (like in Facebook) that is private, but later decides that user-2 and user-3 should be able to see it. When creating the profile user-1 and user-2 might not even exist yet. One option I see is using the Cerbos Admin API and
POST /admin/policy
, but how would it handle if there are hundreds of users and resources. Second option, I thought of would be to define policy role based (e.g USER-1-PROFILE-READ) and just add the user to the role, but at the time of writing the policy, I would’t know the users that will exist in the future. Third option would be to keep track of the permissions and access in our systems, but that would probably just end up as creating own authorisation service, which I hope to avoid with Cerbos. I might be over-engineering everything and there is a really simple solution 😂 Anyway, thanks for the help/ideas in advance!
o
Hi! The policies are meant to use the attributes incoming from the request made to Cerbos by your application. The application passes the related contextual data to the Cerbos by passing the required attributes in the request. Typically, the contextual data we are describing here are held in a database. For example, who owns a resource, and who can
get
this resource, etc. Before the request is made, the application fetches the data required and passes it along with the request, typically in the
attr
fields of the principal and/or resource. Let me describe how this works by giving you an example; Let’s say there are two resources in our example. The first resource, the
some_resource
with ID
1
is created by the user with ID
1
. In this case, naturally we would expect the user with ID
1
to be able to
get
this resource, but not others. The second resource, the
some_resource
with ID
2
is created by the user with ID
5
. But, we have an additional table in our relational database where we have a list of additional user IDs who is able to view this resource and in this list the user 1 exists. So, it looks like this; User 1 can
get
Resource 1 User 5 can
get
Resource 2 User 1 can
get
Resource 2 (due to user 1 being in the list of ‘usersWithViewAccess’) We should have two rules in the policy to express these to Cerbos. If a user is an owner of a resource, the user may
get
the resource. (
rule #1
) If a user is in the list of users with
get
access to a resource, the user may view the resource. (
rule #2
) Please see the Playground example for what I have described. https://play.cerbos.dev/p/ykONr75mhB6370f440Nyq4sTZDaHEFka I hope this answer your questions. Please let me know if you have further questions, happy to help! cerbie
o
Thanks for the reply 🙏 How is the performance impact if the
usersWithGetAccess
size gets bigger? Let’s say 10 id’s vs 100 000 id’s in the
usersWithGetAccess
list? And in general does it impact the evaluation speed if the IDs are numbers vs strings (like UUID).
c
List lookups are quite fast but we don't recommend using very large lists in your policies because the lookup is going to be O(n) as we can't assume that the list is sorted. It sounds like you're trying to model an access control list (ACL) type of thing. In such scenarios you need to do some extra work in the application side for sake of efficiency. As you can probably appreciate, there's not much point in asking Cerbos to check whether a user ID exists in a list. You can do that much more efficiently using a database lookup. Where Cerbos can augment your workflow is after that. Once you know that X is in the allow list, you can send the attributes of X and the attributes of the resource X is trying to access to Cerbos and ask it evaluate whether the action is allowed. This is typically where you have business logic to execute (e.g. users in the US shouldn't have access to EU users, certain actions are allowed only within certain time periods of the day, etc.). Having that codified in Cerbos policies gives you and the organization a central source of truth for those rules and gives you the flexibility to adjust them without touching code.
o
Thanks for the help :)