Add and update scopes, roles, charts and text in docs/source/rbac docs

This commit is contained in:
IvanaH8
2021-04-07 14:34:41 +02:00
parent a512867a1e
commit 949ec5cc75
9 changed files with 133 additions and 70 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

View File

@@ -5,9 +5,9 @@ Role Based Access Control (RBAC) in JupyterHub serves to provide fine grained co
## Motivation ## Motivation
The JupyterHub API requires authorization before allowing changes to the backend. For instance, currently the default behaviour is that creating or deleting users requires *admin rights*. This ensures that an arbitrary user, or even an unauthenticated third party, are not allowed to perform such actions. The JupyterHub API requires authorization before allowing changes to the backend. For instance, currently the default behaviour is that creating or deleting users requires *admin rights*. This ensures that an arbitrary user, or even an unauthenticated third party, are not allowed to perform such actions.
This system is functional, but lacks flexibility. If your Hub serves a number of users in different groups, you might want to delegate permissions to other users or automate certain processes. Appointing a 'group-only admin', or a bot that culls idle servers, requires granting full rights to all actions. This poses a risk of the user or service intentionally or unintentionally accessing and modifying any data within the Hub and violates the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). This system is functional, but lacks flexibility. If your Hub serves a number of users in different groups, you might want to delegate permissions to other users or automate certain processes. With the current framework, appointing a 'group-only admin' or a bot that culls idle servers, requires granting full rights to all actions. This poses a risk of the user or service intentionally or unintentionally accessing and modifying any data within the Hub and violates the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
To remedy situations like this, we implement an RBAC system. By equipping users, groups and services with *roles* that supply them with a collection of permissions (*scopes*), administrators are able to fine-tune which parties are able to access which resources. To remedy situations like this, JupyterHub is transitioning to an RBAC system. By equipping users, groups and services with *roles* that supply them with a collection of permissions (*scopes*), administrators are able to fine-tune which parties are granted access to which resources.
## Definitions ## Definitions
__Scopes__ are specific permissions used to evaluate API requests. For example: the API endpoint `users/servers`, which enables starting or stopping user servers, is guarded by the scope `users:servers`. __Scopes__ are specific permissions used to evaluate API requests. For example: the API endpoint `users/servers`, which enables starting or stopping user servers, is guarded by the scope `users:servers`.
@@ -26,4 +26,5 @@ roles
scopes scopes
use-cases use-cases
tech-implementation tech-implementation
upgrade
``` ```

View File

