Merge branch 'main' into doc-scopes-read-user

This commit is contained in:
Min RK
2025-02-19 09:03:56 +01:00
committed by GitHub
7 changed files with 161 additions and 118 deletions

2
.gitignore vendored
View File

@@ -7,8 +7,6 @@ node_modules
dist dist
docs/_build docs/_build
docs/build docs/build
docs/source/_static/rest-api
docs/source/rbac/scope-table.md
docs/source/reference/metrics.md docs/source/reference/metrics.md
.ipynb_checkpoints .ipynb_checkpoints

View File

@@ -33,7 +33,7 @@ repos:
rev: v4.0.0-alpha.8 rev: v4.0.0-alpha.8
hooks: hooks:
- id: prettier - id: prettier
exclude: .*/templates/.* exclude: .*/templates/.*|docs/source/_static/rest-api.yml|docs/source/rbac/scope-table.md
# autoformat HTML templates # autoformat HTML templates
- repo: https://github.com/djlint/djLint - repo: https://github.com/djlint/djLint
@@ -56,3 +56,16 @@ repos:
- id: requirements-txt-fixer - id: requirements-txt-fixer
- id: check-case-conflict - id: check-case-conflict
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
# source docs: rest-api.yml and scope-table.md are autogenerated
- repo: local
hooks:
- id: update-api-and-scope-docs
name: Update rest-api.yml and scope-table.md based on scopes.py
language: python
additional_dependencies: ["pytablewriter", "ruamel.yaml"]
entry: python docs/source/rbac/generate-scope-table.py
args:
- --update
files: jupyterhub/scopes.py
pass_filenames: false

View File

@@ -35,7 +35,7 @@ help:
# - NOTE: If the pre-requisites for the html target is updated, also update the # - NOTE: If the pre-requisites for the html target is updated, also update the
# Read The Docs section in docs/source/conf.py. # Read The Docs section in docs/source/conf.py.
# #
html: metrics scopes html: metrics
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) $(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS)
@echo @echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
@@ -44,10 +44,6 @@ metrics: source/reference/metrics.md
source/reference/metrics.md: source/reference/metrics.md:
python3 generate-metrics.py python3 generate-metrics.py
scopes: source/rbac/scope-table.md
source/rbac/scope-table.md:
python3 source/rbac/generate-scope-table.py
# Manually added targets - related to development # Manually added targets - related to development
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
@@ -56,7 +52,7 @@ source/rbac/scope-table.md:
# - requires sphinx-autobuild, see # - requires sphinx-autobuild, see
# https://sphinxcontrib-spelling.readthedocs.io/en/latest/ # https://sphinxcontrib-spelling.readthedocs.io/en/latest/
# - builds and rebuilds html on changes to source, but does not re-generate # - builds and rebuilds html on changes to source, but does not re-generate
# metrics/scopes files # metrics files
# - starts a livereload enabled webserver and opens up a browser # - starts a livereload enabled webserver and opens up a browser
devenv: html devenv: html
sphinx-autobuild -b html --open-browser "$(SOURCEDIR)" "$(BUILDDIR)/html" sphinx-autobuild -b html --open-browser "$(SOURCEDIR)" "$(BUILDDIR)/html"

View File

