town/external/cmd/welcome/README.md

3.7 KiB

welcome command

this command is used to exchange a town invite token for a user account. it is responsible for:

  1. accepting and validating an invite token generated by the review command
  2. accepting and validating a new user's username choice (ie enforcing rules and checking for dupes)
  3. accepting and validating a user's email for use in account recovery (defaulting to an email embedded in the invite token)
  4. accepting and validating a display name (PUT OFF)
  5. Confirming that a user agrees to our CoC
  6. accepting and validating a user's public ssh key

upon receipt of these things a user account is created. if it fails, the user is told about the failure and told to email root@tilde.town for guidance; us admins get a local mail about the problem.

upon successful creation, welcome prints a message on STDOUT suggesting how to log in then quits.

It is risky to let welcome create users but no riskier at a high level than the Django admin we had. I can re-use the sudoers trick I did there for the welcome user.

an invite token

an invite token consists of two pieces that are then base64 encoded. the first piece is a random string of 30 characters (alphanumeric and symbols except space) and the second is an email address the invite was sent to; they are separated by a space.

sudoers config

something like:

welcome ALL=(ALL)NOPASSWD:/usr/sbin/adduser,/usr/sbin/usermod,/town/bin/createkeyfile,/town/bin/generate_welcome_present.sh,/town/bin/registeruser

I'd like to consolidate adduser/usermod calls into a single "createuser" helper. I'd also like to move the welcome present generation into welcome. TODO.

user creation flow

once we accept what we need from the user accepting an invite, the flow looks like:

  1. create user account a. run adduser, set shell and displayname b. add user to town group
  2. write authorized keys a. create ~/.ssh b. write ~/.ssh/authorized_keys2 and put their key in there c. write blank ~/.ssh/authorized_keys with note about adding custom keys
  3. generate welcome gift
  4. alert hooks (more of a future idea; but it would be nice to have a "WELCOME NEW USER!" in the mailing list / IRC / etc)

creating keyfiles

A frustrating hurdle is that welcome, just like ttadmin, has to write a keyfile that is perms 600 for the new user. This is annoying as shit and requires running sudo as the new user. In the old python code:

def write_authorized_keys(self):
    # Write out authorized_keys file
    # Why is this a call out to a python script? There's no secure way with
    # sudoers to allow this code to write to a file; if this code was to be
    # compromised, the ability to write arbitrary files with sudo is a TKO.
    # By putting the ssh key file creation into its own script, we can just
    # give sudo access for that one command to this code.
    #
    # We could put the other stuff from here into that script and then only
    # grant sudo for the script, but then we're moving code out of this
    # virtual-env contained, maintainable thing into a script. it's my
    # preference to have the script be as minimal as possible.
    with TemporaryFile(dir="/tmp") as fp:
        fp.write(self.generate_authorized_keys().encode('utf-8'))
        fp.seek(0)
        error = _guarded_run(['sudo',
                              '--user={}'.format(self.username),
                              '/town/src/tildetown-admin/scripts/create_keyfile.py',
                              self.username],
                             stdin=fp)
        if error:
            logger.error(error)

this warrants porting create_keyfile.py to a new Go program that can live at /town/bin/create_keyfile or wherever.