diff --git a/external_scripts/dbhost/cert.py b/external_scripts/dbhost/cert.py new file mode 100755 index 0000000000000000000000000000000000000000..ab6e4eb760511d8c9fbc0cf99be36c177a427bdb --- /dev/null +++ b/external_scripts/dbhost/cert.py @@ -0,0 +1,131 @@ +#!/usr/bin/python +""" +This script will add a federation signing certificate to the database. +One required argument is the identifier of the federation. The certificate +to be added must be in the PEM format must be named upstreamCert_IDENIFIER.cer +and must be in the Certs subdirecory of your current directory. + +The database access details are below as "db, host, user", we suggest that +it is safest to use localhost as host and have the "user" access right only +from the localhost. The script will prompt for password of the user (again +for security reasons this password is not stored in the script). + +If a given federation already has a certificate in the database, the script +will ask if we want to remove or keep the other certificate. It is possible +to have more certificates than one and they will all be tried during the +validation process. This feature is meant for smooth transition form one +signing key to another. The old key should be removed after the transition +has been finalised. + +At the moment there is no script for removing the certificate, this needs +to be done manually accessing the database. Looking at the createtime field +may be helpful in selecting the right certificate to remove. +""" +import sys,re,ssl,base64,urllib2 +import MySQLdb +import os.path +import getpass +from M2Crypto import X509 +from OpenSSL import crypto + +import sys + +db = 'edugain' +host = 'localhost' +user = 'cert' +passwd = getpass.getpass() +selectcodes = "select code from federation" +select = "select code from federation where code='%s'" +exists = "select id from cert where code='%s'" +delete = "delete from cert where id='%s'" +insert = "insert into cert (code,data,sha1, sha256) values (%(code)s, %(cert)s, %(sha1)s, %(sha256)s)" +update = "update federation_status set feed_etag=null, feed_last_modified='000-00-00 00:00:00' where code='%(code)s'" + +mys = MySQLdb.connect(host, user, passwd, db) +mys.autocommit(True) +curs = mys.cursor() +curd = mys.cursor() +codes = [] + +def yn_choice(msg, default='y'): + choices = 'Y/n' if default.lower() in ('y', 'yes') else 'y/N' + choice = raw_input("%s (%s) " % (msg, choices)) + values = ('y', 'yes', '') if choices == 'Y/n' else ('y', 'yes') + return choice.strip().lower() in values + +if len(sys.argv) == 1: + print selectcodes + sys.exit(0) + cnt = curs.execute(selectcodes) + if cnt>0: + nextrow = curs.fetchone() + while nextrow: + code = None + row = nextrow + nextrow = curs.fetchone() + codes.append(row[0]) +else: + for i in range(1, len(sys.argv)): + codes.append(sys.argv[i]) +for code in codes: + try: + cnt = curs.execute(select % code) + if cnt==1: + nextrow = curs.fetchone() + while nextrow: + code = None + row = nextrow + nextrow = curs.fetchone() + if row is None: + continue + if row[0]: + code = row[0] + print 'looking for ', code, 'Certs/upstreamCert_'+code+'.cer' + if code and (os.path.isfile('Certs/upstreamCert_'+code+'.cer')): + f = open ('Certs/upstreamCert_'+code+'.cer', 'r') + cert = f.read() + cert_der = ssl.PEM_cert_to_DER_cert(cert) + x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert) + fpsha256 = x509.digest('sha256').decode().replace(':', '') + fpsha1 = x509.digest('sha1').decode().replace(':', '') + #x509 = X509.load_cert_string(cert, X509.FORMAT_PEM) + #fpsha1 = x509.get_fingerprint('sha1') + #fpsha256 = x509.get_fingerprint('sha256') + c_is = curd.execute(exists % code) + if c_is == 2: + print 'It is the next certificate for ' + code + \ + '\nWe can not register more than two certificates per federation!' + continue + if c_is: + choice = yn_choice('There is a certificate registered for ' + + code + + "\nDo you want to delete this certificate? ") + if choice: + c_nrow = curd.fetchone() + while c_nrow: + c_id = None + c_row = c_nrow + c_nrow = curd.fetchone() + if c_row is None: + continue + if c_row[0]: + print(delete % c_row[0]) + curd.execute(delete % c_row[0]) + else: + choice = yn_choice('Do you want to register this certificate and ' + + 'have temporary two certificates for ' + code + '?') + if not choice: + print code + " skipped, nothing happened" + continue + cnt = curs.execute(insert, {'code': code, 'cert': base64.b64encode(cert_der), 'sha1': fpsha1, 'sha256': fpsha256}) + print 'certificate for', code, 'added' + print(update % {'code': code}) + curs.execute(update % {'code': code}) + else: + print "Certificate not found, nothing happened" + else: + print 'No such federation: '+code + except IndexError: + print 'brak', code + +