hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.01k stars 2.76k forks source link

Derived Permissions #3544

Open nowylie opened 4 years ago

nowylie commented 4 years ago

The Problem

Managing permissions for related tables can be both repetitive and error prone.

Currently we have a number of child tables within our database. These tables have a foreign key relation to some parent table and they do not exist without a parent record. For most of these tables the permissions for the child table are the same as the permissions for the parent table.

For example, I have a parent table application and a child table application_file. I can select the application table if my X-Hasura-User-Id matches the user_id field. I can select the application_file table if my X-Hasura-User-Id matches the application.user_id field (through an object relation).

Now if my requirements change and I need to update the select permission on the application table I need to also go and specify the identical permissions on the application_file table (repetitive) and I have a chance to forget to update the application_file permissions (error prone).

The more child tables I have linked to the parent (and the more parent tables in general) the more repetitive/error prone this becomes.

The Solution

Ideally I want to be able to derive the permissions on my child table from the permissions on my parent table (i.e. If user has insert/select/update/delete permission on the related table it has insert/select/update/delete permission on this table).

This would mean that any time I change the permission on the parent table the child table permissions are up-to-date by default and I also don't have to repeat the exact permission checks on the child table.

We can nearly model this behaviour for select permissions using the new _exists permission but it doesn't work for insert/update/delete permissions.

pnappa commented 4 years ago

Does this only cover the case of all columns being selected in both parent and child for a specific role, for a specific SQL verb (INSERT, etc)? Otherwise, how would you express that when you have disjoint columns, for example?

nowylie commented 4 years ago

I had imagined this functionality as being constrained to the row select permissions. You would still specify the column permissions per action for the child table.

Using the example above, in the current version of graphql-engine I specify the application select permissions like so:

{
   "user_id": {
      "_eq": "X-Hasura-User-Id"
   }
}

and the select permissions on my application_file table as:

{
   "application": {
      "user_id": {
         "_eq": "X-Hasura-User-Id"
      }
   }
}

I would like to be able to specify the select permissions on my application_file table as:

{
    "application": {
        "_select": true
    }
}

which would translate to:

If the user has select permission on the related application row then allow select on this application_file row

This way if I change the select permission on the application table I don't need to update the permission on the application_file table.

heliocaruccio commented 3 years ago

any movement here?

nikhilshinday commented 1 year ago

hey @0x777, is there any movement on this? It's a quality-of-life update that would really benefit the product and would drastically increase hasura's usage for more complex (enterprise) use cases. It also plays nicely into relationship-based permissions models and I think you'd get a lot of enthusiasm and adoption from engineers who have used authz systems that are zanzibar-adjacent

nikhilshinday commented 12 months ago

following up here @0x777 - this is an urgent feature that would leverage us to continue using Hasura rather than moving off of it. Our business relies on it heavily, and the choice is to either continue using Hasura (and start paying for its' use on-prem as we require more enterprise features) or move to our own API. We're willing to pay to get this feature implemented sooner than later. Any response would be appreciated.

coffenbacher commented 8 months ago

Every time I use Hasura's AuthZ system I think this is a desperately needed feature. I finally reached the point that I want to vocalize support for it. In many ways Hasura is much better than traditional API-writing approaches; in this one way it's a pain in the ass.

I feel like this feature is actually pretty straightforward as well, compared to a lot of the other work going on in Hasura. It's basically just adding an ability to reference an existing permission set instead of requiring you to re-write it and maintain both copies. @nowylie's example is great.

In our scenario we have many permissions with complicated _and and _or relationships and keeping them in sync on all of the child tables is a pain. I am almost to the point of writing something to manage the metadata.yaml file to do it for us.

williamliu52 commented 4 months ago

Looks like this is part of the Hasura v3 roadmap: https://github.com/hasura/graphql-engine/blob/0x777-v3-permission-improvements/rfcs/permission-improvements-v3.md#1-reusing-parent-permissions