town/cmd/welcome
vilmibm cee8b75bad WIP on sending external email 2023-03-07 01:06:46 +00:00
..
README.md WIP on welcome tool 2023-02-26 08:57:46 +00:00
form.go CoC prompt 2023-03-06 21:00:59 +00:00
main.go WIP on sending external email 2023-03-07 01:06:46 +00:00
welcome.txt WIP on welcome tool 2023-02-26 08:57:46 +00:00

README.md

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
  5. 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,/bin/mkdir,/town/bin/generate_welcome_present.sh,/town/bin/create_keyfile

though I will likely move welcome_present generation inline to welcome itself.

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.