Normalize unix usernames to be under 32char

JupyterHub usernames do not have this restriction,
causing user creation to fail when usernames are too large.
This commit is contained in:
yuvipanda
2018-09-12 16:46:59 -07:00
parent f163f62c89
commit 9b0248e0c3
3 changed files with 58 additions and 5 deletions

24
tests/test_normalize.py Normal file
View File

@@ -0,0 +1,24 @@
"""
Test functions for normalizing various kinds of values
"""
from tljh.normalize import generate_system_username
def test_generate_username():
"""
Test generating system usernames from hub usernames
"""
usernames = {
# Very short
'jupyter-test': 'jupyter-test',
# Very long
'jupyter-aelie9sohjeequ9iemeipuimuoshahz4aitugiuteeg4ohioh5yuiha6aei7te5z': 'jupyter-aelie9sohjeequ9iem-4b726',
# 26 characters, just below our cutoff for hashing
'jupyter-abcdefghijklmnopq': 'jupyter-abcdefghijklmnopq',
# 27 characters, just above our cutoff for hashing
'jupyter-abcdefghijklmnopqr': 'jupyter-abcdefghijklmnopqr-e375e',
}
for hub_user, system_user in usernames.items():
assert generate_system_username(hub_user) == system_user
assert len(system_user) <= 32

View File

@@ -7,17 +7,23 @@ import yaml
from glob import glob from glob import glob
from systemdspawner import SystemdSpawner from systemdspawner import SystemdSpawner
from tljh import user, configurer from tljh import configurer, user
from tljh.config import INSTALL_PREFIX, USER_ENV_PREFIX, CONFIG_DIR from tljh.config import INSTALL_PREFIX, USER_ENV_PREFIX, CONFIG_DIR
from tljh.normalize import generate_system_username
class CustomSpawner(SystemdSpawner): class UserCreatingSpawner(SystemdSpawner):
"""
SystemdSpawner with user creation on spawn.
FIXME: Remove this somehow?
"""
def start(self): def start(self):
""" """
Perform system user activities before starting server Perform system user activities before starting server
""" """
# FIXME: Move this elsewhere? Into the Authenticator? # FIXME: Move this elsewhere? Into the Authenticator?
system_username = 'jupyter-' + self.user.name system_username = generate_system_username('jupyter-' + self.user.name)
user.ensure_user(system_username) user.ensure_user(system_username)
user.ensure_user_group(system_username, 'jupyterhub-users') user.ensure_user_group(system_username, 'jupyterhub-users')
if self.user.admin: if self.user.admin:
@@ -26,8 +32,7 @@ class CustomSpawner(SystemdSpawner):
user.remove_user_group(system_username, 'jupyterhub-admins') user.remove_user_group(system_username, 'jupyterhub-admins')
return super().start() return super().start()
c.JupyterHub.spawner_class = UserCreatingSpawner
c.JupyterHub.spawner_class = CustomSpawner
# leave users running when the Hub restarts # leave users running when the Hub restarts
c.JupyterHub.cleanup_servers = False c.JupyterHub.cleanup_servers = False

24
tljh/normalize.py Normal file
View File

@@ -0,0 +1,24 @@
"""
Functions to normalize various inputs
"""
import hashlib
def generate_system_username(username):
"""
Generate a posix username from given username.
If username < 26 char, we just return it.
Else, we hash the username, truncate username at
26 char, append a '-' and first add 5char of hash.
This makes sure our usernames are always under 32char.
"""
if len(username) < 26:
return username
userhash = hashlib.sha256(username.encode('utf-8')).hexdigest()
return '{username_trunc}-{hash}'.format(
username_trunc=username[:26],
hash=userhash[:5]
)