From 916a83a9549ed85358f9c3d443f2091ec2dff33b Mon Sep 17 00:00:00 2001 From: Christian Dike Date: Tue, 11 Oct 2022 19:03:21 +0100 Subject: [PATCH 1/3] Update tech-implementation.md Fix typos and grammatical errors. Improve sentence structure. Use appropriate technical terms. --- docs/source/rbac/tech-implementation.md | 35 ++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/source/rbac/tech-implementation.md b/docs/source/rbac/tech-implementation.md index 3156dbf1..b3084ed5 100644 --- a/docs/source/rbac/tech-implementation.md +++ b/docs/source/rbac/tech-implementation.md @@ -1,8 +1,8 @@ # Technical Implementation -Roles are stored in the database, where they are associated with 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. This is currently achieved via `jupyterhub_config.py` (see {ref}`define-role-target`) and will be made available via API in future. The latter will allow for changing a token's role, and thereby its permissions, without the need to issue a new token. +[Roles](https://jupyterhub.readthedocs.io/en/stable/rbac/roles.html#roles) are stored in the database, where they are associated with users, services, groups and tokens. Roles can be added or modified as explained in the {ref}`define-role-target` section. Users, services, groups, and tokens can gain, change, and lose roles. This is currently achieved via `jupyterhub_config.py` (see {ref}`define-role-target`) and will be made available via API in the future. The latter will allow for changing a token's role, and thereby its permissions, without the need to issue a new token. -Roles and scopes utilities can be found in `roles.py` and `scopes.py` modules. Scope variables take on five different formats which is reflected throughout the utilities via specific nomenclature: +Roles and scopes utilities can be found in `roles.py` and `scopes.py` modules. Scope variables take on five different formats that are reflected throughout the utilities via specific nomenclature: ```{admonition} **Scope variable nomenclature** :class: tip @@ -11,22 +11,22 @@ Roles and scopes utilities can be found in `roles.py` and `scopes.py` modules. S - _expanded scopes_ \ Set of fully expanded scopes without abbreviations (i.e., resolved metascopes, filters, and subscopes). E.g., `{"users:activity!user=charlie", "read:users:activity!user=charlie"}`. - _parsed scopes_ \ - Dictionary represenation of expanded scopes. E.g., `{"users:activity": {"user": ["charlie"]}, "read:users:activity": {"users": ["charlie"]}}`. + Dictionary representation of expanded scopes. E.g., `{"users:activity": {"user": ["charlie"]}, "read:users:activity": {"users": ["charlie"]}}`. - _intersection_ \ Set of expanded scopes as intersection of 2 expanded scope sets. - _identify scopes_ \ - Set of expanded scopes needed for identify (whoami) endpoints. + Set of expanded scopes needed for identity (whoami) endpoints. ``` (resolving-roles-scopes-target)= ## Resolving roles and scopes -**Resolving roles** refers to determining which roles a user, service, or group has, extracting the list of scopes from each role and combining them into a single set of scopes. +**Resolving roles** involves determining which roles a user, service, or group has, extracting the list of scopes from each role and combining them into a single set of scopes. -**Resolving scopes** involves expanding scopes into all their possible subscopes (_expanded scopes_), parsing them into format used for access evaluation (_parsed scopes_) and, if applicable, comparing two sets of scopes (_intersection_). All procedures take into account the scope hierarchy, {ref}`vertical ` and {ref}`horizontal filtering `, limiting or elevated permissions (`read:` or `admin:`, respectively), and metascopes. +**Resolving scopes** involves expanding scopes into all their possible subscopes (_expanded scopes_), parsing them into the format used for access evaluation (_parsed scopes_) and, if applicable, comparing two sets of scopes (_intersection_). All procedures take into account the scope hierarchy, {ref}`vertical ` and {ref}`horizontal filtering `, limiting or elevated permissions (`read:` or `admin:`, respectively), and metascopes. -Roles and scopes are resolved on several occasions, for example when requesting an API token with specific scopes 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 scopes or when making an API request. The following sections provide more details. (requesting-api-token-target)= @@ -43,26 +43,25 @@ Prior to 3.0, tokens stored _roles_, which meant their scopes were resolved on each request. ::: -API tokens grant access to JupyterHub's APIs. The RBAC framework allows for requesting tokens with specific permissions. +API tokens grant access to JupyterHub's APIs. The Role Based Access Control (RBAC) framework allows for the requesting of tokens with specific permissions. RBAC is involved in several stages of the OAuth token flow. When requesting a token via the tokens API (`/users/:name/tokens`), or the token page (`/hub/token`), if no scopes are requested, the token is issued with the permissions stored on the default `token` role -(providing the requester is allowed to create the token). +(provided the requester is allowed to create the token). OAuth tokens are also requested via OAuth flow If the token is requested with any scopes, the permissions of requesting entity are checked against the requested permissions to ensure the token would not grant its owner additional privileges. -If, due to modifications of permissions of the token or token owner, -at API request time a token has any scopes that its owner does not, -those scopes are removed. +If a token has any scopes that its owner does not possess +at the time of making the API request, those scopes are removed. The API request is resolved without additional errors using the scope _intersection_; the Hub logs a warning in this case (see {ref}`Figure 2 `). -Resolving a token's scope (yellow box in {ref}`Figure 1 `) corresponds to resolving all the token's owner roles (including the roles associated with their groups) and the token's own scopes into a set of scopes. The two sets are compared (Resolve the scopes box in orange in {ref}`Figure 1 `), taking into account the scope hierarchy. -If the token's scopes are a subset of the token owner's scopes, the token is issued with the requested scopes; if not, JupyterHub will raise an error. +Resolving a token's scope (yellow box in {ref}`Figure 1 `) corresponds to resolving all the roles of the token's owner (including the roles associated with their groups) and the token's own scopes into a set of scopes. The two sets are compared (Resolve the scopes box in orange in {ref}`Figure 1 `), taking into account the scope hierarchy. +If the token's scopes are a subset of the token owner's scopes, the token is issued with the requested scopes; if not, JupyterHub will throw an error. {ref}`Figure 1 ` below illustrates the steps involved. The orange rectangles highlight where in the process the roles and scopes are resolved. @@ -75,10 +74,10 @@ Figure 1. Resolving roles and scopes during API token request ### Making an 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 in order to gain the access to the API. -When an API request is performed, the requesting API token's scopes are again intersected with its owner's (yellow box in {ref}`Figure 2 `) 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 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 used. For example, using a token with scope `users` whose owner's role scope is `read:users:name` will result in only the `read:users:name` scope being passed on. In the case of no _intersection_, an empty set of scopes will be used. +When an API request is made, the requesting API token's scopes are again intersected with its owner's (yellow box in {ref}`Figure 2 `) to ensure that the token does not grant more permissions than its owner has at the request time (e.g., due to changing/losing roles). +If the owner's roles do not include some scopes of the token, only the _intersection_ of the token's and owner's scopes will be used. For example, using a token with scope `users` whose owner's role scope is `read:users:name` will result in only the `read:users:name` scope being passed on. In the case of no _intersection_, an empty set of scopes will be used. The passed scopes are compared to the scopes required to access the API as follows: @@ -86,7 +85,7 @@ The passed scopes are compared to the scopes required to access the API as follo - 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 ` 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 found, the RBAC framework employs the {ref}`filtering ` 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 From fc6d93bbe37209f796bc15a344cfb62a078400c8 Mon Sep 17 00:00:00 2001 From: Christian Dike Date: Mon, 17 Oct 2022 13:20:02 +0100 Subject: [PATCH 2/3] Update docs/source/rbac/tech-implementation.md Replace URLs with internal markdown link Co-authored-by: Min RK --- docs/source/rbac/tech-implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/rbac/tech-implementation.md b/docs/source/rbac/tech-implementation.md index b3084ed5..2a8561ca 100644 --- a/docs/source/rbac/tech-implementation.md +++ b/docs/source/rbac/tech-implementation.md @@ -1,6 +1,6 @@ # Technical Implementation -[Roles](https://jupyterhub.readthedocs.io/en/stable/rbac/roles.html#roles) are stored in the database, where they are associated with users, services, groups and tokens. Roles can be added or modified as explained in the {ref}`define-role-target` section. Users, services, groups, and tokens can gain, change, and lose roles. This is currently achieved via `jupyterhub_config.py` (see {ref}`define-role-target`) and will be made available via API in the future. The latter will allow for changing a token's role, and thereby its permissions, without the need to issue a new token. +[Roles](roles) are stored in the database, where they are associated with users, services, and groups. Roles can be added or modified as explained in the {ref}`define-role-target` section. Users, services, groups, and tokens can gain, change, and lose roles. This is currently achieved via `jupyterhub_config.py` (see {ref}`define-role-target`) and will be made available via API in the future. The latter will allow for changing a user's role, and thereby its permissions, without the need to restart JupyterHub. Roles and scopes utilities can be found in `roles.py` and `scopes.py` modules. Scope variables take on five different formats that are reflected throughout the utilities via specific nomenclature: From e7a325ed248796eab72874d0a3789bfaaa7b1aa7 Mon Sep 17 00:00:00 2001 From: Christian Dike Date: Mon, 17 Oct 2022 13:20:37 +0100 Subject: [PATCH 3/3] Update docs/source/rbac/tech-implementation.md update text Co-authored-by: Min RK --- docs/source/rbac/tech-implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/rbac/tech-implementation.md b/docs/source/rbac/tech-implementation.md index 2a8561ca..93558791 100644 --- a/docs/source/rbac/tech-implementation.md +++ b/docs/source/rbac/tech-implementation.md @@ -61,7 +61,7 @@ The API request is resolved without additional errors using the scope _intersect the Hub logs a warning in this case (see {ref}`Figure 2 `). Resolving a token's scope (yellow box in {ref}`Figure 1 `) corresponds to resolving all the roles of the token's owner (including the roles associated with their groups) and the token's own scopes into a set of scopes. The two sets are compared (Resolve the scopes box in orange in {ref}`Figure 1 `), taking into account the scope hierarchy. -If the token's scopes are a subset of the token owner's scopes, the token is issued with the requested scopes; if not, JupyterHub will throw an error. +If the token's scopes are a subset of the token owner's scopes, the token is issued with the requested scopes; if not, JupyterHub will raise an error. {ref}`Figure 1 ` below illustrates the steps involved. The orange rectangles highlight where in the process the roles and scopes are resolved.