mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-09 02:54:09 +00:00
Generate REST API scope descriptions from source code
This commit is contained in:
@@ -17,40 +17,53 @@ securityDefinitions:
|
|||||||
flow: accessCode
|
flow: accessCode
|
||||||
authorizationUrl: "/hub/api/oauth2/authorize" # what are the absolute URIs here? is oauth2 correct here or shall we use just authorizations?
|
authorizationUrl: "/hub/api/oauth2/authorize" # what are the absolute URIs here? is oauth2 correct here or shall we use just authorizations?
|
||||||
tokenUrl: "/hub/api/oauth2/token"
|
tokenUrl: "/hub/api/oauth2/token"
|
||||||
scopes: # Todo: Generate based on scope table
|
scopes: # Generated based on scope table in jupyterhub/scopes.py
|
||||||
(noscope): Allows only to identify the requesting entity
|
(no_scope): Identify the owner of the requesting entity.
|
||||||
self: Metascope, grants access to user's own resources; resolves to (no scope) for services.
|
self:
|
||||||
all: Metascope, valid for tokens only. Grants access to all resources of the token-owning entity.
|
The user’s own resources _(metascope for users, resolves to (no_scope)
|
||||||
admin:users: Grants read, write, create and delete access to users and their authentication state but not their servers or tokens.
|
for services)_
|
||||||
admin:auth_state: Grants access to users' authentication state only.
|
all: Everything that the token-owning entity can access _(metascope for tokens)_
|
||||||
users: Grants read and write permissions to users' models apart from servers, tokens and authentication state.
|
admin:users:
|
||||||
users:activity: Grants access to read and post users' activity only.
|
Read, write, create and delete users and their authentication state,
|
||||||
users:activity!user=username: Update a single user's activity (example horizontal filter).
|
not including their servers or tokens.
|
||||||
read:users: Read-only access to users' models apart from servers, tokens and authentication state.
|
admin:auth_state: Read a user’s authentication state.
|
||||||
read:users!user=username: As above limited to a specific user (example horizontal filter).
|
users:
|
||||||
read:users:name: Read-only access to user names.
|
Read and write permissions to user models (excluding servers, tokens
|
||||||
read:roles:users: Read-only access to user role assignments.
|
and authentication state).
|
||||||
read:users:groups: Read-only access to a list of users' group names.
|
read:users:
|
||||||
read:users:activity: Read-only access to users' activity.
|
Read user models (excluding including servers, tokens and authentication
|
||||||
read:users:activity!group=groupname: Read-only access to specific group's users' activity (example horizontal filter).
|
state).
|
||||||
admin:servers: Grants read, start/stop, create and delete permissions to users' servers and their state.
|
read:users:name: Read names of users.
|
||||||
admin:server_state: Grants access to servers' state only.
|
read:users:groups: Read users’ group membership.
|
||||||
servers: Allows for starting/stopping users' servers in addition to read access to their models. Does not include the server state.
|
read:users:activity: Read time of last user activity.
|
||||||
servers!server=servername: Limits the above to a specific server (example horizontal filter).
|
read:roles: Read role assignments.
|
||||||
read:servers: Read-only access to users' server models. Does not include the server state.
|
read:roles:users: Read user role assignments.
|
||||||
tokens: Grants read, write, create and delete permissions to users' tokens.
|
read:roles:services: Read service role assignments.
|
||||||
read:tokens: Read-only access to users' tokens.
|
read:roles:groups: Read group role assignments.
|
||||||
admin:groups: Grants read, write, create and delete access to groups.
|
users:activity: Update time of last user activity.
|
||||||
groups: Grants read and write permissions to groups, including adding/removing users to/from groups.
|
admin:servers: Read, start, stop, create and delete user servers and their state.
|
||||||
read:roles:groups: Read-only access to group roles assignments
|
admin:server_state: Read and write users’ server state.
|
||||||
groups!group=groupname: As above limited to a specific group only (example horizontal filter)
|
servers: Start and stop user servers.
|
||||||
read:groups: Read-only access to groups.
|
read:servers:
|
||||||
read:services: Read-only access to service models.
|
Read users’ names and their server models (excluding the server
|
||||||
read:services:name: Read-only access to service names.
|
state).
|
||||||
read:roles:services: Read-only access to a list of service roles names.
|
tokens: Read, write, create and delete user tokens.
|
||||||
read:hub: Read-only access to detailed information about JupyterHub.
|
read:tokens: Read user tokens.
|
||||||
proxy: Allows for obtaining information about the proxy's routing table, for syncing the Hub with proxy and notifying the Hub about a new proxy.
|
admin:groups: Read and write group information, create and delete groups.
|
||||||
shutdown: Grants access to shutdown the Hub.
|
groups:
|
||||||
|
Read and write group information, including adding/removing users to/from
|
||||||
|
groups.
|
||||||
|
read:groups: Read group models.
|
||||||
|
read:groups:name: Read group names.
|
||||||
|
read:services: Read service models.
|
||||||
|
read:services:name: Read service names.
|
||||||
|
read:hub: Read detailed information about the Hub.
|
||||||
|
access:servers: Access user servers via API or browser.
|
||||||
|
access:services: Access services via API or browser.
|
||||||
|
proxy:
|
||||||
|
Read information about the proxy’s routing table, sync the Hub with the
|
||||||
|
proxy and notify the Hub about a new proxy.
|
||||||
|
shutdown: Shutdown the hub.
|
||||||
security: # global security, do we want to keep only the apiKey (token: []), change to only oauth2 (with scope self) or have both (either can be used)?
|
security: # global security, do we want to keep only the apiKey (token: []), change to only oauth2 (with scope self) or have both (either can be used)?
|
||||||
- token: []
|
- token: []
|
||||||
- oauth2:
|
- oauth2:
|
||||||
@@ -106,7 +119,9 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
class:
|
class:
|
||||||
type: string
|
type: string
|
||||||
description: The Python class currently active for JupyterHub Authentication
|
description:
|
||||||
|
The Python class currently active for JupyterHub
|
||||||
|
Authentication
|
||||||
version:
|
version:
|
||||||
type: string
|
type: string
|
||||||
description: The version of the currently active Authenticator
|
description: The version of the currently active Authenticator
|
||||||
@@ -115,7 +130,9 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
class:
|
class:
|
||||||
type: string
|
type: string
|
||||||
description: The Python class currently active for spawning single-user notebook servers
|
description:
|
||||||
|
The Python class currently active for spawning single-user
|
||||||
|
notebook servers
|
||||||
version:
|
version:
|
||||||
type: string
|
type: string
|
||||||
description: The version of the currently active Spawner
|
description: The version of the currently active Spawner
|
||||||
@@ -253,16 +270,22 @@ paths:
|
|||||||
- name: body
|
- name: body
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
description: Updated user info. At least one key to be updated (name or admin) is required.
|
description:
|
||||||
|
Updated user info. At least one key to be updated (name or admin)
|
||||||
|
is required.
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
description: the new name (optional, if another key is updated i.e. admin)
|
description:
|
||||||
|
the new name (optional, if another key is updated i.e.
|
||||||
|
admin)
|
||||||
admin:
|
admin:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: update admin (optional, if another key is updated i.e. name)
|
description:
|
||||||
|
update admin (optional, if another key is updated i.e.
|
||||||
|
name)
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: The updated user info
|
description: The updated user info
|
||||||
@@ -285,9 +308,9 @@ paths:
|
|||||||
/users/{name}/activity:
|
/users/{name}/activity:
|
||||||
post:
|
post:
|
||||||
summary: Notify Hub of activity for a given user.
|
summary: Notify Hub of activity for a given user.
|
||||||
description: Notify the Hub of activity by the user,
|
description:
|
||||||
e.g. accessing a service or (more likely)
|
Notify the Hub of activity by the user, e.g. accessing a service
|
||||||
actively using a server.
|
or (more likely) actively using a server.
|
||||||
security:
|
security:
|
||||||
- oauth2:
|
- oauth2:
|
||||||
- users:activity
|
- users:activity
|
||||||
@@ -369,7 +392,9 @@ paths:
|
|||||||
"201":
|
"201":
|
||||||
description: The user's notebook server has started
|
description: The user's notebook server has started
|
||||||
"202":
|
"202":
|
||||||
description: The user's notebook server has not yet started, but has been requested
|
description:
|
||||||
|
The user's notebook server has not yet started, but has been
|
||||||
|
requested
|
||||||
delete:
|
delete:
|
||||||
summary: Stop a user's server
|
summary: Stop a user's server
|
||||||
security:
|
security:
|
||||||
@@ -385,7 +410,9 @@ paths:
|
|||||||
"204":
|
"204":
|
||||||
description: The user's notebook server has stopped
|
description: The user's notebook server has stopped
|
||||||
"202":
|
"202":
|
||||||
description: The user's notebook server has not yet stopped as it is taking a while to stop
|
description:
|
||||||
|
The user's notebook server has not yet stopped as it is taking
|
||||||
|
a while to stop
|
||||||
/users/{name}/servers/{server_name}:
|
/users/{name}/servers/{server_name}:
|
||||||
post:
|
post:
|
||||||
summary: Start a user's single-user named-server notebook server
|
summary: Start a user's single-user named-server notebook server
|
||||||
@@ -420,7 +447,9 @@ paths:
|
|||||||
"201":
|
"201":
|
||||||
description: The user's notebook named-server has started
|
description: The user's notebook named-server has started
|
||||||
"202":
|
"202":
|
||||||
description: The user's notebook named-server has not yet started, but has been requested
|
description:
|
||||||
|
The user's notebook named-server has not yet started, but has
|
||||||
|
been requested
|
||||||
delete:
|
delete:
|
||||||
summary: Stop a user's named-server
|
summary: Stop a user's named-server
|
||||||
security:
|
security:
|
||||||
@@ -453,7 +482,9 @@ paths:
|
|||||||
"204":
|
"204":
|
||||||
description: The user's notebook named-server has stopped
|
description: The user's notebook named-server has stopped
|
||||||
"202":
|
"202":
|
||||||
description: The user's notebook named-server has not yet stopped as it is taking a while to stop
|
description:
|
||||||
|
The user's notebook named-server has not yet stopped as it
|
||||||
|
is taking a while to stop
|
||||||
/users/{name}/tokens:
|
/users/{name}/tokens:
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
@@ -491,7 +522,9 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
expires_in:
|
expires_in:
|
||||||
type: number
|
type: number
|
||||||
description: lifetime (in seconds) after which the requested token will expire.
|
description:
|
||||||
|
lifetime (in seconds) after which the requested token will
|
||||||
|
expire.
|
||||||
note:
|
note:
|
||||||
type: string
|
type: string
|
||||||
description: A note attached to the token for future bookkeeping
|
description: A note attached to the token for future bookkeeping
|
||||||
@@ -712,9 +745,7 @@ paths:
|
|||||||
summary: Get a service by name
|
summary: Get a service by name
|
||||||
security:
|
security:
|
||||||
- oauth2:
|
- oauth2:
|
||||||
- read:services
|
- read:services - read:services:name - read:roles:services
|
||||||
- read:services:name
|
|
||||||
- read:roles:services
|
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: service name
|
description: service name
|
||||||
@@ -729,7 +760,9 @@ paths:
|
|||||||
/proxy:
|
/proxy:
|
||||||
get:
|
get:
|
||||||
summary: Get the proxy's routing table
|
summary: Get the proxy's routing table
|
||||||
description: A convenience alias for getting the routing table directly from the proxy
|
description:
|
||||||
|
A convenience alias for getting the routing table directly from
|
||||||
|
the proxy
|
||||||
security:
|
security:
|
||||||
- oauth2:
|
- oauth2:
|
||||||
- proxy
|
- proxy
|
||||||
@@ -755,7 +788,9 @@ paths:
|
|||||||
description: Routing table
|
description: Routing table
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
description: configurable-http-proxy routing table (see configurable-http-proxy docs for details)
|
description:
|
||||||
|
configurable-http-proxy routing table (see configurable-http-proxy
|
||||||
|
docs for details)
|
||||||
post:
|
post:
|
||||||
summary: Force the Hub to sync with the proxy
|
summary: Force the Hub to sync with the proxy
|
||||||
security:
|
security:
|
||||||
@@ -774,7 +809,9 @@ paths:
|
|||||||
- name: body
|
- name: body
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
description: Any values that have changed for the new proxy. All keys are optional.
|
description:
|
||||||
|
Any values that have changed for the new proxy. All keys are
|
||||||
|
optional.
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -845,7 +882,9 @@ paths:
|
|||||||
/authorizations/cookie/{cookie_name}/{cookie_value}:
|
/authorizations/cookie/{cookie_name}/{cookie_value}:
|
||||||
get:
|
get:
|
||||||
summary: Identify a user from a cookie
|
summary: Identify a user from a cookie
|
||||||
description: Used by single-user notebook servers to hand off cookie authentication to the Hub
|
description:
|
||||||
|
Used by single-user notebook servers to hand off cookie authentication
|
||||||
|
to the Hub
|
||||||
parameters:
|
parameters:
|
||||||
- name: cookie_name
|
- name: cookie_name
|
||||||
in: path
|
in: path
|
||||||
@@ -955,10 +994,14 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
proxy:
|
proxy:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Whether the proxy should be shutdown as well (default from Hub config)
|
description:
|
||||||
|
Whether the proxy should be shutdown as well (default from
|
||||||
|
Hub config)
|
||||||
servers:
|
servers:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: Whether users' notebook servers should be shutdown as well (default from Hub config)
|
description:
|
||||||
|
Whether users' notebook servers should be shutdown as well
|
||||||
|
(default from Hub config)
|
||||||
responses:
|
responses:
|
||||||
"202":
|
"202":
|
||||||
description: Shutdown successful
|
description: Shutdown successful
|
||||||
@@ -1009,13 +1052,17 @@ definitions:
|
|||||||
auth_state:
|
auth_state:
|
||||||
type: string
|
type: string
|
||||||
#TODO: will there be predefined states? Should it rather be object instead of string?
|
#TODO: will there be predefined states? Should it rather be object instead of string?
|
||||||
description: Authentication state of the user. Only available with admin:users:auth_state scope. None otherwise.
|
description:
|
||||||
|
Authentication state of the user. Only available with admin:users:auth_state
|
||||||
|
scope. None otherwise.
|
||||||
Server:
|
Server:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
description: The server's name. The user's default server has an empty name ('')
|
description:
|
||||||
|
The server's name. The user's default server has an empty name
|
||||||
|
('')
|
||||||
ready:
|
ready:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
@@ -1046,10 +1093,15 @@ definitions:
|
|||||||
description: UTC timestamp last-seen activity on this server.
|
description: UTC timestamp last-seen activity on this server.
|
||||||
state:
|
state:
|
||||||
type: object
|
type: object
|
||||||
description: Arbitrary internal state from this server's spawner. Only available on the hub's users list or get-user-by-name method, and only with admin:users:server_state scope. None otherwise.
|
description:
|
||||||
|
Arbitrary internal state from this server's spawner. Only available
|
||||||
|
on the hub's users list or get-user-by-name method, and only with admin:users:server_state
|
||||||
|
scope. None otherwise.
|
||||||
user_options:
|
user_options:
|
||||||
type: object
|
type: object
|
||||||
description: User specified options for the user's spawned instance of a single-user server.
|
description:
|
||||||
|
User specified options for the user's spawned instance of a single-user
|
||||||
|
server.
|
||||||
Group:
|
Group:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1104,7 +1156,9 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
description: The token itself. Only present in responses to requests for a new token.
|
description:
|
||||||
|
The token itself. Only present in responses to requests for a
|
||||||
|
new token.
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
description: The id of the API token. Used for modifying or deleting the token.
|
description: The id of the API token. Used for modifying or deleting the token.
|
||||||
@@ -1121,7 +1175,9 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
note:
|
note:
|
||||||
type: string
|
type: string
|
||||||
description: A note about the token, typically describing what it was created for.
|
description:
|
||||||
|
A note about the token, typically describing what it was created
|
||||||
|
for.
|
||||||
created:
|
created:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
import os
|
import os
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from pytablewriter import MarkdownTableWriter
|
from pytablewriter import MarkdownTableWriter
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
from jupyterhub.scopes import scope_definitions
|
from jupyterhub.scopes import scope_definitions
|
||||||
|
|
||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
PARENT = Path(HERE).parent.parent.absolute()
|
||||||
|
|
||||||
|
|
||||||
class ScopeTableGenerator:
|
class ScopeTableGenerator:
|
||||||
@@ -76,7 +79,7 @@ class ScopeTableGenerator:
|
|||||||
return table_rows
|
return table_rows
|
||||||
|
|
||||||
def write_table(self):
|
def write_table(self):
|
||||||
"""Generates the scope table in markdown format and writes it into scope-table.md file"""
|
"""Generates the scope table in markdown format and writes it into `scope-table.md`"""
|
||||||
filename = f"{HERE}/scope-table.md"
|
filename = f"{HERE}/scope-table.md"
|
||||||
table_name = ""
|
table_name = ""
|
||||||
headers = ["Scope", "Grants permission to:"]
|
headers = ["Scope", "Grants permission to:"]
|
||||||
@@ -92,10 +95,30 @@ class ScopeTableGenerator:
|
|||||||
"Run 'make clean' before 'make html' to ensure the built scopes.html contains latest scope table changes."
|
"Run 'make clean' before 'make html' to ensure the built scopes.html contains latest scope table changes."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def write_api(self):
|
||||||
|
"""Generates the API description in markdown format and writes it into `rest-api.yml`"""
|
||||||
|
filename = f"{PARENT}/rest-api.yml"
|
||||||
|
yaml = YAML(typ='rt')
|
||||||
|
yaml.preserve_quotes = True
|
||||||
|
scope_dict = {}
|
||||||
|
with open(filename, 'r+') as f:
|
||||||
|
content = yaml.load(f.read())
|
||||||
|
f.seek(0)
|
||||||
|
for scope in self.scopes:
|
||||||
|
description = self.scopes[scope]['description']
|
||||||
|
doc_description = self.scopes[scope].get('doc_description', '')
|
||||||
|
if doc_description:
|
||||||
|
description = doc_description
|
||||||
|
scope_dict[scope] = description
|
||||||
|
content['securityDefinitions']['oauth2']['scopes'] = scope_dict
|
||||||
|
yaml.dump(content, f)
|
||||||
|
f.truncate()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
table_generator = ScopeTableGenerator()
|
table_generator = ScopeTableGenerator()
|
||||||
table_generator.write_table()
|
table_generator.write_table()
|
||||||
|
table_generator.write_api()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@@ -22,6 +22,8 @@ from tornado.log import app_log
|
|||||||
from . import orm
|
from . import orm
|
||||||
from . import roles
|
from . import roles
|
||||||
|
|
||||||
|
"""when modifying the scope definitions, make sure that `docs/source/rbac/generate-scope-table.py` is run
|
||||||
|
so that changes are reflected in the documentation and REST API description."""
|
||||||
scope_definitions = {
|
scope_definitions = {
|
||||||
'(no_scope)': {'description': 'Identify the owner of the requesting entity.'},
|
'(no_scope)': {'description': 'Identify the owner of the requesting entity.'},
|
||||||
'self': {
|
'self': {
|
||||||
|
Reference in New Issue
Block a user