@@ -62,8 +62,7 @@ paths:
properties: properties:
class: class:
type: string type: string
description: description: The Python class currently active for JupyterHub
The Python class currently active for JupyterHub
Authentication Authentication
version: version:
type: string type: string
@@ -73,8 +72,7 @@ paths:
properties: properties:
class: class:
type: string type: string
description: description: The Python class currently active for spawning
The Python class currently active for spawning
single-user notebook servers single-user notebook servers
version: version:
type: string type: string
@@ -258,8 +256,7 @@ paths:
parameters: parameters:
- $ref: "#/components/parameters/userName" - $ref: "#/components/parameters/userName"
requestBody: requestBody:
description: description: Updated user info. At least one key to be updated (name or admin)
Updated user info. At least one key to be updated (name or admin)
is required. is required.
content: content:
application/json: application/json:
@@ -268,13 +265,11 @@ paths:
properties: properties:
name: name:
type: string type: string
description: description: the new name (optional, if another key is updated i.e.
the new name (optional, if another key is updated i.e.
admin) admin)
admin: admin:
type: boolean type: boolean
description: description: update admin (optional, if another key is updated i.e.
update admin (optional, if another key is updated i.e.
name) name)
required: true required: true
responses: responses:
@@ -291,8 +286,7 @@ paths:
post: post:
operationId: post-user-activity operationId: post-user-activity
summary: Notify Hub of activity for a given user summary: Notify Hub of activity for a given user
description: description: Notify the Hub of activity by the user, e.g. accessing a service
Notify the Hub of activity by the user, e.g. accessing a service
or (more likely) actively using a server. or (more likely) actively using a server.
parameters: parameters:
- $ref: "#/components/parameters/userName" - $ref: "#/components/parameters/userName"
@@ -372,8 +366,7 @@ paths:
description: The user's notebook server has started description: The user's notebook server has started
content: {} content: {}
202: 202:
description: description: The user's notebook server has not yet started, but has been
The user's notebook server has not yet started, but has been
requested requested
content: {} content: {}
security: security:
@@ -387,8 +380,7 @@ paths:
- $ref: "#/components/parameters/userName" - $ref: "#/components/parameters/userName"
responses: responses:
202: 202:
description: description: The user's notebook server has not yet stopped as it is taking
The user's notebook server has not yet stopped as it is taking
a while to stop a while to stop
content: {} content: {}
204: 204:
@@ -420,8 +412,7 @@ paths:
description: The user's notebook named-server has started description: The user's notebook named-server has started
content: {} content: {}
202: 202:
description: description: The user's notebook named-server has not yet started, but has
The user's notebook named-server has not yet started, but has
been requested been requested
content: {} content: {}
security: security:
@@ -457,8 +448,7 @@ paths:
required: false required: false
responses: responses:
202: 202:
description: description: The user's notebook named-server has not yet stopped as it
The user's notebook named-server has not yet stopped as it
is taking a while to stop is taking a while to stop
content: {} content: {}
204: 204:
@@ -472,8 +462,7 @@ paths:
get: get:
operationId: get-user-shared operationId: get-user-shared
summary: List servers shared with user summary: List servers shared with user
description: description: Returns list of Shares granting the user access to servers owned
Returns list of Shares granting the user access to servers owned
by others (new in 5.0) by others (new in 5.0)
parameters: parameters:
- $ref: "#/components/parameters/userName" - $ref: "#/components/parameters/userName"
@@ -587,8 +576,7 @@ paths:
expires_in: expires_in:
type: number type: number
example: 3600 example: 3600
description: description: lifetime (in seconds) after which the requested token
lifetime (in seconds) after which the requested token
will expire. Omit, or specify null or 0 for no expiration. will expire. Omit, or specify null or 0 for no expiration.
note: note:
type: string type: string
@@ -1262,8 +1250,7 @@ paths:
get: get:
operationId: get-proxy operationId: get-proxy
summary: Get the proxy's routing table summary: Get the proxy's routing table
description: description: A convenience alias for getting the routing table directly from
A convenience alias for getting the routing table directly from
the proxy the proxy
parameters: parameters:
- $ref: "#/components/parameters/paginationOffset" - $ref: "#/components/parameters/paginationOffset"
@@ -1275,8 +1262,7 @@ paths:
application/json: application/json:
schema: schema:
type: object type: object
description: description: configurable-http-proxy routing table (see configurable-http-proxy
configurable-http-proxy routing table (see configurable-http-proxy
docs for details) docs for details)
security: security:
- oauth2: - oauth2:
@@ -1296,8 +1282,7 @@ paths:
summary: Notify the Hub about a new proxy summary: Notify the Hub about a new proxy
description: Notifies the Hub of a new proxy to use. description: Notifies the Hub of a new proxy to use.
requestBody: requestBody:
description: description: Any values that have changed for the new proxy. All keys are
Any values that have changed for the new proxy. All keys are
optional. optional.
content: content:
application/json: application/json:
@@ -1389,8 +1374,7 @@ paths:
get: get:
operationId: get-auth-cookie operationId: get-auth-cookie
summary: Identify a user from a cookie summary: Identify a user from a cookie
description: description: Used by single-user notebook servers to hand off cookie authentication
Used by single-user notebook servers to hand off cookie authentication
to the Hub to the Hub
parameters: parameters:
- name: cookie_name - name: cookie_name
@@ -1515,13 +1499,11 @@ paths:
properties: properties:
proxy: proxy:
type: boolean type: boolean
description: description: Whether the proxy should be shutdown as well (default
Whether the proxy should be shutdown as well (default
from Hub config) from Hub config)
servers: servers:
type: boolean type: boolean
description: description: Whether users' notebook servers should be shutdown
Whether users' notebook servers should be shutdown
as well (default from Hub config) as well (default from Hub config)
required: false required: false
responses: responses:
@@ -1666,8 +1648,7 @@ components:
type: string type: string
server: server:
type: string type: string
description: description: The user's notebook server's base URL, if running; null if
The user's notebook server's base URL, if running; null if
not. not.
pending: pending:
type: string type: string
@@ -1699,8 +1680,7 @@ components:
properties: properties:
name: name:
type: string type: string
description: description: The server's name. The user's default server has an empty name
The server's name. The user's default server has an empty name
('') ('')
ready: ready:
type: boolean type: boolean
@@ -1763,15 +1743,13 @@ components:
state: state:
type: object type: object
properties: {} properties: {}
description: description: Arbitrary internal state from this server's spawner. Only available
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 on the hub's users list or get-user-by-name method, and only with admin:users:server_state
scope. None otherwise. scope. None otherwise.
user_options: user_options:
type: object type: object
properties: {} properties: {}
description: description: User specified options for the user's spawned instance of a
User specified options for the user's spawned instance of a
single-user server. single-user server.
RequestIdentity: RequestIdentity:
description: | description: |
@@ -1940,8 +1918,7 @@ components:
items: items:
type: string type: string
group: group:
description: description: the group being shared with (exactly one of 'user' or 'group'
the group being shared with (exactly one of 'user' or 'group'
will be non-null, the other will be null) will be non-null, the other will be null)
type: type:
- object - object
@@ -1950,8 +1927,7 @@ components:
name: name:
type: string type: string
user: user:
description: description: the user being shared with (exactly one of 'user' or 'group'
the user being shared with (exactly one of 'user' or 'group'
will be non-null, the other will be null) will be non-null, the other will be null)
type: type:
- object - object
@@ -1965,8 +1941,7 @@ components:
format: date-time format: date-time
ShareCode: ShareCode:
description: description: A single sharing code. There is at most one of these objects per
A single sharing code. There is at most one of these objects per
(server, user) or (server, group) combination. (server, user) or (server, group) combination.
type: object type: object
properties: properties:
@@ -2002,8 +1977,7 @@ components:
properties: properties:
id: id:
type: string type: string
description: description: The id of the API token. Used for modifying or deleting the
The id of the API token. Used for modifying or deleting the
token. token.
user: user:
type: string type: string
@@ -2013,22 +1987,19 @@ components:
description: The service that owns the token (undefined of owned by a user) description: The service that owns the token (undefined of owned by a user)
roles: roles:
type: array type: array
description: description: Deprecated in JupyterHub 3, always an empty list. Tokens have
Deprecated in JupyterHub 3, always an empty list. Tokens have
'scopes' starting from JupyterHub 3. 'scopes' starting from JupyterHub 3.
items: items:
type: string type: string
scopes: scopes:
type: array type: array
description: description: List of scopes this token has been assigned. New in JupyterHub
List of scopes this token has been assigned. New in JupyterHub
3. In JupyterHub 2.x, tokens were assigned 'roles' instead of scopes. 3. In JupyterHub 2.x, tokens were assigned 'roles' instead of scopes.
items: items:
type: string type: string
note: note:
type: string type: string
description: description: A note about the token, typically describing what it was created
A note about the token, typically describing what it was created
for. for.
created: created:
type: string type: string
@@ -2059,13 +2030,11 @@ components:
properties: properties:
token: token:
type: string type: string
description: description: The token itself. Only present in responses to requests for
The token itself. Only present in responses to requests for
a new token. a new token.
id: id:
type: string type: string
description: description: The id of the API token. Used for modifying or deleting the
The id of the API token. Used for modifying or deleting the
token. token.
user: user:
type: string type: string
@@ -2075,22 +2044,19 @@ components:
description: The service that owns the token (undefined of owned by a user) description: The service that owns the token (undefined of owned by a user)
roles: roles:
type: array type: array
description: description: Deprecated in JupyterHub 3, always an empty list. Tokens have
Deprecated in JupyterHub 3, always an empty list. Tokens have
'scopes' starting from JupyterHub 3. 'scopes' starting from JupyterHub 3.
items: items:
type: string type: string
scopes: scopes:
type: array type: array
description: description: List of scopes this token has been assigned. New in JupyterHub
List of scopes this token has been assigned. New in JupyterHub
3. In JupyterHub 2.x, tokens were assigned 'roles' instead of scopes. 3. In JupyterHub 2.x, tokens were assigned 'roles' instead of scopes.
items: items:
type: string type: string
note: note:
type: string type: string
description: description: A note about the token, typically describing what it was created
A note about the token, typically describing what it was created
for. for.
created: created:
type: string type: string
@@ -2128,27 +2094,21 @@ components:
tokenUrl: /hub/api/oauth2/token tokenUrl: /hub/api/oauth2/token
scopes: scopes:
(no_scope): Identify the owner of the requesting entity. (no_scope): Identify the owner of the requesting entity.
self: self: The users own resources _(metascope for users, resolves to (no_scope)
The users own resources _(metascope for users, resolves to (no_scope)
for services)_ for services)_
inherit: inherit: Everything that the token-owning entity can access _(metascope
Everything that the token-owning entity can access _(metascope
for tokens)_ for tokens)_
admin-ui: admin-ui: Access the admin page. Permission to take actions via the admin
Access the admin page. Permission to take actions via the admin
page granted separately. page granted separately.
admin:users: admin:users: Read, modify, create, and delete users and their authentication
Read, modify, create, and delete users and their authentication
state, not including their servers or tokens. This is an extremely privileged state, not including their servers or tokens. This is an extremely privileged
scope and should be considered tantamount to superuser. scope and should be considered tantamount to superuser.
admin:auth_state: Read a users authentication state. admin:auth_state: Read a users authentication state.
users: users: Read and write permissions to user models (excluding servers, tokens
Read and write permissions to user models (excluding servers, tokens
and authentication state). and authentication state).
delete:users: Delete users. delete:users: Delete users.
list:users: List users, including at least their names. list:users: List users, including at least their names.
read:users: read:users: Read user models (including the URL of the default server
Read user models (including the URL of the default server
if it is running). if it is running).
read:users:name: Read names of users. read:users:name: Read names of users.
read:users:groups: Read users group membership. read:users:groups: Read users group membership.
@@ -2158,27 +2118,23 @@ components:
read:roles:services: Read service role assignments. read:roles:services: Read service role assignments.
read:roles:groups: Read group role assignments. read:roles:groups: Read group role assignments.
users:activity: Update time of last user activity. users:activity: Update time of last user activity.
admin:servers: admin:servers: Read, start, stop, create and delete user servers and their
Read, start, stop, create and delete user servers and their
state. state.
admin:server_state: Read and write users server state. admin:server_state: Read and write users server state.
servers: Start and stop user servers. servers: Start and stop user servers.
read:servers: read:servers: Read users names and their server models (excluding the
Read users names and their server models (excluding the
server state). server state).
delete:servers: Stop and delete users' servers. delete:servers: Stop and delete users' servers.
tokens: Read, write, create and delete user tokens. tokens: Read, write, create and delete user tokens.
read:tokens: Read user tokens. read:tokens: Read user tokens.
admin:groups: Read and write group information, create and delete groups. admin:groups: Read and write group information, create and delete groups.
groups: groups: 'Read and write group information, including adding/removing any
"Read and write group information, including adding/removing any users to/from groups. Note: adding users to groups may affect permissions.'
users to/from groups. Note: adding users to groups may affect permissions."
list:groups: List groups, including at least their names. list:groups: List groups, including at least their names.
read:groups: Read group models. read:groups: Read group models.
read:groups:name: Read group names. read:groups:name: Read group names.
delete:groups: Delete groups. delete:groups: Delete groups.
admin:services: admin:services: Create, read, update, delete services, not including services
Create, read, update, delete services, not including services
defined from config files. defined from config files.
list:services: List services, including at least their names. list:services: List services, including at least their names.
read:services: Read service models. read:services: Read service models.
@@ -2192,8 +2148,7 @@ components:
read:groups:shares: Read servers shared with a group. read:groups:shares: Read servers shared with a group.
read:shares: Read information about shared access to servers. read:shares: Read information about shared access to servers.
shares: Manage access to shared servers. shares: Manage access to shared servers.
proxy: proxy: Read information about the proxys routing table, sync the Hub
Read information about the proxys routing table, sync the Hub
with the proxy and notify the Hub about a new proxy. with the proxy and notify the Hub about a new proxy.
shutdown: Shutdown the hub. shutdown: Shutdown the hub.
read:metrics: Read prometheus metrics. read:metrics: Read prometheus metrics.

