rename white/blacklist allowed/blocked

- group_whitelist -> allowed_groups

still todo: handle deprecated signatures in check_whitelist methods while preserving subclass overrides
This commit is contained in:
Min RK
2020-06-15 14:40:20 +02:00
parent b5defabf49
commit cc8e780653
9 changed files with 219 additions and 139 deletions

View File

@@ -201,7 +201,7 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler):
def needs_oauth_confirm(self, user, oauth_client):
"""Return whether the given oauth client needs to prompt for access for the given user
Checks whitelist for oauth clients
Checks list for oauth clients that don't need confirmation
(i.e. the user's own server)
@@ -214,9 +214,8 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler):
if (
# it's the user's own server
oauth_client.identifier in own_oauth_client_ids
# or it's in the global whitelist
or oauth_client.identifier
in self.settings.get('oauth_no_confirm_whitelist', set())
# or it's in the global no-confirm list
or oauth_client.identifier in self.settings.get('oauth_no_confirm', set())
):
return False
# default: require confirmation
@@ -229,7 +228,7 @@ class OAuthAuthorizeHandler(OAuthHandler, BaseHandler):
Render oauth confirmation page:
"Server at ... would like permission to ...".
Users accessing their own server or a service whitelist
Users accessing their own server or a blessed service
will skip confirmation.
"""

View File

