From: Magnus Hagander Date: Sun, 10 Dec 2017 16:22:09 +0000 (+0100) Subject: Synchronize ssh keys using http API instead of postgresql call X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=8e236188422f816003bed82413e36b5e18c4e3d5;p=pggit.git Synchronize ssh keys using http API instead of postgresql call Finally break the ties with community auth 1.0 --- diff --git a/keysync.py b/keysync.py index 50e17b5..0fff2f0 100644 --- a/keysync.py +++ b/keysync.py @@ -9,7 +9,13 @@ wwwmaster system. import sys import os import psycopg2 -import ConfigParser +import ConfigParser +import requests +import base64 +import json +import time +import datetime +from Crypto.Cipher import AES class KeySynchronizer(object): def __init__(self, db): @@ -17,40 +23,39 @@ class KeySynchronizer(object): def sync(self): """ - Perform the synchronization. This is going to be rather inefficient - we just - load up the complete list of users in memory, and then write it to a local table. - - There's not likely (TM) to ever be a lot of data... + Perform the synchronization. """ - masterpg = psycopg2.connect(c.get('database','masterdb')) curs = self.db.cursor() - mcurs = masterpg.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 FROM key_last_sync LIMIT 1") + curs.execute("SELECT lastsync-'5 minutes'::interval FROM key_last_sync LIMIT 1") lastsync = curs.fetchone()[0] - mcurs.execute("SELECT CURRENT_TIMESTAMP, CASE WHEN EXISTS (SELECT * FROM users_keys WHERE sshkey_last_update >= %s) THEN 1 ELSE 0 END", [lastsync]) - synctime, hasupd = mcurs.fetchone() - if hasupd == 0: - return # Nothing changed, just get out - - # Fetch a list of all keys on the master server - mcurs.execute("SELECT userid, sshkey FROM users_keys") - allkeys = mcurs.fetchall() - mcurs.close() - masterpg.close() - - # Load them into the local table - curs.execute("TRUNCATE TABLE git_users") - for row in allkeys: - curs.execute("INSERT INTO git_users (userid, sshkey) VALUES (%s,%s)", row) - - # If there ever turns out to be a bunch, better analyze - curs.execute("ANALYZE git_users") - - # Note the fact that we have synced (note that we use the timestamp value from the master, - # in case there is clock skew) + 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(' ') + j = json.loads(s) + for u in j: + curs.execute("INSERT INTO git_users (userid, sshkey) VALUES (%(userid)s, %(key)s) ON CONFLICT (userid) 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() diff --git a/pggit.settings.sample b/pggit.settings.sample index 3b748e1..d5c484b 100644 --- a/pggit.settings.sample +++ b/pggit.settings.sample @@ -1,7 +1,10 @@ [database] db=dbname=pggit host=/tmp/ user=mha -;masterdb=hostname=wwwmaster.postgresql.org dbname=186_www user=auth_svc -masterdb=dbname=186_www host=/tmp/ user=mha + +[upstream] +root=http://localhost:8000 +siteid=1 +key=secret [user] user=pggit