View File

@@ -14,26 +14,52 @@ The files are:
scopes descriptions are updated in it. scopes descriptions are updated in it.
""" """
import os
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from subprocess import run
from pytablewriter import MarkdownTableWriter from pytablewriter import MarkdownTableWriter
from ruamel.yaml import YAML from ruamel.yaml import YAML
from jupyterhub import __version__ HERE = Path(__file__).parent.absolute()
from jupyterhub.scopes import scope_definitions DOCS = HERE / ".." / ".."
HERE = os.path.abspath(os.path.dirname(__file__))
DOCS = Path(HERE).parent.parent.absolute()
REST_API_YAML = DOCS.joinpath("source", "_static", "rest-api.yml") REST_API_YAML = DOCS.joinpath("source", "_static", "rest-api.yml")
SCOPE_TABLE_MD = Path(HERE).joinpath("scope-table.md") SCOPE_TABLE_MD = HERE.joinpath("scope-table.md")
def _load_jupyterhub_info():
"""
The equivalent of
from jupyterhub import __version__
from jupyterhub.scopes import scope_definitions
but without needing to install JupyterHub and dependencies
so that we can run this pre-commit
"""
root = HERE / ".." / ".." / ".."
g = {}
exec((root / "jupyterhub" / "_version.py").read_text(), g)
# To avoid parsing the whole of scope_definitions.py just pull out
# the relevant lines
scopes_file = root / "jupyterhub" / "scopes.py"
scopes_lines = []
for line in scopes_file.read_text().splitlines():
if not scopes_lines and line == "scope_definitions = {":
scopes_lines.append(line)
elif scopes_lines:
scopes_lines.append(line)
if line == "}":
break
exec("\n".join(scopes_lines), g)
return g["__version__"], g["scope_definitions"]
class ScopeTableGenerator: class ScopeTableGenerator:
def __init__(self): def __init__(self):
self.scopes = scope_definitions self.version, self.scopes = _load_jupyterhub_info()
@classmethod @classmethod
def create_writer(cls, table_name, headers, values): def create_writer(cls, table_name, headers, values):
@@ -131,7 +157,7 @@ class ScopeTableGenerator:
with open(filename) as f: with open(filename) as f:
content = yaml.load(f.read()) content = yaml.load(f.read())
content["info"]["version"] = __version__ content["info"]["version"] = self.version
for scope in self.scopes: for scope in self.scopes:
description = self.scopes[scope]['description'] description = self.scopes[scope]['description']
doc_description = self.scopes[scope].get('doc_description', '') doc_description = self.scopes[scope].get('doc_description', '')
@@ -145,12 +171,6 @@ class ScopeTableGenerator:
with open(filename, 'w') as f: with open(filename, 'w') as f:
yaml.dump(content, f) yaml.dump(content, f)
run(
['pre-commit', 'run', 'prettier', '--files', filename],
cwd=HERE,
check=False,
)
def main(): def main():
table_generator = ScopeTableGenerator() table_generator = ScopeTableGenerator()

