diff options
Diffstat (limited to 'scripts/convert-from-entitydb-to-sql.py')
-rw-r--r-- | scripts/convert-from-entitydb-to-sql.py | 145 |
1 files changed, 129 insertions, 16 deletions
diff --git a/scripts/convert-from-entitydb-to-sql.py b/scripts/convert-from-entitydb-to-sql.py index 09c5e973..b69e1ec2 100644 --- a/scripts/convert-from-entitydb-to-sql.py +++ b/scripts/convert-from-entitydb-to-sql.py @@ -21,8 +21,8 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -import sys, os, time, getopt -import rpki.config +import sys, os, time, getopt, glob, subprocess +import rpki.config, rpki.x509, rpki.relaxng from rpki.mysql_import import MySQLdb from lxml.etree import ElementTree @@ -31,24 +31,23 @@ if os.getlogin() != "sra": cfg_file = "rpki.conf" entitydb = "entitydb" +bpki = "bpki" -opts, argv = getopt.getopt(sys.argv[1:], "c:e:h?", ["config=", "entitydb=", "help"]) +opts, argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"]) for o, a in opts: if o in ("-h", "--help", "-?"): print __doc__ sys.exit(0) if o in ("-c", "--config"): cfg_file = a - elif o in ("-e", "--entitydb"): - entitydb = a if argv: sys.exit("Unexpected arguments %s" % argv) -cfg = rpki.config.parser(cfg_file, "irdbd") +cfg = rpki.config.parser(cfg_file) -sql_database = cfg.get("sql-database") -sql_username = cfg.get("sql-username") -sql_password = cfg.get("sql-password") +sql_database = cfg.get("sql-database", section = "irdbd") +sql_username = cfg.get("sql-username", section = "irdbd") +sql_password = cfg.get("sql-password", section = "irdbd") # Rename the old SQL tables, if they exist @@ -80,7 +79,8 @@ settings.configure( "USER" : sql_username, "PASSWORD" : sql_password, "HOST" : "", - "PORT" : "" }}, + "PORT" : "", + "OPTIONS" : { "init_command": "SET storage_engine=INNODB" }}}, INSTALLED_APPS = ("rpki.irdb",), ) @@ -93,8 +93,8 @@ import django.core.management django.core.management.call_command("syncdb", verbosity = 4, load_initial_data = False) # From here down will be an awful lot of messing about with XML and -# X.509 data, extracting stuff from the old database and whacking it -# into the new. Still working out these bits. +# X.509 data, extracting stuff from the old SQL database and whacking +# it into the new. Still working out these bits. xmlns = "{http://www.hactrn.net/uris/rpki/myrpki/}" @@ -110,16 +110,129 @@ tag_parent = xmlns + "parent" tag_repository = xmlns + "repository" e = ElementTree(file = os.path.join(entitydb, "identity.xml")).getroot() +rpki.relaxng.myrpki.assertValid(e) assert e.tag == tag_identity handle = e.get("handle") - -# Check handle against what's in rpki.conf? +assert handle == cfg.get("handle", section = "myrpki") # Create identity if we haven't already identity = rpki.irdb.Identity.objects.get_or_create(handle = handle)[0] +# Some BPKI utillity routines + +def read_openssl_serial(filename): + f = open(filename, "r") + text = f.read() + f.close() + return int(text.strip(), 16) + +def get_or_create_CA(purpose): + cer = rpki.x509.X509(Auto_file = os.path.join(bpki, purpose, "ca.cer")) + key = rpki.x509.RSA(Auto_file = os.path.join(bpki, purpose, "ca.key")) + crl = rpki.x509.CRL(Auto_file = os.path.join(bpki, purpose, "ca.crl")) + serial = read_openssl_serial(os.path.join(bpki, purpose, "serial")) + crl_number = read_openssl_serial(os.path.join(bpki, purpose, "crl_number")) + + return rpki.irdb.CA.objects.get_or_create(identity = identity, + purpose = rpki.irdb.CA.purpose_map[purpose], + certificate = cer.get_DER(), + private_key = key.get_DER(), + next_serial = serial, + next_crl_number = crl_number, + last_crl_update = crl.getThisUpdate().to_sql(), + next_crl_update = crl.getNextUpdate().to_sql())[0] + +def get_or_create_EECertificate(issuer, purpose): + cer = rpki.x509.X509(Auto_file = os.path.join(bpki, "servers", purpose + ".cer")) + key = rpki.x509.RSA(Auto_file = os.path.join(bpki, "servers", purpose + ".key")) + rpki.irdb.EECertificate.objects.get_or_create( + issuer = issuer, + purpose = rpki.irdb.EECertificate.purpose_map[purpose], + certificate = cer.get_DER(), + private_key = key.get_DER()) + +# Load BPKI CA data + +resource_ca = get_or_create_CA("resources") + +# Load BPKI server EE certificates and keys + +run_flags = dict((i, cfg.getboolean(i, section = "myrpki")) + for i in ("run_rpkid", "run_pubd", "run_rootd")) + +if any(run_flags.itervalues()): + server_ca = get_or_create_CA("servers") + get_or_create_EECertificate(server_ca, "irbe") + if run_flags["run_rpkid"]: + get_or_create_EECertificate(server_ca, "rpkid") + get_or_create_EECertificate(server_ca, "irdbd") + if run_flags["run_pubd"]: + get_or_create_EECertificate(server_ca, "pubd") + if run_flags["run_rootd"]: + get_or_create_EECertificate(server_ca, "rootd") +else: + server_ca = None + +# Load BSC certificates and requests + +for fn in glob.iglob(os.path.join(bpki, "resources", "bsc.*.cer")): + cer = rpki.x509.X509(Auto_file = fn) + req = rpki.x509.X509(Auto_file = fn[:-4] + ".req") + rpki.irdb.BSC.objects.get_or_create( + issuer = resource_ca, + certificate = cer.get_DER(), + pkcs10 = req.get_DER()) + + +def xcert_hash(cert): + """ + Generate the filename hash that myrpki would have generated for a + cross-certification. This is nasty, don't look. + """ + + cmd1 = ("openssl", "x509", "-noout", "-pubkey", "-subject") + cmd2 = ("openssl", "dgst", "-md5") + + env = { "PATH" : os.environ["PATH"], "OPENSSL_CONF" : "/dev/null" } + p1 = subprocess.Popen(cmd1, env = env, stdin = subprocess.PIPE, stdout = subprocess.PIPE) + p2 = subprocess.Popen(cmd2, env = env, stdin = p1.stdout, stdout = subprocess.PIPE) + p1.stdin.write(cert.get_PEM()) + p1.stdin.close() + hash = p2.stdout.read() + if p1.wait() != 0: + raise subprocess.CalledProcessError(returncode = p1.returncode, cmd = cmd1) + if p2.wait() != 0: + raise subprocess.CalledProcessError(returncode = p2.returncode, cmd = cmd2) + + hash = "".join(hash.split()) + if hash.startswith("(stdin)="): + hash = hash[len("(stdin)="):] + return hash + +# Build a table of all the cross-certified BPKI certificates. + +xcerts = {} + +for filename in glob.iglob(os.path.join("bpki", "*", "xcert.*.cer")): + h = filename.split(".")[-2] + + if not h in xcerts: + xcerts[h] = [] + xcerts[h].append(filename) + + # While we're at this, check to make sure that our reproduction of + # the hash algorithm is working correctly. + # + assert xcert_hash(rpki.x509.X509(Auto_file = filename)) == h + + + +# Somewhere around here I'm going to run out of things to do other +# than scraping through the horrible entitydb XML. Bother. + + # Copy over any ROA requests cur.execute(""" @@ -149,8 +262,8 @@ cur.execute(""" WHERE self_handle = %s AND parent_handle IS NULL """, (handle,)) for row in cur.fetchall(): - rpki.irdb.GhostbusterRequest.objects.get_or_create(identity = identity, vcard = row[0], - defaults = { "parent" : None }) + rpki.irdb.GhostbusterRequest.objects.get_or_create(identity = identity, parent = None, + vcard = row[0]) cur.close() db.close() |