From 552db9f74da9900409cbdc1e35626cd172604d04 Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Wed, 29 Aug 2018 11:04:07 -0700 Subject: [PATCH 1/2] Don't create home publicly readable World-Readable seem to be a surprising default for many people, especially in teaching context. Switch to a more reasonable rwxr-x--- We have to issue a chmod, as changing at creation time would require changin /etc/adduser.conf DIR_MODE=0760 (or whatever), but that seem unwise. We do not set the exact permission in case the DIR_MODE is more restrictive. Closing #158 --- docs/topic/security.rst | 4 ++++ tljh/user.py | 7 +++++++ 2 files changed, 11 insertions(+) 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/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): """ From 5bbba2bd7c896caa72f6157fbc75c063ddddaf2b Mon Sep 17 00:00:00 2001 From: Matthias Bussonnier Date: Fri, 31 Aug 2018 18:04:06 -0700 Subject: [PATCH 2/2] add test --- tests/test_user.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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