diff --git a/docs/topic/security.rst b/docs/topic/security.rst index e540f31..4c98ba7 100644 --- a/docs/topic/security.rst +++ b/docs/topic/security.rst @@ -22,6 +22,10 @@ permissions. #. A home directory is created for the user under ``/home/jupyter-``. +#. The default permission of the home directory is change with ``o-rwx`` (remove + non-group members the ability to read, write or list files and folders in the + Home directory). + #. No password is set for this unix system user by default. The password used to log in to JupyterHub (if using an authenticator that requires a password) is not related to the unix user's password in any form. diff --git a/tests/test_user.py b/tests/test_user.py index 53c6772..0cc079a 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -3,6 +3,8 @@ Test wrappers in tljw.user module """ from tljh import user import os +import os.path +import stat import uuid import pwd import grp @@ -23,9 +25,16 @@ def test_ensure_user(): # Create user! user.ensure_user(username) # This raises exception if user doesn't exist - ent = pwd.getpwnam(username) + entry = pwd.getpwnam(username) # Home directory must also exist - assert os.path.exists(ent.pw_dir) + home_dir = entry.pw_dir + assert os.path.exists(home_dir) + # Ensure not word readable/writable especially in teaching context + homedir_stats = os.stat(home_dir).st_mode + assert not (homedir_stats & stat.S_IROTH), "Everyone should not be able to read users home directory" + assert not (homedir_stats & stat.S_IWOTH), "Everyone should not be able to write users home directory" + assert not (homedir_stats & stat.S_IXOTH), "Everyone should not be able to list what is in users home directory" + # Run ensure_user again, should be a noop user.ensure_user(username) # User still exists, after our second ensure_user call diff --git a/tljh/user.py b/tljh/user.py index 6b7ca0c..ef946e3 100644 --- a/tljh/user.py +++ b/tljh/user.py @@ -6,6 +6,7 @@ Supports minimal user & group management import pwd import grp import subprocess +from os.path import expanduser def ensure_user(username): @@ -27,6 +28,12 @@ def ensure_user(username): username ]) + subprocess.check_call([ + 'chmod', + 'o-rwx', + expanduser('~{username}'.format(username=username)) + ]) + def remove_user(username): """