summaryrefslogtreecommitdiff
path: root/keysync.py
blob: 8279cd50b2bbc5608ed7bae32936f92f90d82d1d (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
68
69
#!/usr/bin/env python3

"""
Cron-job that synchronizes SSH public keys for all users that have them with the
wwwmaster system.

"""

import sys
import os
import psycopg2
import configparser
import requests
import base64
import json
import time
import datetime
from Cryptodome.Cipher import AES


class KeySynchronizer(object):
    def __init__(self, db):
        self.db = db

    def sync(self):
        """
        Perform the synchronization.
        """
        curs = self.db.cursor()

        # Record synctime at *start* of sync, in case it takes some time
        synctime = datetime.datetime.now()

        # Fetch last sync date, and see if anything has changed since
        curs.execute("SELECT lastsync-'5 minutes'::interval FROM key_last_sync LIMIT 1")
        lastsync = curs.fetchone()[0]

        r = requests.get("{0}/account/auth/{1}/getkeys/{2}/".format(
            c.get('upstream', 'root'),
            c.get('upstream', 'siteid'),
            int(time.mktime(lastsync.timetuple())),
        ))
        if r.status_code != 200:
            print(("API call failed: %s" % r.status_code))
            return

        (ivs, datas) = str(r.text).split('&')
        decryptor = AES.new(base64.b64decode(c.get('upstream', 'key')),
                            AES.MODE_CBC,
                            base64.b64decode(ivs, "-_"))
        s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(b' ').decode('utf8')
        j = json.loads(s)
        for u in j:
            curs.execute("INSERT INTO git_users (user_id, sshkey) SELECT id, %(key)s FROM auth_user WHERE username=%(userid)s ON CONFLICT (user_id) DO UPDATE SET sshkey=excluded.sshkey", {
                'userid': u['u'],
                'key': u['s'],
            })

        # Flag our last sync time
        curs.execute("UPDATE key_last_sync SET lastsync=%s", [synctime])

        self.db.commit()


if __name__ == "__main__":
    c = configparser.ConfigParser()
    c.read("pggit.settings")
    db = psycopg2.connect(c.get('database', 'db'))
    KeySynchronizer(db).sync()