@@ -1,19 +1,31 @@
# Roles # Roles
JupyterHub provides three **default roles** which are automatically loaded to the database at the startup: JupyterHub provides four roles that are available by default:
```{admonition} **Default roles** ```{admonition} **Default roles**
- `user` role provides a {ref}`default user scope <default-user-scope-target>` `all` that grants access to only the user's own resources. - `user` role provides a {ref}`default user scope <default-user-scope-target>` `self` that grants access to only the user's own resources.
- `admin` role contains all available scopes and grants full rights to all actions similarly to the current admin status. - `admin` role contains all available scopes and grants full rights to all actions similarly to the current admin status. This role **cannot be edited**.
- `server` role allows for posting activity only through the single `users:activity` scope. - `token` role provides a {ref}`default token scope <default-token-scope-target>` `all` that resolves to the same permissions as the token's owner has.
- `server` role allows for posting activity of "itself" only. The scope is currently under development.
**These roles cannot be deleted.**
``` ```
Roles can also be customly defined and assigned to users, services, groups and tokens. New roles can also be customly defined (see {ref}`define_role_target`). Roles can be assigned to the following entities:
- Users
- Services
- Groups
- Tokens
**_Users_** and **_services_** are assigned a default role ( `user` or `admin`) if no custom role is requested based on their admin status. An entity can have zero, one, or multiple roles, and there are no restrictions on which roles can be assigned to which entity. Roles can be added to or removed from entities at any time.
**_Tokens_** roles cannot grant the token higher permissions than their owners roles. If no specific role is requested, tokens are assigned the `user` role. **Users and services** \
When a new user or service gets created, they are assigned their default role ( `user` or `admin`) if no custom role is requested, currently based on their admin status.
**_Groups_** do not require any role and are not assigned any roles by default. Once roles are defined and assigned to groups, the privileges of each group member are extended when needed (see {ref}`resolving-roles-scopes-target` for more details). This is useful for assigning a set of common permissions to several users. **Groups** \
A group does not require any role, and has no roles by default. If a user is a member of a group, they autimatically inherit any of the group's permissions (see {ref}`resolving-roles-scopes-target` for more details). This is useful for assigning a set of common permissions to several users.
**Tokens** \
A tokens permissions are evaluated based on their owning entity. Since a token is always issued for a user or service, it can never have more permissions than its owner. If no specific role is requested for a new token, the token is assigned the `token` role.
(define_role_target)= (define_role_target)=
## Defining Roles ## Defining Roles
@@ -26,7 +38,7 @@ c.JupyterHub.load_roles = [
{ {
'name': 'server-rights', 'name': 'server-rights',
'description': 'Allows parties to start and stop user servers', 'description': 'Allows parties to start and stop user servers',
'scopes': ['users:servers', 'read:users:servers'], 'scopes': ['users:servers'],
'users': ['alice', 'bob'], 'users': ['alice', 'bob'],
'services': ['idle-culler'], 'services': ['idle-culler'],
'groups': ['admin-group'], 'groups': ['admin-group'],
@@ -39,8 +51,8 @@ The role `server-rights` now allows the starting and stopping of servers by any
- the service `idle-culler` - the service `idle-culler`
- any member of the `admin-group` - any member of the `admin-group`
- requests using the tokens `foo-6f6e65` or `bar-74776f`. - requests using the tokens `foo-6f6e65` or `bar-74776f`.
```{note} ```{attention}
The `foo-6f6e65` and `bar-74776f` tokens will be assigned the `server-rights` role only if their owner has the same or higher permissions. For example, if the tokens' owner has only `user` role, JupyterHub will throw an error. See {ref}`Figure 1 <api-token-request-chart>` for more details. The `foo-6f6e65` and `bar-74776f` tokens will be assigned the `server-rights` role only if their owner has the corresponding permissions, otherwise JupyterHub throws an error. See {ref}`resolving-roles-scopes-target` for more details on how this is assessed.
``` ```
Another example: Another example:
@@ -62,12 +74,14 @@ The role `reader` allows users `maria` and `joe` and service `external` to read
```{admonition} Requirements ```{admonition} Requirements
:class: warning :class: warning
In a role definition, the `name` field is required, while all other fields are optional. If no scopes are defined for new role, JupyterHub will raise a warning. In a role definition, the `name` field is required, while all other fields are optional.\
Moreover, `users`, `services`, `groups` and `tokens` only accept objects that already exist or are defined previously in the file. If no scopes are defined for new role, JupyterHub will raise a warning. Providing non-existing scopes will result in an error.\
Moreover, `users`, `services`, `groups` and `tokens` only accept objects that already exist or are defined previously in the file.\
It is not possible to implicitly add a new user to the database by defining a new role. It is not possible to implicitly add a new user to the database by defining a new role.
``` ```
\
In case the role with a certain name already exists in the database, its definition and scopes will be overwritten. This holds true for all roles except the `admin` role, which cannot be overwritten; an error will be raised if trying to do so. \
Any previously defined role bearers for this role will remain the role bearers but their permissions will change if the role's permissions are overwritten. The newly defined bearers (in this case `maria` and `joe` and `external`) will be added to the existing ones.
In case the role with a certain name already exists in the database, its definition and scopes will be overwritten. This holds true for any role apart from `admin` role that cannot be overwritten; an error will be raised if trying to do so. Once a role is loaded, it remains in the database until explicitly deleting it through `delete_role()` function in `roles.py`. Default roles cannot be deleted. \
Any previously defined role bearers will remain unchanged, but newly defined requesters (in this case `maria` and `joe` and `external`) will be assigned the new role definition. Omitting the `c.JupyterHub.load_roles` or specifying different roles in the `jupyterhub_config.py` file on the next startup will not erase previously defined roles, nor their bearers.
Once a role is loaded, it remains in the database until explicitly deleting it through `remove_role` function in `roles.py`. I.e., omitting the `c.JupyterHub.load_roles` or specifying different roles in the `jupyterhub_config.py` file on the next startup will not erase previously defined roles.

View File

@@ -2,7 +2,7 @@
A scope has a syntax-based design that reveals which resources it provides access to. Resources are objects with a type, associated data, relationships to other resources, and a set of methods that operate on them (see [RESTful API](https://restful-api-design.readthedocs.io/en/latest/resources.html) documentation for more information). A scope has a syntax-based design that reveals which resources it provides access to. Resources are objects with a type, associated data, relationships to other resources, and a set of methods that operate on them (see [RESTful API](https://restful-api-design.readthedocs.io/en/latest/resources.html) documentation for more information).
`<resource>` in the scope syntax here refers to the resource name in the [JupyterHub's API](../reference/rest-api.rst) endpoints. For instance, `<resource>` equal to `users` corresponds to JupyterHub's API endpoints beginning with _/users_. `<resource>` in the RBAC scope design refers to the resource name in the [JupyterHub's API](../reference/rest-api.rst) endpoints in most cases. For instance, `<resource>` equal to `users` corresponds to JupyterHub's API endpoints beginning with _/users_.
## Scope syntax ## Scope syntax
@@ -10,37 +10,47 @@ A scope has a syntax-based design that reveals which resources it provides acces
The `<resource>` scopes, such as `users` or `groups`, grant read and write permissions to the resource itself and all its sub-resources. E.g., the scope `users:servers` is included within the scope `users`. The `<resource>` scopes, such as `users` or `groups`, grant read and write permissions to the resource itself and all its sub-resources. E.g., the scope `users:servers` is included within the scope `users`.
+++ +++
- `<resource>:<subresource>` \
The {ref}`vertically filtered <vertical-filtering-target>` scopes provide access to a subset of the information granted by the `<resource>` scope. E.g., the scope `users:name` allows for accessing user names only.
+++
- `<resource>!<object>=<objectname>` \
{ref}`horizontal-filtering-target` is implemented by adding `!<object>=<objectname>` to the scope structure. A resource (or subresource) can be filtered based on `user`, `server`, `group` or `service` name. For instance, `<resource>!user=charlie` limits access to only return resources of user `charlie`. \
Only one filter per scope is allowed, but filters for the same scope have an additive effect; a larger filter can be used by supplying the scope multiple times with different filters.
+++
- `read:<resource>` \ - `read:<resource>` \
Limits permissions to **read-only** operations on the resource. Limits permissions to read-only operations on the resource.
+++ +++
- `admin:<resource>` \ - `admin:<resource>` \
Grants **create/delete permissions only** on the corresponding resource. For example, the scope `admin:users` allows creating and deleting users but does not allow for accessing information about existing users or modifying them, which is provided by the scope `users`. Grants create/delete permissions on the corresponding resource in addition to read and write permissions.
+++
- `<resource>:<subresource>` \
The {ref}`vertically filtered <vertical-filtering-target>` scopes provide access to a subset of the information granted by the `<resource>` scope. E.g., the scope `users:servers` allows for accessing user servers only.
+++
- `<resource>!<object>=<objectname>` \
{ref}`horizontal-filtering-target` is implemented by the `!<object>=<objectname>`scope structure. A resource (or sub-resource) can be filtered based on `user`, `server`, `group` or `service` name. For instance, `<resource>!user=charlie` limits access to only return resources of user `charlie`. \
Only one filter per scope is allowed, but filters for the same scope have an additive effect; a larger filter can be used by supplying the scope multiple times with different filters.
By adding a scope to an existing role, all role bearers will gain the associated permissions. By adding a scope to an existing role, all role bearers will gain the associated permissions.
## Available scopes
[](../reference/rest-api.rst) documentation lists all available scopes. Each API endpoint has a list of scopes which can be used to access the API. ## Metascopes
```{important}
Note that only the {ref}`horizontal filtering <horizontal-filtering-target>` can be added to scopes to customize them. `<resource>` scopes, `<resource>:<subresource>`, `read:<resource>` and `admin:<resource>` scopes are predefined and cannot be changed otherwise. Metascopes do not follow the general scope syntax. Instead, a metascope resolves to a set of scopes, which can refer to different resources, based on their owning entity. In JupyterHub, there are currently two metascopes:
``` 1. default user scope `self`, and
2. default token scope `all`.
(default-user-scope-target)= (default-user-scope-target)=
## Default user scope ### Default user scope
Access to the user's own resources and subresources is covered by metascope `self`. This metascope includes the user's model, activity, servers and tokens. For example, `self` for a user named "gerard" includes:
- `users!user=gerard` where the `users` scope provides access to the full user model and activity. The filter restricts this access to the user's own resources.
- `users:servers!user=gerard` which grants the user access to their own servers without being able to create/delete any.
- `users:tokens!user=gerard` which allows the user to access, request and delete their own tokens.
The default user scope `all` provides access to the user's own resources and subresources, including the user's model, activity, servers and tokens. For example, the scope for a user `'gerard'` covers: The `self` scope is only valid for user entities. In other cases (e.g., for services) it resolves to an empty set of scopes.
- `users!user=gerard` where the `users` scope includes access to the full user model, activity and starting/stopping servers. The horizontal filter restricts this access to the user's own resources.
- `users:tokens!user=gerard` allows the user to access, request and delete his own tokens only. (default-token-scope-target)=
### Default token scope
The token metascope `all` covers the same scopes as the token owner's scopes during requests. For example, if a token owner has roles containing the scopes `read:groups` and `read:users`, the `all` scope resolves to the set of scopes `{read:groups, read:users}`.
If the token owner has default `user` role, the `all` scope resolves to `self`, which will subsequently be expanded to include all the user-specific scopes (or empty set in the case of services).
If the token owner is a member of any group with roles, the group scopes will also be included in resolving the `all` scope.
(horizontal-filtering-target)= (horizontal-filtering-target)=
## Horizontal filtering ## Horizontal filtering
@@ -59,3 +69,19 @@ In case the client has multiple subscopes, the call returns the union of the dat
The payload of an API call can be filtered both horizontally and vertically simultaneously. For instance, performing an API call to the endpoint `/users/` with the scope `users:name!user=juliette` returns a payload of `[{name: 'juliette'}]` (provided that this name is present in the database). The payload of an API call can be filtered both horizontally and vertically simultaneously. For instance, performing an API call to the endpoint `/users/` with the scope `users:name!user=juliette` returns a payload of `[{name: 'juliette'}]` (provided that this name is present in the database).
## Available scopes
Table below lists all available scopes and illustrates their hierarchy.
_Table of scopes here_
```{Caution}
Note that only the {ref}`horizontal filtering <horizontal-filtering-target>` can be added to scopes to customize them. \
Metascopes `self` and `all`, `<resource>`, `<resource>:<subresource>`, `read:<resource>` and `admin:<resource>` scopes are predefined and cannot be changed otherwise.
```
### Scopes and APIs
The scopes are also listed in the [](../reference/rest-api.rst) documentation. Each API endpoint has a list of scopes which can be used to access the API; if no scopes are listed, the API is not authenticated and can be accessed without any permissions (i.e., no scopes).
Listed scopes by each API endpoint reflect the "lowest" permissions required to gain any access to the corresponding API. For example, posting user's activity (_POST /users/:name/activity_) needs `users:activity` scope. If scope `users` is passed during the request, the access will be granted as the required scope is a subscope of the `users` scope. If, on the other hand, `read:users:activity` scope is passed, the access will be denied.

View File

@@ -1,49 +1,59 @@
# Technical Implementation # Technical Implementation
Roles are stored in the database similarly as users, services, etc., and can be added or modified as explained in {ref}`define_role_target`. Objects can gain, change and lose roles. For example, one can change a token's role, and as such its permissions, without the need to initiate new token (currently through `update_roles` and `remove_obj` functions in `roles.py`, this will be eventually available through APIs). Roles' and scopes' utilities can be found in `roles.py` and `scopes.py` modules. Roles are stored in the database similarly as users, services, etc., and can be added or modified as explained in {ref}`define_role_target` section. Users, services, groups and tokens can gain, change and lose roles. For example, one can change a token's role, and as such its permissions, without the need to initiate new token (currently through `update_roles()` and `strip_role()` functions in `roles.py`, this will be eventually available through APIs). Roles' and scopes' utilities can be found in `roles.py` and `scopes.py` modules.
(resolving-roles-scopes-target)= (resolving-roles-scopes-target)=
## Resolving roles and scopes ## Resolving roles and scopes
**Resolving roles** refers to determining which roles a user, service, token or group has, extracting the list of scopes from each role and combining them into a single set of scopes. **Resolving roles** refers to determining which roles a user, service, token or group has, extracting the list of scopes from each role and combining them into a single set of scopes.
**Resolving scopes** involves comparing two sets of scopes taking into account the scope hierarchy. This includes {ref}`vertical <vertical-filtering-target>` and {ref}`horizontal filtering <horizontal-filtering-target>` and limiting or elevated permissions (`read:<resource>` or `admin:<resource>`, respectively). **Resolving scopes** involves expanding scopes into all their possible subscopes and, if applicable, comparing two sets of scopes. Both procedures take into account the scope hierarchy, {ref}`vertical <vertical-filtering-target>` and {ref}`horizontal filtering <horizontal-filtering-target>` limiting or elevated permissions (`read:<resource>` or `admin:<resource>`, respectively), and metascopes.
Roles and scopes are resolved on several occasions, for example when requesting an API token with specific roles or making an API request. The following sections provide more details. Roles and scopes are resolved on several occasions, for example when requesting an API token with specific roles or making an API request. The following sections provide more details.
### Requesting API token with specific roles ### Requesting API token with specific roles
API tokens grant access to JupyterHub's APIs. The RBAC framework allows for requesting tokens with specific existing roles. To date, it is only possible to add roles to a token in two ways: API tokens grant access to JupyterHub's APIs. The RBAC framework allows for requesting tokens with specific existing roles. To date, it is only possible to add roles to a token in two ways:
1. through the `jupyterhub_config.py` file as described in the {ref}`define_role_target` section 1. through the `jupyterhub_config.py` file as described in the {ref}`define_role_target` section
2. through the POST /users/{name}/tokens API where the roles can be specified in the token parameters body (see [](../reference/rest-api.rst)). 2. through the _POST /users/:name/tokens_ API where the roles can be specified in the token parameters body (see [](../reference/rest-api.rst)).
The RBAC framework adds several steps into the token issue flow. The RBAC framework adds several steps into the token issue flow.
If no roles are requested, the token is issued with a default role (providing the requester is allowed to create the token). If no roles are requested, the token is issued with a default role (providing the requester is allowed to create the token).
If the token is requested with a specific role or multiple roles, the permissions of the would-be token's owner are checked against the requested permissions to ensure the token will not grant its owner additional privileges. In practice, this corresponds to resolving all the token owner's roles (including the roles associated with their groups) and the token's requested roles into a set of scopes. The two sets are compared and if the token's scopes are a subset of the token owner's scopes, the token is issued with the requested roles. If the token is requested with any roles, the permissions of requesting entity are checked against the requested permissions to ensure the token will not grant its owner additional privileges.
{ref}`Figure 1 <api-token-request-chart>` below illustrates this process. The orange rectangles highlight where in the process the roles and scopes are resolved. If, due to modifications of roles or entities, at API request time a token has any scopes that its owner does not, those scopes are not taken into account. The API request is resolved without additional errors, but the Hub logs a warning (see {ref}`Figure 2 <api-request-chart>`).
```{figure} ../images/rbac-api-token-request-chart.png Resolving token's roles (yellow box in {ref}`Figure 1 <token-request-chart>`) corresponds to resolving all the token's owner roles (including the roles associated with their groups) and the token's requested roles into a set of scopes. The two sets are compared (Resolve the scopes box in orange in {ref}`Figure 1 <token-request-chart>`), taking into account the scope hierarchy but, solely for role assignment, omitting any {ref}`horizontal filter <horizontal-filtering-target>` comparison. If the token's scopes are a subset of the token owner's scopes, the token is issued with the requested roles; if not, JupyterHub will raise an error.
{ref}`Figure 1 <token-request-chart>` below illustrates the steps involved. The orange rectangles highlight where in the process the roles and scopes are resolved.
```{figure} ../images/rbac-token-request-chart.png
:align: center :align: center
:name: api-token-request-chart :name: token-request-chart
Figure 1. Resolving roles and scopes during API token request Figure 1. Resolving roles and scopes during API token request
``` ```
```{note} ```{note}
The above check is also performed when roles are requested for existing tokens, e.g., when adding tokens to {ref}`role definitions through the config.py <define_role_target>`. The above check is also performed when roles are requested for existing tokens, e.g., when adding tokens to {ref}`role definitions <define_role_target>` through the `jupyterhub_config.py`.
``` ```
### Making API request ### Making API request
With the RBAC framework each authenticated JupyterHub API request is guarded by a scope decorator that specifies which scopes are required to gain the access to the API. With the RBAC framework each authenticated JupyterHub API request is guarded by a scope decorator that specifies which scopes are required to gain the access to the API.
When an API request is performed, the passed API token's roles are again resolved into a set of scopes and compared to the scopes required to access the API as follows: When an API request is performed, the passed API token's roles are again resolved (yellow box in {ref}`Figure 2 <api-request-chart>`) to ensure the token does not grant more permissions than its owner has at the request time (e.g., due to changing/losing roles).
- if the API scopes are present within the set of token's scopes, the access is granted and the API returns its "full" response If the owner's roles do not include some scopes of the token's scopes, only the intersection of the token's and owner's scopes will be passed further. For example, using a token with scope `users` whose owner's role scope is `read:users:name` will results in only the `read:users:name` scope being passed on. In the case of no intersection, en empty set of scopes will be passed on.
- if that is not the case, another check is utilized to determine if sub-scopes of the required API scopes can be found in the token's scope set:
- if the subscopes are present, the RBAC framework employs the {ref}`filtering <horizontal-filtering-target>` procedures to refine the API response to provide access to only resource attributes specified by the token provided scopes The passed scopes are compared to the scopes required to access the API as follows:
- for example, providing a scope `read:users:activity!group=class-C` for the _GET /users_ API will return a list of user models from group `class-C` containing only the `last_activity` attribute for each user model
- if the subscopes are not present, the access to API is denied - if the API scopes are present within the set of passed scopes, the access is granted and the API returns its "full" response
- if that is not the case, another check is utilized to determine if subscopes of the required API scopes can be found in the passed scope set:
- if found, the RBAC framework employs the {ref}`filtering <vertical-filtering-target>` procedures to refine the API response to access only resource attributes corresponding to the passed scopes. For example, providing a scope `read:users:activity!group=class-C` for the _GET /users_ API will return a list of user models from group `class-C` containing only the `last_activity` attribute for each user model
- if not found, the access to API is denied
{ref}`Figure 2 <api-request-chart>` illustrates this process highlighting the steps where the role and scope resolutions as well as filtering occur in orange. {ref}`Figure 2 <api-request-chart>` illustrates this process highlighting the steps where the role and scope resolutions as well as filtering occur in orange.

View File

@@ -0,0 +1 @@
# Upgrading JupyterHub with RBAC framework

View File

@@ -1,17 +1,14 @@
# Use Cases # Use Cases
To determine which scopes a role should have it is best to follow these steps: To determine which scopes a role should have, one can follow these steps:
1. Determine what actions the role holder should have/have not access to 1. Determine what actions the role holder should have/have not access to
2. Match the actions against the JupyterHub's REST APIs 2. Match the actions against the [JupyterHub's APIs](../reference/rest-api.rst)
3. Check which scopes are required to access the APIs 3. Check which scopes are required to access the APIs
4. Customize the scopes with filters if needed 4. Combine scopes and subscopes if applicable
5. Define the role with required scopes and assign to users/services/groups/tokens 5. Customize the scopes with filters if needed
6. Define the role with required scopes and assign to users/services/groups/tokens
Below, different use cases are presented on how to use the RBAC framework. Below, different use cases are presented on how to use the RBAC framework.
## User access
A regular user should be able to view and manage all of their own resources. This can be achieved using the scope `all` (or assigning the `user` role). If the user's access is to be restricted from modifying any of their resources (e.g., when a teacher wants to check their notebooks), their role should be changed to read-only access, in this case scope `read:all`.
## Service to cull idle servers ## Service to cull idle servers
@@ -39,7 +36,7 @@ Below follows a short tutorial on how to add a cull-idle service in the RBAC sys
{ {
"name": "idle-culler", "name": "idle-culler",
"description": "Culls idle servers", "description": "Culls idle servers",
"scopes": ["read:users:name", "read:users:activity", "read:users:servers", "users:servers"], "scopes": ["read:users:name", "read:users:activity", "users:servers"],
"services": ["idle-culler"], "services": ["idle-culler"],
} }
] ]
@@ -47,27 +44,41 @@ Below follows a short tutorial on how to add a cull-idle service in the RBAC sys
```{important} ```{important}
Note that in the RBAC system the `admin` field in the `idle-culler` service definition is omitted. Instead, the `idle-culler` role provides the service with only the permissions it needs. Note that in the RBAC system the `admin` field in the `idle-culler` service definition is omitted. Instead, the `idle-culler` role provides the service with only the permissions it needs.
If the optional actions of deleting the idle servers and/or removing inactive users are desired, **add the following scopes** to the `idle-culler` role definition: If the optional actions of deleting the idle servers and/or removing inactive users are desired, **change the following scopes** in the `idle-culler` role definition:
- `admin:users:servers` for deleting servers - `users:servers` to `admin:users:servers` for deleting servers
- `admin:users` for deleting users. - `read:users:name`, `read:users:activity` to `admin:users` for deleting users.
``` ```
3. Restart JupyterHub to complete the process. 3. Restart JupyterHub to complete the process.
## API launcher ## API launcher
A service capable of creating/removing users and launching multiple servers should have access to: A service capable of creating/removing users and launching multiple servers should have access to:
1. POST and DELETE /users 1. _POST_ and _DELETE /users_
2. POST and DELETE /users/{name}/server 2. _POST_ and _DELETE /users/:name/server_ or _/users/:name/servers/:server_name_
3. Creating/deleting servers 3. Creating/deleting servers
From the above, the scopes required for the role are The scopes required to access the API enpoints:
1. `admin:users` 1. `admin:users`
2. `users:servers` 2. `users:servers`
3. `admin:users:servers` 3. `admin:users:servers`
From the above, the role definition is:
```python
# in jupyterhub_config.py
c.JupyterHub.load_roles = [
{
"name": "api-launcher",
"description": "Manages servers",
"scopes": ["admin:users", "admin:users:servers"],
"services": [<service_name>]
}
]
```
If needed, the scopes can be modified to limit the permissions to e.g. a particular group with `!group=groupname` filter. If needed, the scopes can be modified to limit the permissions to e.g. a particular group with `!group=groupname` filter.
## Users as group admins/Group admin roles ## Group admin roles
Roles can be used to specify different group member privileges. Roles can be used to specify different group member privileges.