mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 07:23:00 +00:00
Merge pull request #3476 from IvanaH8/rbac-scope-table-makefile
[rbac] Generate scope table for docs
This commit is contained in:
@@ -66,7 +66,12 @@ metrics: source/reference/metrics.rst
|
||||
source/reference/metrics.rst: generate-metrics.py
|
||||
python3 generate-metrics.py
|
||||
|
||||
html: rest-api metrics
|
||||
scopes: source/rbac/scope-table.md
|
||||
|
||||
source/rbac/scope-table.md: source/rbac/generate-scope-table.py
|
||||
python3 source/rbac/generate-scope-table.py
|
||||
|
||||
html: rest-api metrics scopes
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
@@ -212,7 +212,7 @@ if on_rtd:
|
||||
# build both metrics and rest-api, since RTD doesn't run make
|
||||
from subprocess import check_call as sh
|
||||
|
||||
sh(['make', 'metrics', 'rest-api'], cwd=docs)
|
||||
sh(['make', 'metrics', 'rest-api', 'scopes'], cwd=docs)
|
||||
|
||||
# -- Spell checking -------------------------------------------------------
|
||||
|
||||
|
99
docs/source/rbac/generate-scope-table.py
Normal file
99
docs/source/rbac/generate-scope-table.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
from pytablewriter import MarkdownTableWriter
|
||||
|
||||
from jupyterhub.scopes import scope_definitions
|
||||
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class ScopeTableGenerator:
|
||||
def __init__(self):
|
||||
self.scopes = scope_definitions
|
||||
|
||||
@classmethod
|
||||
def create_writer(cls, table_name, headers, values):
|
||||
writer = MarkdownTableWriter()
|
||||
writer.table_name = table_name
|
||||
writer.headers = headers
|
||||
writer.value_matrix = values
|
||||
writer.margin = 1
|
||||
return writer
|
||||
|
||||
def _get_scope_relationships(self):
|
||||
"""Returns a tuple of dictionary of all scope-subscope pairs and a list of just subscopes:
|
||||
|
||||
({scope: subscope}, [subscopes])
|
||||
|
||||
used for creating hierarchical scope table in _parse_scopes()
|
||||
"""
|
||||
pairs = []
|
||||
for scope in self.scopes.keys():
|
||||
if self.scopes[scope].get('subscopes'):
|
||||
for subscope in self.scopes[scope]['subscopes']:
|
||||
pairs.append((scope, subscope))
|
||||
else:
|
||||
pairs.append((scope, None))
|
||||
subscopes = [pair[1] for pair in pairs]
|
||||
pairs_dict = defaultdict(list)
|
||||
for scope, subscope in pairs:
|
||||
pairs_dict[scope].append(subscope)
|
||||
return pairs_dict, subscopes
|
||||
|
||||
def _get_top_scopes(self, subscopes):
|
||||
"""Returns a list of highest level scopes
|
||||
(not a subscope of any other scopes)"""
|
||||
top_scopes = []
|
||||
for scope in self.scopes.keys():
|
||||
if scope not in subscopes:
|
||||
top_scopes.append(scope)
|
||||
return top_scopes
|
||||
|
||||
def _parse_scopes(self):
|
||||
"""Returns a list of table rows where row:
|
||||
[indented scopename string, scope description string]"""
|
||||
scope_pairs, subscopes = self._get_scope_relationships()
|
||||
top_scopes = self._get_top_scopes(subscopes)
|
||||
|
||||
table_rows = []
|
||||
md_indent = " "
|
||||
|
||||
def _add_subscopes(table_rows, scopename, depth=0):
|
||||
description = self.scopes[scopename]['description']
|
||||
table_row = [f"{md_indent*depth}`{scopename}`", description]
|
||||
table_rows.append(table_row)
|
||||
for subscope in scope_pairs[scopename]:
|
||||
if subscope:
|
||||
_add_subscopes(table_rows, subscope, depth + 1)
|
||||
|
||||
for scope in top_scopes:
|
||||
_add_subscopes(table_rows, scope)
|
||||
|
||||
return table_rows
|
||||
|
||||
def write_table(self):
|
||||
"""Generates the scope table in markdown format and writes it into scope-table.md file"""
|
||||
filename = f"{HERE}/scope-table.md"
|
||||
table_name = ""
|
||||
headers = ["Scope", "Description"]
|
||||
values = self._parse_scopes()
|
||||
writer = self.create_writer(table_name, headers, values)
|
||||
|
||||
title = "Table 1. Available scopes and their hierarchy"
|
||||
content = f"{title}\n{writer.dumps()}"
|
||||
with open(filename, 'w') as f:
|
||||
f.write(content)
|
||||
print(f"Generated {filename}.")
|
||||
print(
|
||||
"Run 'make clean' before 'make html' to ensure the built scopes.html contains latest scope table changes."
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
table_generator = ScopeTableGenerator()
|
||||
table_generator.write_table()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -81,37 +81,10 @@ The payload of an API call can be filtered both horizontally and vertically simu
|
||||
## Available scopes
|
||||
|
||||
Table below lists all available scopes and illustrates their hierarchy. Indented scopes indicate subscopes of the scope(s) above them.
|
||||
% TODO: Automatically generate this table from code when creating docs
|
||||
Table 1. Available scopes and their hierarchy
|
||||
| Scope name | Description |
|
||||
| :--------- | :---------- |
|
||||
| (no scope) | Allows for only identifying the owning entity. |
|
||||
| `self` | Metascope, grants access to user's own resources; resolves to (no scope) for services. |
|
||||
| `all` | Metascope, valid for tokens only. Grants access to everything that the token's owning entity can do. |
|
||||
| `admin:users` | Grants read, write, create and delete access to users and their authentication state _but not their servers or tokens._ |
|
||||
| `admin:users:auth_state` | Grants access to users' authentication state only. |
|
||||
| `users` | Grants read and write permissions to users' models _apart from servers, tokens and authentication state_. |
|
||||
| `users:activity` | Grants access to read and post users' activity only. |
|
||||
| `read:users` | Read-only access to users' models _apart from servers, tokens and authentication state_. |
|
||||
| `read:users:name` | Read-only access to users' names. |
|
||||
| `read:users:roles` | Read-only access to a list of users' roles names. |
|
||||
| `read:users:groups` | Read-only access to a list of users' group names. |
|
||||
| `read:users:activity` | Read-only access to users' activity. |
|
||||
| `admin:users:servers` | Grants read, start/stop, create and delete permissions to users' servers and their state. |
|
||||
| `admin:users:server_state` | Grants access to servers' state only. |
|
||||
| `users:servers` | Allows for starting/stopping users' servers in addition to read access to their models. _Does not include the server state_. |
|
||||
| `read:users:servers` | Read-only access to users' server models. _Does not include the server state_. |
|
||||
| `users:tokens` | Grants read, write, create and delete permissions to users' tokens. |
|
||||
| `read:users:tokens` | Read-only access to users' tokens. |
|
||||
| `admin:groups` | Grants read, write, create and delete access to groups. |
|
||||
| `groups` | Grants read and write permissions to groups, including adding/removing users to/from groups. |
|
||||
| `read:groups` | Read-only access to groups. |
|
||||
| `read:services` | Read-only access to service models. |
|
||||
| `read:services:name` | Read-only access to service names. |
|
||||
| `read:services:roles` | Read-only access to a list of service roles names. |
|
||||
| `read:hub` | Read-only access to detailed information about the Hub. |
|
||||
| `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. |
|
||||
| `shutdown` | Grants access to shutdown the hub. |
|
||||
|
||||
```{include} scope-table.md
|
||||
|
||||
```
|
||||
|
||||
```{Caution}
|
||||
Note that only the {ref}`horizontal filtering <horizontal-filtering-target>` can be added to scopes to customize them. \
|
||||
|
@@ -11,6 +11,87 @@ from . import orm
|
||||
from . import roles
|
||||
|
||||
|
||||
scope_definitions = {
|
||||
'(no_scope)': {'description': 'Allows for only identifying the owning entity.'},
|
||||
'self': {
|
||||
'description': 'Metascope, grants access to user’s own resources only; resolves to (no_scope) for services.'
|
||||
},
|
||||
'all': {
|
||||
'description': 'Metascope, valid for tokens only. Grants access to everything that the token’s owning entity can access.'
|
||||
},
|
||||
'admin:users': {
|
||||
'description': 'Grants read, write, create and delete access to users and their authentication state but not their servers or tokens.',
|
||||
'subscopes': ['admin:users:auth_state', 'users'],
|
||||
},
|
||||
'admin:users:auth_state': {
|
||||
'description': 'Grants access to users’ authentication state only.'
|
||||
},
|
||||
'users': {
|
||||
'description': 'Grants read and write permissions to users’ models apart from servers, tokens and authentication state.',
|
||||
'subscopes': ['read:users', 'users:activity'],
|
||||
},
|
||||
'read:users': {
|
||||
'description': 'Read-only access to users’ models apart from servers, tokens and authentication state.',
|
||||
'subscopes': [
|
||||
'read:users:name',
|
||||
'read:users:groups',
|
||||
'read:users:activity',
|
||||
'read:users:roles',
|
||||
],
|
||||
},
|
||||
'read:users:name': {'description': 'Read-only access to users’ names.'},
|
||||
'read:users:groups': {'description': 'Read-only access to users’ group names.'},
|
||||
'read:users:roles': {'description': 'Read-only access to users’ role names.'},
|
||||
'read:users:activity': {'description': 'Read-only access to users’ last activity.'},
|
||||
'users:activity': {
|
||||
'description': 'Grants access to read and post users’ last activity only.',
|
||||
'subscopes': ['read:users:activity'],
|
||||
},
|
||||
'admin:users:servers': {
|
||||
'description': 'Grants read, start/stop, create and delete permissions to users’ servers and their state.',
|
||||
'subscopes': ['admin:users:server_state', 'users:servers'],
|
||||
},
|
||||
'admin:users:server_state': {
|
||||
'description': 'Grants access to servers’ state only.'
|
||||
},
|
||||
'users:servers': {
|
||||
'description': 'Allows for starting/stopping users’ servers in addition to read access to their models. Does not include the server state.',
|
||||
'subscopes': ['read:users:servers'],
|
||||
},
|
||||
'read:users:servers': {
|
||||
'description': 'Read-only access to users’ names and their server models. Does not include the server state.',
|
||||
'subscopes': ['read:users:name'],
|
||||
},
|
||||
'users:tokens': {
|
||||
'description': 'Grants read, write, create and delete permissions to users’ tokens.',
|
||||
'subscopes': ['read:users:tokens'],
|
||||
},
|
||||
'read:users:tokens': {'description': 'Read-only access to users’ tokens.'},
|
||||
'admin:groups': {
|
||||
'description': 'Grants read, write, create and delete access to groups.',
|
||||
'subscopes': ['groups'],
|
||||
},
|
||||
'groups': {
|
||||
'description': 'Grants read and write permissions to groups, including adding/removing users to/from groups.',
|
||||
'subscopes': ['read:groups'],
|
||||
},
|
||||
'read:groups': {'description': 'Read-only access to groups’ models.'},
|
||||
'read:services': {
|
||||
'description': 'Read-only access to service models.',
|
||||
'subscopes': ['read:services:name', 'read:services:roles'],
|
||||
},
|
||||
'read:services:name': {'description': 'Read-only access to service names.'},
|
||||
'read:services:roles': {'description': 'Read-only access to service role names.'},
|
||||
'read:hub': {
|
||||
'description': 'Read-only access to detailed information about the Hub.'
|
||||
},
|
||||
'proxy': {
|
||||
'description': 'Allows for obtaining information about the proxy’s routing table, for syncing the Hub with proxy and notifying the Hub about a new proxy.'
|
||||
},
|
||||
'shutdown': {'description': 'Grants access to shutdown the hub.'},
|
||||
}
|
||||
|
||||
|
||||
class Scope(Enum):
|
||||
ALL = True
|
||||
|
||||
|
Reference in New Issue
Block a user