@@ -1689,22 +1689,22 @@ class JupyterHub(Application):
# the admin_users config variable will never be used after this point.
# only the database values will be referenced.
whitelist = [
allowed = [
self.authenticator.normalize_username(name)
for name in self.authenticator.whitelist
for name in self.authenticator.allowed
]
self.authenticator.whitelist = set(whitelist) # force normalization
for username in whitelist:
self.authenticator.allowed = set(allowed) # force normalization
for username in allowed:
if not self.authenticator.validate_username(username):
raise ValueError("username %r is not valid" % username)
if not whitelist:
if not allowed:
self.log.info(
"Not using whitelist. Any authenticated user will be allowed."
"Not using allowed user list. Any authenticated user will be allowed."
)
# add whitelisted users to the db
for name in whitelist:
# add allowed users to the db
for name in allowed:
user = orm.User.find(db, name)
if user is None:
user = orm.User(name=name)
@@ -1714,9 +1714,9 @@ class JupyterHub(Application):
db.commit()
# Notify authenticator of all users.
# This ensures Auth whitelist is up-to-date with the database.
# This lets whitelist be used to set up initial list,
# but changes to the whitelist can occur in the database,
# This ensures Authenticator.allowed is up-to-date with the database.
# This lets .allowed be used to set up initial list,
# but changes to the allowed list can occur in the database,
# and persist across sessions.
total_users = 0
for user in db.query(orm.User):
@@ -1753,9 +1753,9 @@ class JupyterHub(Application):
user.created = user.last_activity or datetime.utcnow()
db.commit()
# The whitelist set and the users in the db are now the same.
# The allowed set and the users in the db are now the same.
# From this point on, any user changes should be done simultaneously
# to the whitelist set and user db, unless the whitelist is empty (all users allowed).
# to the allowed set and user db, unless the allowed set is empty (all users allowed).
TOTAL_USERS.set(total_users)
@@ -1770,11 +1770,11 @@ class JupyterHub(Application):
for username in usernames:
username = self.authenticator.normalize_username(username)
if not (
await maybe_future(
self.authenticator.check_whitelist(username, None)
)
await maybe_future(self.authenticator.check_allowed(username, None))
):
raise ValueError("Username %r is not in whitelist" % username)
raise ValueError(
"Username %r is not in Authenticator.allowed" % username
)
user = orm.User.find(db, name=username)
if user is None:
if not self.authenticator.validate_username(username):
@@ -1798,11 +1798,13 @@ class JupyterHub(Application):
if kind == 'user':
name = self.authenticator.normalize_username(name)
if not (
await maybe_future(self.authenticator.check_whitelist(name, None))
await maybe_future(self.authenticator.check_allowed(name, None))
):
raise ValueError("Token name %r is not in whitelist" % name)
raise ValueError(
"Token user name %r is not in Authenticator.allowed" % name
)
if not self.authenticator.validate_username(name):
raise ValueError("Token name %r is not valid" % name)
raise ValueError("Token user name %r is not valid" % name)
if kind == 'service':
if not any(service["name"] == name for service in self.services):
self.log.warning(
@@ -2183,14 +2185,14 @@ class JupyterHub(Application):
else:
version_hash = datetime.now().strftime("%Y%m%d%H%M%S")
oauth_no_confirm_whitelist = set()
oauth_no_confirm_list = set()
for service in self._service_map.values():
if service.oauth_no_confirm:
self.log.warning(
"Allowing service %s to complete OAuth without confirmation on an authorization web page",
service.name,
)
oauth_no_confirm_whitelist.add(service.oauth_client_id)
oauth_no_confirm_list.add(service.oauth_client_id)
settings = dict(
log_function=log_request,
@@ -2226,7 +2228,7 @@ class JupyterHub(Application):
default_server_name=self._default_server_name,
named_server_limit_per_user=self.named_server_limit_per_user,
oauth_provider=self.oauth_provider,
oauth_no_confirm_whitelist=oauth_no_confirm_whitelist,
oauth_no_confirm_list=oauth_no_confirm_list,
concurrent_spawn_limit=self.concurrent_spawn_limit,
spawn_throttle_retry_range=self.spawn_throttle_retry_range,
active_server_limit=self.active_server_limit,

View File

@@ -7,6 +7,7 @@ import re
import sys
import warnings
from concurrent.futures import ThreadPoolExecutor
from functools import partial
from shutil import which
from subprocess import PIPE
from subprocess import Popen
@@ -100,41 +101,74 @@ class Authenticator(LoggingConfigurable):
"""
).tag(config=True)
whitelist = Set(
whitelist = Set(help="Deprecated, use `Authenticator.allowed`", config=True,)
allowed = Set(
help="""
Whitelist of usernames that are allowed to log in.
Set of usernames that are allowed to log in.
Use this with supported authenticators to restrict which users can log in. This is an
additional whitelist that further restricts users, beyond whatever restrictions the
additional list that further restricts users, beyond whatever restrictions the
authenticator has in place.
If empty, does not perform any additional restriction.
.. versionchanged:: 1.2
`Authenticator.whitelist` renamed to `allowed`
"""
).tag(config=True)
blacklist = Set(
blocked = Set(
help="""
Blacklist of usernames that are not allowed to log in.
Set of usernames that are not allowed to log in.
Use this with supported authenticators to restrict which users can not log in. This is an
additional blacklist that further restricts users, beyond whatever restrictions the
additional block list that further restricts users, beyond whatever restrictions the
authenticator has in place.
If empty, does not perform any additional restriction.
.. versionadded: 0.9
.. versionchanged:: 1.2
`Authenticator.blacklist` renamed to `blocked`
"""
).tag(config=True)
@observe('whitelist')
def _check_whitelist(self, change):
_deprecated_aliases = {
"whitelist": ("allowed", "1.2"),
"blacklist": ("blocked", "1.2"),
}
@observe(*list(_deprecated_aliases))
def _deprecated_trait(self, change):
"""observer for deprecated traits"""
old_attr = change.name
new_attr, version = self._deprecated_aliases.get(old_attr)
new_value = getattr(self, new_attr)
if new_value != change.new:
# only warn if different
# protects backward-compatible config from warnings
# if they set the same value under both names
self.log.warning(
"{cls}.{old} is deprecated in JupyterHub {version}, use {cls}.{new} instead".format(
cls=self.__class__.__name__,
old=old_attr,
new=new_attr,
version=version,
)
)
setattr(self, new_attr, change.new)
@observe('allowed')
def _check_allowed(self, change):
short_names = [name for name in change['new'] if len(name) <= 1]
if short_names:
sorted_names = sorted(short_names)
single = ''.join(sorted_names)
string_set_typo = "set('%s')" % single
self.log.warning(
"whitelist contains single-character names: %s; did you mean set([%r]) instead of %s?",
"Allowed list contains single-character names: %s; did you mean set([%r]) instead of %s?",
sorted_names[:8],
single,
string_set_typo,
@@ -260,6 +294,8 @@ class Authenticator(LoggingConfigurable):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# TODO: properly handle deprecated signature *and* name
# with correct subclass override priority!
for method_name in (
'check_whitelist',
'check_blacklist',
@@ -326,39 +362,45 @@ class Authenticator(LoggingConfigurable):
username = self.username_map.get(username, username)
return username
def check_whitelist(self, username, authentication=None):
"""Check if a username is allowed to authenticate based on whitelist configuration
def check_allowed(self, username, authentication=None):
"""Check if a username is allowed to authenticate based on configuration
Return True if username is allowed, False otherwise.
No whitelist means any username is allowed.
No allowed set means any username is allowed.
Names are normalized *before* being checked against the whitelist.
Names are normalized *before* being checked against the allowed set.
.. versionchanged:: 1.0
Signature updated to accept authentication data and any future changes
"""
if not self.whitelist:
# No whitelist means any name is allowed
return True
return username in self.whitelist
def check_blacklist(self, username, authentication=None):
"""Check if a username is blocked to authenticate based on blacklist configuration
.. versionchanged:: 1.2
Renamed check_whitelist to check_allowed
"""
if not self.allowed:
# No allowed set means any name is allowed
return True
return username in self.allowed
def check_blocked(self, username, authentication=None):
"""Check if a username is blocked to authenticate based on Authenticator.blocked configuration
Return True if username is allowed, False otherwise.
No blacklist means any username is allowed.
No block list means any username is allowed.
Names are normalized *before* being checked against the blacklist.
Names are normalized *before* being checked against the block list.
.. versionadded: 0.9
.. versionchanged:: 1.0
Signature updated to accept authentication data as second argument
.. versionchanged:: 1.2
Renamed check_blacklist to check_blocked
"""
if not self.blacklist:
# No blacklist means any name is allowed
if not self.blocked:
# No block list means any name is allowed
return True
return username not in self.blacklist
return username not in self.blocked
async def get_authenticated_user(self, handler, data):
"""Authenticate the user who is attempting to log in
@@ -367,7 +409,7 @@ class Authenticator(LoggingConfigurable):
This calls `authenticate`, which should be overridden in subclasses,
normalizes the username if any normalization should be done,
and then validates the name in the whitelist.
and then validates the name in the allowed set.
This is the outer API for authenticating a user.
Subclasses should not override this method.
@@ -375,7 +417,7 @@ class Authenticator(LoggingConfigurable):
The various stages can be overridden separately:
- `authenticate` turns formdata into a username
- `normalize_username` normalizes the username
- `check_whitelist` checks against the user whitelist
- `check_allowed` checks against the user allowed
.. versionchanged:: 0.8
return dict instead of username
@@ -389,7 +431,7 @@ class Authenticator(LoggingConfigurable):
else:
authenticated = {'name': authenticated}
authenticated.setdefault('auth_state', None)
# Leave the default as None, but reevaluate later post-whitelist
# Leave the default as None, but reevaluate later post-allowed-check
authenticated.setdefault('admin', None)
# normalize the username
@@ -400,20 +442,16 @@ class Authenticator(LoggingConfigurable):
self.log.warning("Disallowing invalid username %r.", username)
return
blacklist_pass = await maybe_future(
self.check_blacklist(username, authenticated)
)
whitelist_pass = await maybe_future(
self.check_whitelist(username, authenticated)
)
blocked_pass = await maybe_future(self.check_blocked(username, authenticated))
allowed_pass = await maybe_future(self.check_allowed(username, authenticated))
if blacklist_pass:
if blocked_pass:
pass
else:
self.log.warning("User %r in blacklist. Stop authentication", username)
self.log.warning("User %r blocked. Stop authentication", username)
return
if whitelist_pass:
if allowed_pass:
if authenticated['admin'] is None:
authenticated['admin'] = await maybe_future(
self.is_admin(handler, authenticated)
@@ -423,7 +461,7 @@ class Authenticator(LoggingConfigurable):
return authenticated
else:
self.log.warning("User %r not in whitelist.", username)
self.log.warning("User %r not allowed.", username)
return
async def refresh_user(self, user, handler=None):
@@ -479,7 +517,7 @@ class Authenticator(LoggingConfigurable):
It must return the username on successful authentication,
and return None on failed authentication.
Checking the whitelist is handled separately by the caller.
Checking allowed/blocked is handled separately by the caller.
.. versionchanged:: 0.8
Allow `authenticate` to return a dict containing auth_state.
@@ -520,10 +558,10 @@ class Authenticator(LoggingConfigurable):
This method may be a coroutine.
By default, this just adds the user to the whitelist.
By default, this just adds the user to the allowed set.
Subclasses may do more extensive things, such as adding actual unix users,
but they should call super to ensure the whitelist is updated.
but they should call super to ensure the allowed set is updated.
Note that this should be idempotent, since it is called whenever the hub restarts
for all users.
@@ -533,19 +571,19 @@ class Authenticator(LoggingConfigurable):
"""
if not self.validate_username(user.name):
raise ValueError("Invalid username: %s" % user.name)
if self.whitelist:
self.whitelist.add(user.name)
if self.allowed:
self.allowed.add(user.name)
def delete_user(self, user):
"""Hook called when a user is deleted
Removes the user from the whitelist.
Subclasses should call super to ensure the whitelist is updated.
Removes the user from the allowed set.
Subclasses should call super to ensure the allowed set is updated.
Args:
user (User): The User wrapper object
"""
self.whitelist.discard(user.name)
self.allowed.discard(user.name)
auto_login = Bool(
False,
@@ -610,6 +648,38 @@ class Authenticator(LoggingConfigurable):
return [('/login', LoginHandler)]
def _deprecated_method(old_name, new_name, version, self, *args, **kwargs):
"""Method wrapper for a deprecated method name"""
warnings.warn(
(
"{cls}.{old_name} is deprecated in JupyterHub {version}."
" Please use {cls}.{new_name} instead."
).format(
cls=self.__class__.__name__,
old_name=old_name,
new_name=new_name,
version=version,
),
DeprecationWarning,
stacklevel=2,
)
old_method = getattr(self, new_name)
return old_method(*args, **kwargs)
# deprecate white/blacklist method names
for _old_name, _new_name, _version in [
("check_whitelist", "check_allowed", "1.2"),
("check_blacklist", "check_blocked", "1.2"),
]:
setattr(
Authenticator,
_old_name,
partial(_deprecated_method, _old_name, _new_name, _version),
)
class LocalAuthenticator(Authenticator):
"""Base class for Authenticators that work with local Linux/UNIX users
@@ -669,37 +739,37 @@ class LocalAuthenticator(Authenticator):
"""
).tag(config=True)
group_whitelist = Set(
help="""
Whitelist all users from this UNIX group.
group_whitelist = Set(help="""DEPRECATED: use allowed_groups""",).tag(config=True)
This makes the username whitelist ineffective.
allowed_groups = Set(
help="""
Allow login from all users in these UNIX groups.
If set, allowed username set is ignored.
"""
).tag(config=True)
@observe('group_whitelist')
def _group_whitelist_changed(self, change):
"""
Log a warning if both group_whitelist and user whitelist are set.
"""
if self.whitelist:
@observe('allowed_groups')
def _allowed_groups_changed(self, change):
"""Log a warning if mutually exclusive user and group allowed sets are specified."""
if self.allowed:
self.log.warning(
"Ignoring username whitelist because group whitelist supplied!"
"Ignoring Authenticator.allowed set because Authenticator.allowed_groups supplied!"
)
def check_whitelist(self, username, authentication=None):
if self.group_whitelist:
return self.check_group_whitelist(username, authentication)
def check_allowed(self, username, authentication=None):
if self.allowed_groups:
return self.check_allowed_groups(username, authentication)
else:
return super().check_whitelist(username, authentication)
return super().check_allowed(username, authentication)
def check_group_whitelist(self, username, authentication=None):
def check_allowed_groups(self, username, authentication=None):
"""
If group_whitelist is configured, check if authenticating user is part of group.
If allowed_groups is configured, check if authenticating user is part of group.
"""
if not self.group_whitelist:
if not self.allowed_groups:
return False
for grnam in self.group_whitelist:
for grnam in self.allowed_groups:
try:
group = self._getgrnam(grnam)
except KeyError:
@@ -843,7 +913,7 @@ class PAMAuthenticator(LocalAuthenticator):
Authoritative list of user groups that determine admin access.
Users not in these groups can still be granted admin status through admin_users.
White/blacklisting rules still apply.
allowed/blocked rules still apply.
"""
).tag(config=True)
@@ -986,6 +1056,16 @@ class PAMAuthenticator(LocalAuthenticator):
return super().normalize_username(username)
for _old_name, _new_name, _version in [
("check_group_whitelist", "check_group_allowed", "1.2"),
]:
setattr(
LocalAuthenticator,
_old_name,
partial(_deprecated_method, _old_name, _new_name, _version),
)
class DummyAuthenticator(Authenticator):
"""Dummy Authenticator for testing

View File

@@ -860,15 +860,15 @@ class HubAuthenticated(object):
if kind == 'service':
# it's a service, check hub_services
if self.hub_services and name in self.hub_services:
app_log.debug("Allowing whitelisted Hub service %s", name)
app_log.debug("Allowing Hub service %s", name)
return model
else:
app_log.warning("Not allowing Hub service %s", name)
raise UserNotAllowed(model)
if self.hub_users and name in self.hub_users:
# user in whitelist
app_log.debug("Allowing whitelisted Hub user %s", name)
# user in allowed list
app_log.debug("Allowing Hub user %s", name)
return model
elif self.hub_groups and set(model['groups']).intersection(self.hub_groups):
allowed_groups = set(model['groups']).intersection(self.hub_groups)
@@ -877,7 +877,7 @@ class HubAuthenticated(object):
name,
','.join(sorted(allowed_groups)),
)
# group in whitelist
# group in allowed list
return model
else:
app_log.warning("Not allowing Hub user %s", name)

View File

@@ -435,9 +435,9 @@ class Spawner(LoggingConfigurable):
'LC_ALL',
],
help="""
Whitelist of environment variables for the single-user server to inherit from the JupyterHub process.
List of environment variables for the single-user server to inherit from the JupyterHub process.
This whitelist is used to ensure that sensitive information in the JupyterHub process's environment
This list is used to ensure that sensitive information in the JupyterHub process's environment
(such as `CONFIGPROXY_AUTH_TOKEN`) is not passed to the single-user server's process.
""",
).tag(config=True)
@@ -456,7 +456,7 @@ class Spawner(LoggingConfigurable):
Environment variables that end up in the single-user server's process come from 3 sources:
- This `environment` configurable
- The JupyterHub process' environment variables that are whitelisted in `env_keep`
- The JupyterHub process' environment variables that are listed in `env_keep`
- Variables to establish contact between the single-user notebook and the hub (such as JUPYTERHUB_API_TOKEN)
The `environment` configurable should be set by JupyterHub administrators to add

View File

@@ -93,7 +93,7 @@ def test_generate_config():
os.remove(cfg_file)
assert cfg_file in out
assert 'Spawner.cmd' in cfg_text
assert 'Authenticator.whitelist' in cfg_text
assert 'Authenticator.allowed' in cfg_text
async def test_init_tokens(request):

View File

@@ -6,6 +6,7 @@ from unittest import mock
import pytest
from requests import HTTPError
from traitlets.config import Config
from .mocking import MockPAMAuthenticator
from .mocking import MockStructGroup
@@ -137,8 +138,8 @@ async def test_pam_auth_admin_groups():
assert authorized['admin'] is False
async def test_pam_auth_whitelist():
authenticator = MockPAMAuthenticator(whitelist={'wash', 'kaylee'})
async def test_pam_auth_allowed():
authenticator = MockPAMAuthenticator(allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'kaylee', 'password': 'kaylee'}
)
@@ -155,11 +156,11 @@ async def test_pam_auth_whitelist():
assert authorized is None
async def test_pam_auth_group_whitelist():
async def test_pam_auth_allowed_groups():
def getgrnam(name):
return MockStructGroup('grp', ['kaylee'])
authenticator = MockPAMAuthenticator(group_whitelist={'group'})
authenticator = MockPAMAuthenticator(allowed_groups={'group'})
with mock.patch.object(authenticator, '_getgrnam', getgrnam):
authorized = await authenticator.get_authenticated_user(
@@ -174,7 +175,7 @@ async def test_pam_auth_group_whitelist():
assert authorized is None
async def test_pam_auth_blacklist():
async def test_pam_auth_blocked():
# Null case compared to next case
authenticator = MockPAMAuthenticator()
authorized = await authenticator.get_authenticated_user(
@@ -183,50 +184,41 @@ async def test_pam_auth_blacklist():
assert authorized['name'] == 'wash'
# Blacklist basics
authenticator = MockPAMAuthenticator(blacklist={'wash'})
authenticator = MockPAMAuthenticator(blocked={'wash'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'wash', 'password': 'wash'}
)
assert authorized is None
# User in both white and blacklists: default deny. Make error someday?
authenticator = MockPAMAuthenticator(
blacklist={'wash'}, whitelist={'wash', 'kaylee'}
)
# User in both allowed and blocked: default deny. Make error someday?
authenticator = MockPAMAuthenticator(blocked={'wash'}, allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'wash', 'password': 'wash'}
)
assert authorized is None
# User not in blacklist can log in
authenticator = MockPAMAuthenticator(
blacklist={'wash'}, whitelist={'wash', 'kaylee'}
)
# User not in blocked set can log in
authenticator = MockPAMAuthenticator(blocked={'wash'}, allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'kaylee', 'password': 'kaylee'}
)
assert authorized['name'] == 'kaylee'
# User in whitelist, blacklist irrelevent
authenticator = MockPAMAuthenticator(
blacklist={'mal'}, whitelist={'wash', 'kaylee'}
)
# User in allowed, blocked irrelevent
authenticator = MockPAMAuthenticator(blocked={'mal'}, allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'wash', 'password': 'wash'}
)
assert authorized['name'] == 'wash'
# User in neither list
authenticator = MockPAMAuthenticator(
blacklist={'mal'}, whitelist={'wash', 'kaylee'}
)
authenticator = MockPAMAuthenticator(blocked={'mal'}, allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'simon', 'password': 'simon'}
)
assert authorized is None
# blacklist == {}
authenticator = MockPAMAuthenticator(blacklist=set(), whitelist={'wash', 'kaylee'})
authenticator = MockPAMAuthenticator(blocked=set(), allowed={'wash', 'kaylee'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'kaylee', 'password': 'kaylee'}
)
@@ -253,7 +245,7 @@ async def test_deprecated_signatures():
async def test_pam_auth_no_such_group():
authenticator = MockPAMAuthenticator(group_whitelist={'nosuchcrazygroup'})
authenticator = MockPAMAuthenticator(allowed_groups={'nosuchcrazygroup'})
authorized = await authenticator.get_authenticated_user(
None, {'username': 'kaylee', 'password': 'kaylee'}
)
@@ -262,7 +254,7 @@ async def test_pam_auth_no_such_group():
async def test_wont_add_system_user():
user = orm.User(name='lioness4321')
authenticator = auth.PAMAuthenticator(whitelist={'mal'})
authenticator = auth.PAMAuthenticator(allowed={'mal'})
authenticator.create_system_users = False
with pytest.raises(KeyError):
await authenticator.add_user(user)
@@ -270,7 +262,7 @@ async def test_wont_add_system_user():
async def test_cant_add_system_user():
user = orm.User(name='lioness4321')
authenticator = auth.PAMAuthenticator(whitelist={'mal'})
authenticator = auth.PAMAuthenticator(allowed={'mal'})
authenticator.add_user_cmd = ['jupyterhub-fake-command']
authenticator.create_system_users = True
@@ -296,7 +288,7 @@ async def test_cant_add_system_user():
async def test_add_system_user():
user = orm.User(name='lioness4321')
authenticator = auth.PAMAuthenticator(whitelist={'mal'})
authenticator = auth.PAMAuthenticator(allowed={'mal'})
authenticator.create_system_users = True
authenticator.add_user_cmd = ['echo', '/home/USERNAME']
@@ -317,13 +309,13 @@ async def test_add_system_user():
async def test_delete_user():
user = orm.User(name='zoe')
a = MockPAMAuthenticator(whitelist={'mal'})
a = MockPAMAuthenticator(allowed={'mal'})
assert 'zoe' not in a.whitelist
assert 'zoe' not in a.allowed
await a.add_user(user)
assert 'zoe' in a.whitelist
assert 'zoe' in a.allowed
a.delete_user(user)
assert 'zoe' not in a.whitelist
assert 'zoe' not in a.allowed
def test_urls():
@@ -461,3 +453,10 @@ async def test_post_auth_hook():
)
assert authorized['testkey'] == 'testvalue'
async def test_deprecations():
cfg = Config()
cfg.Authenticator.whitelist = {'user'}
authenticator = auth.Authenticator(config=cfg)
assert authenticator.allowed == {'user'}

View File

@@ -686,7 +686,7 @@ async def test_shutdown_on_logout(app, shutdown_on_logout):
assert spawner.ready == (not shutdown_on_logout)
async def test_login_no_whitelist_adds_user(app):
async def test_login_no_allowed_adds_user(app):
auth = app.authenticator
mock_add_user = mock.Mock()
with mock.patch.object(auth, 'add_user', mock_add_user):

View File

@@ -185,7 +185,7 @@ def test_hub_authenticated(request):
m.get(good_url, text=json.dumps(mock_model))
# no whitelist
# no specific allowed user
r = requests.get(
'http://127.0.0.1:%i' % port,
cookies={'jubal': 'early'},
@@ -194,7 +194,7 @@ def test_hub_authenticated(request):
r.raise_for_status()
assert r.status_code == 200
# pass whitelist
# pass allowed user
TestHandler.hub_users = {'jubalearly'}
r = requests.get(
'http://127.0.0.1:%i' % port,
@@ -204,7 +204,7 @@ def test_hub_authenticated(request):
r.raise_for_status()
assert r.status_code == 200
# no pass whitelist
# no pass allowed ser
TestHandler.hub_users = {'kaylee'}
r = requests.get(
'http://127.0.0.1:%i' % port,
@@ -213,7 +213,7 @@ def test_hub_authenticated(request):
)
assert r.status_code == 403
# pass group whitelist
# pass allowed group
TestHandler.hub_groups = {'lions'}
r = requests.get(
'http://127.0.0.1:%i' % port,
@@ -223,7 +223,7 @@ def test_hub_authenticated(request):
r.raise_for_status()
assert r.status_code == 200
# no pass group whitelist
# no pass allowed group
TestHandler.hub_groups = {'tigers'}
r = requests.get(
'http://127.0.0.1:%i' % port,