mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-13 13:03:01 +00:00
Merge pull request #1828 from rkdarst/authenthicator_blacklist
Authenthicator blacklist
This commit is contained in:
@@ -88,6 +88,20 @@ class Authenticator(LoggingConfigurable):
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
blacklist = Set(
|
||||
help="""
|
||||
Blacklist 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
|
||||
authenticator has in place.
|
||||
|
||||
If empty, does not perform any additional restriction.
|
||||
|
||||
.. versionadded: 0.9
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
@observe('whitelist')
|
||||
def _check_whitelist(self, change):
|
||||
short_names = [name for name in change['new'] if len(name) <= 1]
|
||||
@@ -205,6 +219,21 @@ class Authenticator(LoggingConfigurable):
|
||||
return True
|
||||
return username in self.whitelist
|
||||
|
||||
def check_blacklist(self, username):
|
||||
"""Check if a username is blocked to authenticate based on blacklist configuration
|
||||
|
||||
Return True if username is allowed, False otherwise.
|
||||
No blacklist means any username is allowed.
|
||||
|
||||
Names are normalized *before* being checked against the blacklist.
|
||||
|
||||
.. versionadded: 0.9
|
||||
"""
|
||||
if not self.blacklist:
|
||||
# No blacklist means any name is allowed
|
||||
return True
|
||||
return username not in self.blacklist
|
||||
|
||||
async def get_authenticated_user(self, handler, data):
|
||||
"""Authenticate the user who is attempting to log in
|
||||
|
||||
@@ -244,7 +273,14 @@ class Authenticator(LoggingConfigurable):
|
||||
self.log.warning("Disallowing invalid username %r.", username)
|
||||
return
|
||||
|
||||
blacklist_pass = await maybe_future(self.check_blacklist(username))
|
||||
whitelist_pass = await maybe_future(self.check_whitelist(username))
|
||||
if blacklist_pass:
|
||||
pass
|
||||
else:
|
||||
self.log.warning("User %r in blacklist. Stop authentication", username)
|
||||
return
|
||||
|
||||
if whitelist_pass:
|
||||
return authenticated
|
||||
else:
|
||||
|
@@ -103,6 +103,65 @@ def test_pam_auth_group_whitelist():
|
||||
assert authorized is None
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_pam_auth_blacklist():
|
||||
# Null case compared to next case
|
||||
authenticator = MockPAMAuthenticator()
|
||||
authorized = yield authenticator.get_authenticated_user(None, {
|
||||
'username': 'wash',
|
||||
'password': 'wash',
|
||||
})
|
||||
assert authorized['name'] == 'wash'
|
||||
|
||||
# Blacklist basics
|
||||
authenticator = MockPAMAuthenticator(blacklist={'wash'})
|
||||
authorized = yield 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'})
|
||||
authorized = yield 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'})
|
||||
authorized = yield 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'})
|
||||
authorized = yield authenticator.get_authenticated_user(None, {
|
||||
'username': 'wash',
|
||||
'password': 'wash',
|
||||
})
|
||||
assert authorized['name'] == 'wash'
|
||||
|
||||
# User in neither list
|
||||
authenticator = MockPAMAuthenticator(blacklist={'mal'}, whitelist={'wash', 'kaylee'})
|
||||
authorized = yield authenticator.get_authenticated_user(None, {
|
||||
'username': 'simon',
|
||||
'password': 'simon',
|
||||
})
|
||||
assert authorized is None
|
||||
|
||||
# blacklist == {}
|
||||
authenticator = MockPAMAuthenticator(blacklist=set(), whitelist={'wash', 'kaylee'})
|
||||
authorized = yield authenticator.get_authenticated_user(None, {
|
||||
'username': 'kaylee',
|
||||
'password': 'kaylee',
|
||||
})
|
||||
assert authorized['name'] == 'kaylee'
|
||||
|
||||
|
||||
@pytest.mark.gen_test
|
||||
def test_pam_auth_no_such_group():
|
||||
authenticator = MockPAMAuthenticator(group_whitelist={'nosuchcrazygroup'})
|
||||
|
Reference in New Issue
Block a user