#!/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()