mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
docs: document inherited roles
Co-authored-by: Rikin Kachhia <54616969+rikinsk@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> GitOrigin-RevId: b147ed69b90c40d6e1478f028f5d9d7e6f5629f0
This commit is contained in:
parent
5778fe3e9b
commit
067a38f74d
@ -413,6 +413,18 @@ The various types of queries are listed in the following table:
|
||||
- 1
|
||||
- Drop a RESTified GraphQL Endpoint
|
||||
|
||||
* - :ref:`metadata_add_inherited_role`
|
||||
- :ref:`add_inherited_role_args <metadata_add_inherited_role_syntax>`
|
||||
- 1
|
||||
- Add an inherited role
|
||||
|
||||
* - :ref:`metadata_drop_inherited_role`
|
||||
- :ref:`drop_inherited_role_args <metadata_drop_inherited_role_syntax>`
|
||||
- 1
|
||||
- Drop an inherited role
|
||||
|
||||
|
||||
|
||||
**See:**
|
||||
|
||||
- :ref:`Tables/Views <metadata_api_tables_views>`
|
||||
@ -420,6 +432,7 @@ The various types of queries are listed in the following table:
|
||||
- :ref:`Relationships <metadata_api_relationship>`
|
||||
- :ref:`Computed Fields <metadata_api_computed_field>`
|
||||
- :ref:`Permissions <metadata_api_permission>`
|
||||
- :ref:`Inherited Roles <metadata_inherited_role>`
|
||||
- :ref:`Remote Schema Permissions <metadata_remote_schema_api_permission>`
|
||||
- :ref:`Event Triggers <metadata_api_event_triggers>`
|
||||
- :ref:`Remote Schemas <metadata_api_remote_schemas>`
|
||||
@ -512,6 +525,7 @@ The version is incremented on any operation that modified metadata as well as ``
|
||||
Custom Functions <custom-functions>
|
||||
Relationships <relationship>
|
||||
Permissions <permission>
|
||||
Inherited Roles <inherited-roles>
|
||||
Remote Schema Permissions <remote-schema-permissions>
|
||||
Computed Fields <computed-field>
|
||||
Event Triggers <event-triggers>
|
||||
|
105
docs/graphql/core/api-reference/metadata-api/inherited-roles.rst
Normal file
105
docs/graphql/core/api-reference/metadata-api/inherited-roles.rst
Normal file
@ -0,0 +1,105 @@
|
||||
.. meta::
|
||||
:description: Manage inherited roles with the Hasura metadata API
|
||||
:keywords: hasura, docs, metadata API, API reference, inherited roles, multiple roles
|
||||
|
||||
.. _metadata_inherited_role:
|
||||
|
||||
Metadata API Reference: Inherited Roles
|
||||
=======================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Inherited roles allow you to create a role which inherits permissions from other non-inherited roles.
|
||||
|
||||
.. admonition:: Supported from
|
||||
|
||||
The metadata API is supported for versions ``v2.0.0`` and above and replaces the older
|
||||
:ref:`schema/metadata API <schema_metadata_apis>`.
|
||||
|
||||
.. _metadata_add_inherited_role:
|
||||
|
||||
add_inherited_role
|
||||
------------------
|
||||
|
||||
``add_inherited_role`` is used to create a new inherited role with existing non-inherited roles.
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type":"add_inherited_role",
|
||||
"args":{
|
||||
"role": "sample_inherited_role",
|
||||
"role_set": [
|
||||
"role1",
|
||||
"role2"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
.. _metadata_add_inherited_role_syntax:
|
||||
|
||||
Args syntax
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Key
|
||||
- Required
|
||||
- Schema
|
||||
- Description
|
||||
* - role
|
||||
- true
|
||||
- :ref:`RoleName`
|
||||
- Name of the inherited role
|
||||
* - role_set
|
||||
- true
|
||||
- [:ref:`RoleName`]
|
||||
- List of non-inherited roles from which permissions should be inherited
|
||||
|
||||
.. _metadata_drop_inherited_role:
|
||||
|
||||
drop_inherited_role
|
||||
-------------------
|
||||
|
||||
``drop_inherited_role`` is used to delete an existing inherited role.
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type" : "drop_inherited_role",
|
||||
"args" : {
|
||||
"role": "sample_inherited_role"
|
||||
}
|
||||
}
|
||||
|
||||
.. _metadata_drop_inherited_role_syntax:
|
||||
|
||||
Args syntax
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Key
|
||||
- Required
|
||||
- Schema
|
||||
- Description
|
||||
* - role
|
||||
- true
|
||||
- :ref:`RoleName`
|
||||
- Name of the inherited role
|
@ -54,10 +54,12 @@ Follow the example at :ref:`access control basics <auth_basics>`.
|
||||
|
||||
basics
|
||||
roles-variables
|
||||
inherited-roles
|
||||
permission-rules
|
||||
common-roles-auth-examples
|
||||
role-multiple-rules
|
||||
|
||||
|
||||
.. admonition:: Additional Resources
|
||||
|
||||
Enterprise Grade Authorization - `Watch Webinar <https://hasura.io/events/webinar/authorization-modeling-hasura/?pg=docs&plcmt=body&cta=watch-webinar&tech=>`__.
|
||||
Enterprise Grade Authorization - `Watch Webinar <https://hasura.io/events/webinar/authorization-modeling-hasura/?pg=docs&plcmt=body&cta=watch-webinar&tech=>`__.
|
||||
|
336
docs/graphql/core/auth/authorization/inherited-roles.rst
Normal file
336
docs/graphql/core/auth/authorization/inherited-roles.rst
Normal file
@ -0,0 +1,336 @@
|
||||
.. meta::
|
||||
:description: Hasura inherited roles
|
||||
:keywords: hasura, docs, authorization, multiple roles, inherited roles
|
||||
|
||||
.. _inherited_roles:
|
||||
|
||||
Inherited roles
|
||||
===============
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
An inherited role is a way to create a new role which infers permissions from two or more non-inherited roles. Once an inherited role is created, it can be treated as any other role i.e. can be given in ``X-Hasura-Role`` session variable.
|
||||
|
||||
Inherited roles are useful when you need to define multiple permission rules (may be overlapping) on schema objects and also for greater modularity in role management.
|
||||
|
||||
.. note::
|
||||
|
||||
This feature is currently accessible as an experimental feature and must be enabled.
|
||||
This can be done either by setting the env var ``HASURA_GRAPHQL_EXPERIMENTAL_FEATURES``
|
||||
to ``inherited_roles`` or by providing the server flag ``--experimental-features``
|
||||
to ``inherited_roles``.
|
||||
|
||||
See :ref:`server flag reference <server_flag_reference>` for info on setting the flag/env var.
|
||||
|
||||
.. admonition:: Supported from
|
||||
|
||||
Inherited roles are supported for versions ``v2.0.0-alpha.4`` and above.
|
||||
|
||||
Creating Inherited roles
|
||||
------------------------
|
||||
|
||||
.. rst-class:: api_tabs
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Console
|
||||
|
||||
Go to the ``Settings`` tab on the console and click on ``Inherited Roles``.
|
||||
|
||||
.. thumbnail:: /img/graphql/core/auth/console-inherited-role.png
|
||||
:alt: Console create inherited role
|
||||
:width: 1100px
|
||||
|
||||
.. tab:: CLI
|
||||
|
||||
To add a new inherited role, edit the ``metadata/inherited_roles.yaml`` file adding the inherited role definition
|
||||
like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- role_name: sample_inherited_role
|
||||
role_set:
|
||||
- user
|
||||
- editor
|
||||
|
||||
Apply the metadata by running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
hasura metadata apply
|
||||
|
||||
.. tab:: API
|
||||
|
||||
You can add a inherited role using the :ref:`add_inherited_role metadata API <metadata_add_inherited_role>`:
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "add_inherited_role",
|
||||
"args": {
|
||||
"role_name":"sample_inherited_role",
|
||||
"role_set":[
|
||||
"user",
|
||||
"editor"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
How is the permission of the inherited role inferred?
|
||||
-----------------------------------------------------
|
||||
|
||||
A select permission is comprised of the following things:
|
||||
|
||||
1. Columns accessible to the role
|
||||
2. Row selection filter
|
||||
3. Limit
|
||||
4. Allow aggregation
|
||||
5. Scalar computed fields accessible to the role
|
||||
|
||||
.. note::
|
||||
|
||||
Inherited roles can only combine SELECT permissions currently
|
||||
|
||||
Suppose there are two roles, ``role1`` gives access to column ``C1`` with row filter ``P1`` and ``role2`` gives access to columns ``C1`` and ``C2`` with row filter ``P2``. Consider the following GraphQL query executed with an inherited role comprised of ``role1`` and ``role2``:
|
||||
|
||||
.. code-block:: graphql
|
||||
|
||||
query {
|
||||
T {
|
||||
C1
|
||||
C2
|
||||
}
|
||||
}
|
||||
|
||||
The above GraphQL query will be translated to the following SQL query.
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
select (case when (P1 or P2) then C1 else null end) as C1,
|
||||
(case when P2 then C2 else null end) as C2
|
||||
from T
|
||||
where (P1 or P2)
|
||||
|
||||
|
||||
The other parameters of the select permission will be combined in the following manner:
|
||||
|
||||
1. Limit - Minimum of the limits will be the limit of the inherited role
|
||||
2. Allow aggregations - If any of the role allows aggregation, then the inherited role will allow aggregation
|
||||
3. Scalar computed fields - same as table column fields, as in the above example
|
||||
|
||||
Accessibility of a field to an inherited role is defined as follows:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. When all the roles give access to a column ``C``, then ``C`` will
|
||||
always be accessible.
|
||||
2. When not all, but some of the roles give access to the column ``C``
|
||||
then the value of the column ``C`` will be outputed when the OR
|
||||
of ``P1,P2....P(n)`` is ``true`` and when it evaluates to ``false``,
|
||||
the value of the column ``C`` will be ``null``, where ``P`` is the
|
||||
row filter of the select permissions in which column ``C`` is given access to.
|
||||
3. When none of the roles give access to column ``C``, it won't be accessible
|
||||
to the inherited role.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Let's take the example of an ``users`` table with the following columns:
|
||||
|
||||
1. ``id`` - Int - Primary key
|
||||
2. ``name`` - Text
|
||||
3. ``email`` - Text
|
||||
|
||||
There are two roles defined namely ``employee`` and ``manager``.
|
||||
|
||||
1. User role - The user role will be able to able to access all columns of their row when the session variable ``X-Hasura-User-Id`` is equal to the ``id``.
|
||||
|
||||
2. Anonymous role - The anonymous role will be able to access only the ``id`` and ``name`` columns of all the users.
|
||||
|
||||
Let's create a new inherited role called ``user_anonymous_inherited_role`` which inherits from the ``user`` and the ``anonymous`` roles.
|
||||
|
||||
1. Executing the query as ``user`` role
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/graphql HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: user
|
||||
X-Hasura-User-Id: 1
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
users {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "alice",
|
||||
"email": "alice@xyz.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
2. Executing the query as ``anonymous`` role
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/graphql HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: anonymous
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
users {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Bob"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Sam"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
3. Executing the query as ``user_anonymous_inherited_role`` role
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/graphql HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: user_anonymous_inherited_role
|
||||
X-Hasura-User-Id: 1
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
users {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice",
|
||||
"email": "alice@xyz.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Bob",
|
||||
"email": null
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Sam",
|
||||
"email": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
In the response of the query being executed with the ``user_anonymous_inherited_role`` role, there are 3 rows returned and if
|
||||
we compare that to the queries executed as the ``user`` and ``anonymous`` roles, the results are unioned in the inherited
|
||||
role. But some of the fields have ``null`` values despite the value in the database not being ``null``. This can only happen
|
||||
with inherited roles when a column doesn't have permission in the particular row. In the above example, we see that the
|
||||
``email`` of "Bob" and "Sam" is ``null`` but a non null value for "Alice", this is because the "Alice" row is executed as the
|
||||
``user`` role and the other rows are executed as the ``anonymous`` role which is why is why the value is ``null``.
|
||||
|
||||
|
||||
4. Suppose we have two tables ``users`` and ``authors`` and similarly two roles ``user`` and ``author`` are defined. The ``user``
|
||||
role doesn't have permission to query the ``authors`` table and the ``user`` role doesn't have permission to query the ``authors`` table. With only the ``user`` and the ``author`` role, we won't be able to construct a query which fetches data from both the tables. This can be solved by creating an inherited role out of ``user`` and ``author`` which can query both the
|
||||
tables in a single query.
|
||||
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/graphql HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: user_authors_inherited_role
|
||||
X-Hasura-User-Id: 1
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
users {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
authors {
|
||||
id
|
||||
name
|
||||
followers
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice",
|
||||
"email": "alice@xyz.com"
|
||||
}
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Paulo Coelho",
|
||||
"followers": 10382193
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Present limitations
|
||||
-------------------
|
||||
|
||||
Currently, inherited roles are supported only for Postgres read queries and subscriptions.
|
||||
The following features are **not** supported for inherited roles yet:
|
||||
|
||||
1. Mutations
|
||||
2. Actions
|
||||
3. Remote schemas
|
@ -252,6 +252,10 @@ For the ``serve`` sub-command these are the available flags and ENV variables:
|
||||
|
||||
*(Available for versions > v2.0.0)*
|
||||
|
||||
* - ``--experimental-features``
|
||||
- ``HASURA_GRAPHQL_EXPERIMENTAL_FEATURES``
|
||||
- List of experimental features to be enabled. A comma separated value is expected. Options: ``inherited_roles``.
|
||||
|
||||
.. note::
|
||||
|
||||
When the equivalent flags for environment variables are used, the flags will take precedence.
|
||||
|
BIN
docs/img/graphql/core/auth/console-inherited-role.png
Normal file
BIN
docs/img/graphql/core/auth/console-inherited-role.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
Loading…
Reference in New Issue
Block a user