mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 15:33:02 +00:00
resolve self in _get_subscopes
avoids inconsistent behavior in different uses of _get_subscopes where 'self' is left unmodified, leading to errors
This commit is contained in:
@@ -163,22 +163,24 @@ def _expand_scope(scopename):
|
||||
def expand_roles_to_scopes(orm_object):
|
||||
"""Get the scopes listed in the roles of the User/Service/Group/Token
|
||||
If User, take into account the user's groups roles as well"""
|
||||
from .user import User
|
||||
|
||||
if isinstance(orm_object, User):
|
||||
orm_object = User.orm_user
|
||||
|
||||
pass_roles = orm_object.roles
|
||||
|
||||
if isinstance(orm_object, orm.User):
|
||||
groups_roles = []
|
||||
for group in orm_object.groups:
|
||||
groups_roles.extend(group.roles)
|
||||
pass_roles.extend(groups_roles)
|
||||
scopes = _get_subscopes(*pass_roles)
|
||||
if 'self' in scopes:
|
||||
scopes.remove('self')
|
||||
if isinstance(orm_object, orm.User) or hasattr(orm_object, 'orm_user'):
|
||||
scopes |= expand_self_scope(orm_object.name)
|
||||
|
||||
scopes = _get_subscopes(*pass_roles, owner=orm_object)
|
||||
return scopes
|
||||
|
||||
|
||||
def _get_subscopes(*args):
|
||||
def _get_subscopes(*args, owner=None):
|
||||
"""Returns a set of all available subscopes for a specified role or list of roles"""
|
||||
|
||||
scope_list = []
|
||||
@@ -188,6 +190,11 @@ def _get_subscopes(*args):
|
||||
|
||||
scopes = set(chain.from_iterable(list(map(_expand_scope, scope_list))))
|
||||
|
||||
if 'self' in scopes:
|
||||
scopes.remove('self')
|
||||
if owner and isinstance(owner, orm.User):
|
||||
scopes |= expand_self_scope(owner.name)
|
||||
|
||||
return scopes
|
||||
|
||||
|
||||
@@ -380,32 +387,36 @@ def _token_allowed_role(db, token, role):
|
||||
"""Returns True if token allowed to have requested role through
|
||||
comparing the requested scopes with the set of token's owner scopes"""
|
||||
|
||||
standard_permissions = {'all', 'read:all'}
|
||||
owner = token.user
|
||||
if owner is None:
|
||||
owner = token.service
|
||||
|
||||
token_scopes = _get_subscopes(role)
|
||||
extra_scopes = token_scopes - standard_permissions
|
||||
if owner is None:
|
||||
raise ValueError(f"Owner not found for {token}")
|
||||
|
||||
token_scopes = _get_subscopes(role, owner=owner)
|
||||
|
||||
implicit_permissions = {'all', 'read:all'}
|
||||
explicit_scopes = token_scopes - implicit_permissions
|
||||
# ignore horizontal filters
|
||||
raw_extra_scopes = {
|
||||
scope.split('!', 1)[0] if '!' in scope else scope for scope in extra_scopes
|
||||
raw_scopes = {
|
||||
scope.split('!', 1)[0] if '!' in scope else scope for scope in explicit_scopes
|
||||
}
|
||||
# find the owner and their roles
|
||||
owner = None
|
||||
if token.user_id:
|
||||
owner = db.query(orm.User).get(token.user_id)
|
||||
elif token.service_id:
|
||||
owner = db.query(orm.Service).get(token.service_id)
|
||||
if owner:
|
||||
# find the owner's scopes
|
||||
owner_scopes = expand_roles_to_scopes(owner)
|
||||
# ignore horizontal filters
|
||||
raw_owner_scopes = {
|
||||
scope.split('!', 1)[0] if '!' in scope else scope for scope in owner_scopes
|
||||
}
|
||||
if raw_extra_scopes.issubset(raw_owner_scopes):
|
||||
disallowed_scopes = raw_scopes.difference(raw_owner_scopes)
|
||||
if not disallowed_scopes:
|
||||
# no scopes requested outside owner's own scopes
|
||||
return True
|
||||
else:
|
||||
app_log.warning(
|
||||
f"Token requesting scopes exceeding owner {owner.name}: {disallowed_scopes}"
|
||||
)
|
||||
return False
|
||||
else:
|
||||
raise ValueError('Owner the token %r not found', token)
|
||||
|
||||
|
||||
def assign_default_roles(db, entity):
|
||||
@@ -440,12 +451,10 @@ def update_roles(db, entity, roles):
|
||||
)
|
||||
if _token_allowed_role(db, entity, role):
|
||||
role.tokens.append(entity)
|
||||
app_log.info('Adding role %s for token: %s', role.name, entity)
|
||||
app_log.info('Adding role %s to token: %s', role.name, entity)
|
||||
else:
|
||||
raise ValueError(
|
||||
'Requested token role %r of %r has more permissions than the token owner',
|
||||
rolename,
|
||||
entity,
|
||||
f'Requested token role {rolename} of {entity} has more permissions than the token owner'
|
||||
)
|
||||
else:
|
||||
raise NameError('Role %r does not exist' % rolename)
|
||||
|
Reference in New Issue
Block a user