View File

@@ -0,0 +1,58 @@
Table 1. Available scopes and their hierarchy
| Scope | Grants permission to: |
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `(no_scope)` | Identify the owner of the requesting entity. |
| `self` | The users own resources _(metascope for users, resolves to (no_scope) for services)_ |
| `inherit` | Everything that the token-owning entity can access _(metascope for tokens)_ |
| `admin-ui` | Access the admin page. Permission to take actions via the admin page granted separately. |
| `admin:users` | Read, modify, create, and delete users and their authentication state, not including their servers or tokens. This is an extremely privileged scope and should be considered tantamount to superuser. |
|    `admin:auth_state` | Read a users authentication state. |
|    `users` | Read and write permissions to user models (excluding servers, tokens and authentication state). |
|       `read:users` | Read user models (including servers, tokens and authentication state). |
|          `read:users:name` | Read names of users. |
|          `read:users:groups` | Read users group membership. |
|          `read:users:activity` | Read time of last user activity. |
|       `list:users` | List users, including at least their names. |
|          `read:users:name` | Read names of users. |
|       `users:activity` | Update time of last user activity. |
|          `read:users:activity` | Read time of last user activity. |
|    `read:roles:users` | Read user role assignments. |
|    `delete:users` | Delete users. |
| `read:roles` | Read role assignments. |
|    `read:roles:users` | Read user role assignments. |
|    `read:roles:services` | Read service role assignments. |
|    `read:roles:groups` | Read group role assignments. |
| `admin:servers` | Read, start, stop, create and delete user servers and their state. |
|    `admin:server_state` | Read and write users server state. |
|    `servers` | Start and stop user servers. |
|       `read:servers` | Read users names and their server models (excluding the server state). |
|          `read:users:name` | Read names of users. |
|       `delete:servers` | Stop and delete users' servers. |
| `tokens` | Read, write, create and delete user tokens. |
|    `read:tokens` | Read user tokens. |
| `admin:groups` | Read and write group information, create and delete groups. |
|    `groups` | Read and write group information, including adding/removing any users to/from groups. Note: adding users to groups may affect permissions. |
|       `read:groups` | Read group models. |
|          `read:groups:name` | Read group names. |
|       `list:groups` | List groups, including at least their names. |
|          `read:groups:name` | Read group names. |
|    `read:roles:groups` | Read group role assignments. |
|    `delete:groups` | Delete groups. |
| `admin:services` | Create, read, update, delete services, not including services defined from config files. |
|    `list:services` | List services, including at least their names. |
|       `read:services:name` | Read service names. |
|    `read:services` | Read service models. |
|       `read:services:name` | Read service names. |
|    `read:roles:services` | Read service role assignments. |
| `read:hub` | Read detailed information about the Hub. |
| `access:services` | Access services via API or browser. |
| `shares` | Manage access to shared servers. |
|    `access:servers` | Access user servers via API or browser. |
|    `read:shares` | Read information about shared access to servers. |
|    `users:shares` | Read and revoke a user's access to shared servers. |
|       `read:users:shares` | Read servers shared with a user. |
|    `groups:shares` | Read and revoke a group's access to shared servers. |
|       `read:groups:shares` | Read servers shared with a group. |
| `proxy` | Read information about the proxys routing table, sync the Hub with the proxy and notify the Hub about a new proxy. |
| `shutdown` | Shutdown the hub. |
| `read:metrics` | Read prometheus metrics. |

View File

@@ -31,8 +31,11 @@ from tornado.log import app_log
from . import orm, roles from . import orm, roles
from ._memoize import DoNotCache, FrozenDict, lru_cache_key from ._memoize import DoNotCache, FrozenDict, lru_cache_key
"""when modifying the scope definitions, make sure that `docs/source/rbac/generate-scope-table.py` is run """when modifying the scope definitions
so that changes are reflected in the documentation and REST API description.""" `docs/source/rbac/generate-scope-table.py` must be run
so that changes are reflected in the documentation and REST API description.
`pre-commit run -a` should automatically take care of this.
"""
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': {