Roles#
JupyterHub provides four (4) roles that are available by default:
Default roles
userrole provides a default user scopeselfthat grants access to the user’s own resources.adminrole contains all available scopes and grants full rights to all actions. This role cannot be edited.tokenrole provides a default token scopeinheritthat resolves to the same permissions as the owner of the token has.serverrole allows for posting activity of “itself” only.
These roles cannot be deleted.
We call these ‘default’ roles because they are available by default and have a default collection of scopes. However, you can define the scopes associated with each role (excluding the admin role) to suit your needs, as seen below.
The user, admin, and token roles, by default, all preserve the permissions prior to Role-based Access Control (RBAC).
Only the server role is changed from pre-2.0, to reduce its permissions to activity-only
instead of the default of a full access token.
Additional custom roles can also be defined (see Defining Roles). Roles can be assigned to the following entities:
Users
Services
Groups
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.
Users
When a new user gets created, they are assigned their default role, user. Additionally, if the user is created with admin privileges (via c.Authenticator.admin_users in jupyterhub_config.py or admin: true via API), they will be also granted admin role. If existing user’s admin status changes via API or jupyterhub_config.py, their default role will be updated accordingly (after next startup for the latter).
Services
Services do not have a default role. Services without roles have no access to the guarded API end-points. So, most services will require assignment of a role in order to function.
Groups
A group does not require any role, and has no roles by default. If a user is a member of a group, they automatically inherit any of the group’s permissions (see Resolving roles and scopes for more details). This is useful for assigning a set of common permissions to several users.
Tokens
A token’s 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 scopes are requested for a new token, the token is assigned the scopes of the token role.
Defining Roles#
Roles can be defined or modified in the configuration file as a list of dictionaries. An example:
# in jupyterhub_config.py
c.JupyterHub.load_roles = [
{
'name': 'server-rights',
'description': 'Allows parties to start and stop user servers',
'scopes': ['servers'],
'users': ['alice', 'bob'],
'services': ['idle-culler'],
'groups': ['admin-group'],
}
]
The role server-rights now allows the starting and stopping of servers by any of the following:
users
aliceandbobthe service
idle-cullerany member of the
admin-group.
Attention
Tokens cannot be assigned roles through role definition but may be assigned specific roles when requested via API (see Requesting API token with specific scopes).
Another example:
# in jupyterhub_config.py
c.JupyterHub.load_roles = [
{
'description': 'Read-only user models',
'name': 'reader',
'scopes': ['read:users'],
'services': ['external'],
'users': ['maria', 'joe']
}
]
The role reader allows users maria and joe and service external to read (but not modify) any user’s model.
Requirements
In a role definition, the name field is required, while all other fields are optional.
Role names must:
be 3 - 255 characters
use ascii lowercase, numbers, ‘unreserved’ URL punctuation
-_.~start with a letter
end with letter or number.
users, services, and groups only accept objects that already exist in the database 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.
If no scopes are defined for new role, JupyterHub will raise a warning. Providing non-existing scopes will result in an error.
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. All the role bearers permissions present in the definition will change accordingly.
Overriding Default Roles#
Role definitions can include those of the “default” roles listed above (admin excluded), if the default scopes associated with those roles do not suit your deployment.
For example, to specify what permissions the $JUPYTERHUB_API_TOKEN issued to all single-user servers
has, you may define the server role.
However, starting with JupyterHub 4, it is recommended to use the Spawner.server_token_scopes option for this instead.
To restore the JupyterHub 1.x behavior of servers being able to do anything their owners can do,
use the scope inherit (for ‘inheriting’ the owner’s permissions):
c.JupyterHub.server_token_scopes = {"inherit"}
or, better yet, identify the specific scopes you want server environments to have access to.
If you choose to restrict the server token, the one required scope for the server token users:activity!user will be added automatically.
If you don’t want to get too detailed, one option is the self scope,
which will restrict the token issued to admin user servers to only have access to their own resources,
instead of being able to take actions on behalf of all other users.
c.JupyterHub.server_token_scopes = {"self"}
You can also override the default user role, to add or remove permissions from all jupyterhub users by defining the user role.
By default, the user role has only the self scope, allowing accessing and managing the user’s own server:
c.JupyterHub.load_roles = [
{
"name": "user",
"scopes": [
"self",
],
}
]
If you override the user role, you can restrict user permissions to less than this, e.g.
c.JupyterHub.load_roles = [
{
"name": "user",
"scopes": [
"access:servers!user",
"users:activity!user",
],
}
]
which will allow users to access their own servers, but not start them (maybe you have some other mechanism you control for starting servers).
If you want to add to default user permissions, make sure to include the self scope, otherwise you might find yourself restricting users unintentionally.
Starting with JupyterHub 6, there is now JupyterHub.extra_user_scopes option,
which only adds to the default user scopes, so you don’t need to override the default role with load_roles if expanding permissions is your goal.
For example, to grant access to any JupyterHub service:
c.JupyterHub.extra_user_scopes = {"access:services"}
which adds the access:services scope to all users without overriding the default scopes in the user role.
This is equivalent (in JupyterHub 6.0) to:
c.JupyterHub.load_roles = [
{
"name": "user",
"scopes": [
"self",
"access:services",
],
}
]
but if a future JupyterHub release ever changes the default user role, the extra_user_scopes approach will continue to add access:services to the default, whatever the default may be,
whereas the overridden user role will continue to have exactly the permissions defined in your configuration, no matter what the default changes to.
You cannot define scopes for the user role using extra_user_scopes and load_roles at the same time (there would be no reason to).
If your config has both:
c.JupyterHub.extra_user_scopes = {"access:services"}
c.JupyterHub.load_roles = [
{
"name": "user",
"scopes": [
"self",
"access:servers!group=shared",
],
}
]
then extra_user_scopes will be ignored.
If you are defining user scopes via load_roles, then that is the only list of scopes that will be considered.
Removing Roles#
Only the entities present in the role definition in the jupyterhub_config.py remain the role bearers. If a user, service or group is removed from the role definition, they will lose the role on the next startup.
Once a role is loaded, it remains in the database until removing it from the jupyterhub_config.py and restarting the Hub. All previously defined role bearers will lose the role and associated permissions. Default roles, even if previously redefined through the config file and removed, will not be deleted from the database.