summaryrefslogtreecommitdiff
path: root/newuser.py
blob: 4e0a0cd37af79e8af06efcb66f88b49365efcf6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#! /usr/bin/env python

from subprocess import call
import base64

import gnupg # python-gnupg

root_user_fs_path = './user_fses/'
root_repo_path = './repos/'

authorized_keys_base = '/var/authorized_keys/'

gpg = gnupg.GPG(gnupghome='/does/not/exist')

def recv_keys(gpg_key_path, ssh_key_path):
    fingerprint = full_fingerprint(gpg_key_path)
    username = tiny_gpg_fingerprint(fingerprint)
    alloc_user(username)
    add_key(username, ssh_key_path)
    print("gpg key: %s, ssh key: %s" % (gpg_key_path, ssh_key_path))
    print("username: %s, gpg fingerprint: %s" % (username, fingerprint))
    return True

def full_fingerprint(gpg_key_path):
    keys = gpg.scan_keys(gpg_key_path)
    if (len(keys) == 0):
        raise "hell"
    if (len(keys) != 1):
        raise "the roof"
    return keys[0]["fingerprint"]

# the s/./=/g thing here is because
# = is apparently not valid in a username!
# but having the padding around is nice. so keep it.
# so turn it into valid characters!
def untiny_gpg_fingerprint(tiny):
    return binascii.unhexlify(
        base64.b64decode(tiny.replace('.', '='), '-_')
    )

def tiny_gpg_fingerprint(raw_fingerprint):
    fingerprint_bytes = raw_fingerprint.decode('hex')
    return base64.b64encode(fingerprint_bytes, '-_').replace('=', '.')

def add_key(username, ssh_key_path):
    with open(ssh_key_path, 'r') as key_file:
        ssh_key = key_file.read()
        with open(authorized_keys_base + username, 'a+') as user_authorized_keys:
            user_authorized_keys.write(ssh_key)
    return True

def alloc_user(username):

    if username == '':
        raise Exception("Username must not be empty and must be alphanumeric (but it's derived from your full gpg key id, so how did you do that?")

    fs_path = root_user_fs_path + username
    repo_path = root_repo_path + username
# [D]on't give a password (ssh login only)
# Don't create a [H]ome directory
# Set the login [s]hell to a non-shell to disallow logins
    call(['adduser', '-D', '-H', '-s', '/bin/false', username])
    call(['dd', 'if=/dev/zero', 'of=' + fs_path, 'bs=4096', 'count=32768'])
    call(['mkfs.ext4', '-q', fs_path])
    call(['mkdir', repo_path])
    call(['mount', '-o', 'loop,rw', fs_path, repo_path + '/'])
    call(['touch', repo_path + '/git-daemon-export-ok'])