aboutsummaryrefslogtreecommitdiff
path: root/scripts/convert-from-csv-to-entitydb.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/convert-from-csv-to-entitydb.py')
-rw-r--r--scripts/convert-from-csv-to-entitydb.py233
1 files changed, 233 insertions, 0 deletions
diff --git a/scripts/convert-from-csv-to-entitydb.py b/scripts/convert-from-csv-to-entitydb.py
new file mode 100644
index 00000000..282d2e75
--- /dev/null
+++ b/scripts/convert-from-csv-to-entitydb.py
@@ -0,0 +1,233 @@
+"""
+Convert {parents,children,pubclients}.csv into new XML formats.
+
+$Id$
+
+Copyright (C) 2010 Internet Systems Consortium ("ISC")
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+"""
+
+import subprocess, csv, re, os, getopt, sys, base64, urlparse
+import rpki.sundial, myrpki, rpki.config
+
+from lxml.etree import Element, SubElement, ElementTree
+
+section_regexp = re.compile("\s*\[\s*(.+?)\s*\]\s*$")
+variable_regexp = re.compile("\s*([-a-zA-Z0-9_]+)(\s*=\s*)(.+?)\s*$")
+
+cfg_file = "myrpki.conf"
+template_file = os.path.join(os.path.dirname(sys.argv[0]), "examples", "myrpki.conf")
+new_cfg_file = None
+preserve_valid_until = False
+
+opts, argv = getopt.getopt(sys.argv[1:], "c:hn:pt:?", ["config=", "new_config=", "preserve_valid_until", "template_config=", "help"])
+for o, a in opts:
+ if o in ("-h", "--help", "-?"):
+ print __doc__
+ sys.exit(0)
+ elif o in ("-c", "--config"):
+ cfg_file = a
+ elif o in ("-n", "--new_config"):
+ new_cfg_file = a
+ elif o in ("-p", "--preserve_valid_until"):
+ preserve_valid_until = True
+ elif o in ("-t", "--template_config"):
+ template_file = a
+if argv:
+ raise RuntimeError, "Unexpected arguments %r" % (argv,)
+if os.path.samefile(cfg_file, template_file):
+ raise RuntimeError, "Old config and template for new config can't be the same file"
+if new_cfg_file is None:
+ new_cfg_file = cfg_file + ".new"
+if os.path.exists(new_cfg_file):
+ raise RuntimeError, "%s already exists, NOT overwriting" % new_cfg_file
+
+cfg = rpki.config.parser(cfg_file)
+
+# These have no counterparts in new config file, just read them from old
+
+repository_bpki_certificate = cfg.get(option = "repository_bpki_certificate", section = "myrpki")
+repository_handle = cfg.get(option = "repository_handle", section = "myrpki")
+parents_csv = cfg.get(option = "parents_csv", section = "myrpki", default = "parents.csv")
+children_csv = cfg.get(option = "children_csv", section = "myrpki", default = "children.csv")
+pubclients_csv = cfg.get(option = "pubclients_csv", section = "myrpki", default = "pubclients.csv")
+pubd_base = cfg.get(option = "pubd_base", section = "myirbe")
+
+# Here we need to construct values for the new config file from the
+# old one. Basic model here is to look at whatever variables need to
+# be set in the template (mostly just the [myrpki], I hope), pull
+# necessary data from old config file any way we can. Stuff that
+# didn't make the jump from old config file to new we can just ignore,
+# stuff that is automated via macro expansions in the new config file
+# should be ok without modification.
+
+r = {}
+
+if cfg.has_section("myrpki"):
+ for i in ("handle", "roa_csv", "prefix_csv", "asn_csv", "xml_filename"):
+ r["myrpki", i] = cfg.get(section = "myrpki", option = i)
+ r["myrpki", "bpki_resources_directory"] = cfg.get(option = "bpki_directory", section = "myrpki")
+
+if cfg.has_section("myirbe"):
+ r["myrpki", "bpki_servers_directory"] = cfg.get(option = "bpki_directory", section = "myirbe")
+ r["myrpki", "run_rpkid"] = True
+ r["myrpki", "run_pubd"] = cfg.getboolean(option = "want_pubd", section = "myirbe", default = False)
+ r["myrpki", "run_rootd"] = cfg.getboolean(option = "want_rootd", section = "myirbe", default = False)
+else:
+ for i in ("run_rpkid", "run_pubd", "run_rootd"):
+ r["myrpki", i] = False
+
+if cfg.has_section("rpkid"):
+ r["myrpki", "rpkid_server_host"] = cfg.get(option = "server-host", section = "rpkid")
+ r["myrpki", "rpkid_server_port"] = cfg.get(option = "server-port", section = "rpkid")
+
+if cfg.has_section("irdbd"):
+ u = urlparse.urlparse(cfg.get(option = "https-url", section = "irdbd"))
+ r["myrpki", "irdbd_server_host"] = u.hostname or "localhost"
+ r["myrpki", "irdbd_server_port"] = u.port or 443
+
+if cfg.has_section("pubd"):
+ r["myrpki", "pubd_server_host"] = cfg.get(option = "server-host", section = "pubd")
+ r["myrpki", "pubd_server_port"] = cfg.get(option = "server-port", section = "pubd")
+ r["myrpki", "publication_base_directory"] = cfg.get(option = "publication-base", section = "pubd")
+
+if cfg.has_section("rootd"):
+ r["myrpki", "rootd_server_port"] = cfg.get(option = "server-port", section = "rootd")
+ u = urlparse.urlparse(cfg.get(option = "rpki-base-uri", section = "rootd"))
+ r["myrpki", "publication_rsync_server"] = u.netloc
+
+for i in ("rpkid", "irdbd", "pubd"):
+ if cfg.has_section(i):
+ for j in ("sql-database", "sql-username", "sql-password"):
+ r[i, j] = cfg.get(section = i, option = j)
+
+f = open(new_cfg_file, "w")
+f.write("# Automatically converted from %s using %s as a template.\n\n" % (cfg_file, template_file))
+section = None
+for line in open(template_file):
+ m = section_regexp.match(line)
+ if m:
+ section = m.group(1)
+ m = variable_regexp.match(line)
+ if m:
+ option, whitespace = m.group(1, 2)
+ else:
+ option = None
+ if (section, option) in r:
+ line = "%s%s%s\n" % (option, whitespace, r[section, option])
+ f.write(line)
+f.close()
+print "Wrote", new_cfg_file
+
+# Get all of these from the new config file; in theory we just set all
+# of them, but we want to use values matching new config in any case.
+
+newcfg = rpki.config.parser(new_cfg_file, "myrpki")
+
+handle = newcfg.get("handle")
+bpki_resources_directory = newcfg.get("bpki_resources_directory")
+bpki_servers_directory = newcfg.get("bpki_servers_directory")
+pubd_server_host = newcfg.get("pubd_server_host")
+pubd_server_port = newcfg.get("pubd_server_port")
+rpkid_server_host = newcfg.get("rpkid_server_host")
+rpkid_server_port = newcfg.get("rpkid_server_port")
+entitydb_dir = newcfg.get("entitydb_dir", "entitydb")
+
+bpki_resources_pemfile = bpki_resources_directory + "/ca.cer"
+bpki_servers_pemfile = bpki_servers_directory + "/ca.cer"
+
+def entitydb(*args):
+ return os.path.join(entitydb_dir, *args)
+
+# Now convert the .csv files. It'd be nice to have XML validation
+# enabled for this, so try to turn it on ourselves if the magic
+# environment variable hasn't already been set.
+
+rng_file = os.path.join(os.path.dirname(sys.argv[0]), "myrpki.rng")
+if not os.getenv("MYRPKI_RNG") and os.path.exists(rng_file):
+ os.putenv("MYRPKI_RNG", rng_file)
+
+for d in map(entitydb, ("children", "parents", "repositories", "pubclients")):
+ if not os.path.exists(d):
+ os.makedirs(d)
+
+one_year_from_now = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365))
+
+if os.path.exists(children_csv):
+ for child_handle, valid_until, child_resource_pemfile in myrpki.csv_reader(children_csv, columns = 3):
+ try:
+
+ e = Element("parent",
+ valid_until = valid_until if preserve_valid_until else one_year_from_now,
+ service_uri = "https://%s:%s/up-down/%s/%s" % (rpkid_server_host, rpkid_server_port, handle, child_handle),
+ child_handle = child_handle,
+ parent_handle = handle)
+ myrpki.PEMElement(e, "bpki_resource_ta", bpki_resources_pemfile)
+ myrpki.PEMElement(e, "bpki_server_ta", bpki_servers_pemfile)
+ myrpki.PEMElement(e, "bpki_child_ta", child_resource_pemfile)
+ myrpki.etree_write(e, entitydb("children", "%s.xml" % child_handle))
+
+ except IOError:
+ pass
+
+if os.path.exists(parents_csv):
+ for parent_handle, parent_service_uri, parent_cms_pemfile, parent_https_pemfile, parent_myhandle, parent_sia_base in myrpki.csv_reader(parents_csv, columns = 6):
+ try:
+
+ e = Element("parent",
+ valid_until = one_year_from_now,
+ service_uri = parent_service_uri,
+ child_handle = parent_myhandle,
+ parent_handle = parent_handle)
+ myrpki.PEMElement(e, "bpki_resource_ta", parent_cms_pemfile)
+ myrpki.PEMElement(e, "bpki_server_ta", parent_https_pemfile)
+ myrpki.PEMElement(e, "bpki_child_ta", bpki_resources_pemfile)
+ myrpki.etree_write(e, entitydb("parents", "%s.xml" % parent_handle))
+
+ client_handle = "/".join(parent_sia_base.rstrip("/").split("/")[3:])
+ assert client_handle.startswith(repository_handle)
+
+ e = Element("repository",
+ parent_handle = parent_handle,
+ client_handle = client_handle,
+ service_uri = "%s/client/%s" % (pubd_base.rstrip("/"), client_handle),
+ sia_base = parent_sia_base,
+ type = "confirmed")
+ myrpki.PEMElement(e, "bpki_server_ta", repository_bpki_certificate)
+ myrpki.PEMElement(e, "bpki_client_ta", bpki_resources_pemfile)
+ SubElement(e, "contact_info").text = "Automatically generated by convert-csv.py"
+ myrpki.etree_write(e, entitydb("repositories", "%s.xml" % parent_handle))
+
+ except IOError:
+ pass
+
+if os.path.exists(pubclients_csv):
+ for client_handle, client_resource_pemfile, client_sia_base in myrpki.csv_reader(pubclients_csv, columns = 3):
+ try:
+
+ parent_handle = client_handle.split("/")[-2] if "/" in client_handle else handle
+
+ e = Element("repository",
+ parent_handle = parent_handle,
+ client_handle = client_handle,
+ service_uri = "https://%s:%s/client/%s" % (pubd_server_host, pubd_server_port, client_handle),
+ sia_base = client_sia_base,
+ type = "confirmed")
+ myrpki.PEMElement(e, "bpki_server_ta", bpki_servers_pemfile)
+ myrpki.PEMElement(e, "bpki_client_ta", client_resource_pemfile)
+ SubElement(e, "contact_info").text = "Automatically generated by convert-csv.py"
+ myrpki.etree_write(e, entitydb("pubclients", "%s.xml" % client_handle.replace("/", ".")))
+
+ except IOError:
+ pass