From 0d8b370b5d6a5a54635ad52f71bfbe2a669a208d Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 13:58:54 -0800 Subject: [PATCH 1/8] write rename_user standalone script --- scripts/rename_user.py | 37 +++++++++++++++++++++++++++++++++++++ ttadmin/users/forms.py | 1 + 2 files changed, 38 insertions(+) create mode 100644 scripts/rename_user.py diff --git a/scripts/rename_user.py b/scripts/rename_user.py new file mode 100644 index 0000000..30497e7 --- /dev/null +++ b/scripts/rename_user.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +"""This script wraps the usermod command to allow user account renames via sudoers.""" +import os +import sys +import subprocess + + +def rename_user(username, new_username): + # usermod -l new_username -m -d /home/{new_username} username + args = [ + 'usermod', + '-l', + new_username, + '-m', + '-d', + os.path.join('/home', new_username), + username + ] + subprocess.run(args, check=True) + + +def main(argv): + if len(argv) < 3: + print('[rename_user] Too few arguments passed.', file=sys.stderr) + return 1 + + try: + rename_user(argv[1], argv[2]) + except subprocess.CalledProcessError as e: + print('[rename_user] {}'.format(e), file=sys.stderr) + return 2 + + return 0 + + +if __name__ == '__main__': + exit(main(sys.argv)) diff --git a/ttadmin/users/forms.py b/ttadmin/users/forms.py index 0dcd555..9b29d3e 100644 --- a/ttadmin/users/forms.py +++ b/ttadmin/users/forms.py @@ -34,6 +34,7 @@ def validate_displayname(display_name): if not DISPLAY_NAME_RE.match(display_name): raise ValidationError("Valid characters: a-z, A-Z, 0-9, -, _, and '.") + def validate_pubkey(pubkey): # TODO see if I can get the type out key = ssh.SSHKey(pubkey, strict_mode=False, skip_option_parsing=True) From 7da85faeed9302756a020f5e44435e63c860a98a Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:31:25 -0800 Subject: [PATCH 2/8] clarify variables in rename script --- scripts/rename_user.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/rename_user.py b/scripts/rename_user.py index 30497e7..9e657e7 100644 --- a/scripts/rename_user.py +++ b/scripts/rename_user.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 -"""This script wraps the usermod command to allow user account renames via sudoers.""" +"""This script wraps the usermod command to allow user account renames via +sudoers.""" import os import sys import subprocess -def rename_user(username, new_username): - # usermod -l new_username -m -d /home/{new_username} username +def rename_user(old_username, new_username): + """Given an old and a new username, renames user on disk with usermod. + Raises if the usermod call fails.""" args = [ 'usermod', '-l', @@ -14,7 +16,7 @@ def rename_user(username, new_username): '-m', '-d', os.path.join('/home', new_username), - username + old_username ] subprocess.run(args, check=True) From f7bbdf3f0f532ca05f4899c5c14079ecb8bd22c3 Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:31:43 -0800 Subject: [PATCH 3/8] add rename ability to user model --- ttadmin/users/models.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ttadmin/users/models.py b/ttadmin/users/models.py index bcfdf50..a08da46 100644 --- a/ttadmin/users/models.py +++ b/ttadmin/users/models.py @@ -152,13 +152,25 @@ class Townie(User): return content + def rename_on_disk(self, old_username): + """Assuming that this instance has a new name set, renames this user on + disk with self.username.""" + error = _guarded_run([ + 'sudo', + '/tilde/bin/rename_user.py', + old_username, + self.username]) + if error: + logging.error(error) + return + logging.info('Renamed {} to {}'.format(old_username, self.username)) + class Pubkey(Model): key_type = CharField(max_length=50, blank=False, null=False, - choices=SSH_TYPE_CHOICES, - ) + choices=SSH_TYPE_CHOICES) key = TextField(blank=False, null=False) townie = ForeignKey(Townie) From 0a5dae85a34afc94d4e4a0be65ee90af18fb7737 Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:31:58 -0800 Subject: [PATCH 4/8] handle renaming in pre_save I chose pre_save so that if renaming fails, the db and disk remain consistent. --- ttadmin/users/models.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ttadmin/users/models.py b/ttadmin/users/models.py index a08da46..c54d077 100644 --- a/ttadmin/users/models.py +++ b/ttadmin/users/models.py @@ -200,11 +200,16 @@ def on_townie_pre_save(sender, instance, **kwargs): existing = existing[0] - if not existing.reviewed and instance.reviewed == True: + # See if we need to create this user on disk. + if not existing.reviewed and instance.reviewed is True: instance.create_on_disk() instance.send_welcome_email() instance.write_authorized_keys() + # See if this user needs a rename on disk + if existing.username != instance.username: + instance.rename_on_disk(existing.username) + def _guarded_run(cmd_args, **run_args): """Given a list of args representing a command invocation as well as var From ae4ce741ba7ab6188553f14c316388d6f30c57ce Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:32:21 -0800 Subject: [PATCH 5/8] clean up notes --- ttadmin/users/models.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ttadmin/users/models.py b/ttadmin/users/models.py index c54d077..5b42168 100644 --- a/ttadmin/users/models.py +++ b/ttadmin/users/models.py @@ -230,9 +230,6 @@ def _guarded_run(cmd_args, **run_args): # things to consider: -# * what happens when a user wants their name changed? -# * it looks like usermod -l and a mv of the home dir can change a user's username. -# * would hook this into the pre_save signal to note a username change # * what happens when a user is marked as not reviewed? # * does this signal user deletion? Or does literal Townie deletion signal # "needs to be removed from disk"? I think it makes the most sense for the @@ -242,7 +239,3 @@ def _guarded_run(cmd_args, **run_args): # think I can ignore it. # * what happens when a user needs to be banned? # * the Townie should be deleted via post_delete signal -# * what are things about a user that might change in django and require changes on disk? -# * username -# * displayname (only if i start using this?) -# * ssh key From 6ec813a328baa37d17be97274e5dd49e799fda93 Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:43:01 -0800 Subject: [PATCH 6/8] fix perms --- scripts/create_keyfile.py | 0 scripts/rename_user.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/create_keyfile.py mode change 100644 => 100755 scripts/rename_user.py diff --git a/scripts/create_keyfile.py b/scripts/create_keyfile.py old mode 100644 new mode 100755 diff --git a/scripts/rename_user.py b/scripts/rename_user.py old mode 100644 new mode 100755 From 3d58870f344968d83aa308d90db9efb5d3268a4c Mon Sep 17 00:00:00 2001 From: nate Date: Fri, 23 Feb 2018 14:48:00 -0800 Subject: [PATCH 7/8] update docs --- serversetup.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/serversetup.md b/serversetup.md index 8a87e58..6ed4a5f 100644 --- a/serversetup.md +++ b/serversetup.md @@ -14,11 +14,14 @@ * create ttadmin user * ttadmin db user (or just rely on ident..?) / database created -* copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`. -* `chmod o+x /opt/bin/create_keyfile.py`` +* copy `create_keyfile.py` from `scripts/` and put it in `/opt/bin/`. +* copy `rename_user.py` from `scripts/` and put it in `/tilde/bin/`. +* `chmod u+x /opt/bin/create_keyfile.py`` * add to sudoers: - ttadmin ALL=(ALL)NOPASSWD:/usr/sbin/adduser,/bin/mkdir,/opt/bin/create_keyfile.py + ``` + ttadmin ALL=(ALL)NOPASSWD:/usr/sbin/adduser,/bin/mkdir,/opt/bin/create_keyfile.py,/tilde/bin/rename_user.py + ``` * have virtualenv with python 3.5+ ready, install tildetown-admin package into it * run django app as wsgi container through gunicorn as the ttadmin user with venv active From 48bebb73869858ff740611352bcdc11234fe52df Mon Sep 17 00:00:00 2001 From: nate Date: Sat, 24 Feb 2018 00:14:08 -0800 Subject: [PATCH 8/8] note that we only support debian --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0eafc90..c2e7bdc 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ _Being an adminstrative tool written in Django for _. * Python 3.5+ * PostgreSQL 9+ + * Ubuntu or Debian ## Installation / setup