aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--myrpki.rototill/myirbe.py476
-rw-r--r--myrpki.rototill/myrpki.py886
-rw-r--r--myrpki.rototill/setup.py357
-rw-r--r--myrpki.rototill/yamltest.py14
4 files changed, 834 insertions, 899 deletions
diff --git a/myrpki.rototill/myirbe.py b/myrpki.rototill/myirbe.py
deleted file mode 100644
index d9c75ddc..00000000
--- a/myrpki.rototill/myirbe.py
+++ /dev/null
@@ -1,476 +0,0 @@
-"""
-IRBE-side stuff for myrpki tools.
-
-The basic model here is that each entity with resources to certify
-runs the myrpki tool, but not all of them necessarily run their own
-RPKi engines. The entities that do run RPKI engines get data from the
-entities they host via the XML files output by the myrpki tool. Those
-XML files are the input to this script, which uses them to do all the
-work of constructing certificates, populating SQL databases, and so
-forth. A few operations (eg, BSC construction) generate data which
-has to be shipped back to the resource holder, which we do by updating
-the same XML file.
-
-In essence, the XML files are a sneakernet (or email, or carrier
-pigeon) communication channel between the resource holders and the
-RPKI engine operators.
-
-As a convenience, for the normal case where the RPKI engine operator
-is itself a resource holder, this script also runs the myrpki script
-directly to process the RPKI engine operator's own resources.
-
-Note that, due to the back and forth nature of some of these
-operations, it may take several cycles for data structures to stablize
-and everything to reach a steady state. This is normal.
-
-
-$Id$
-
-Copyright (C) 2009 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.
-"""
-
-from __future__ import with_statement
-
-import base64, subprocess, sys, os, time, re, getopt, warnings, glob
-import rpki.https, rpki.config, rpki.resource_set, rpki.relaxng
-import rpki.exceptions, rpki.left_right, rpki.log, rpki.x509, rpki.async
-import myrpki
-
-from lxml.etree import Element, SubElement, ElementTree
-
-# Silence warning while loading MySQLdb in Python 2.6, sigh
-if hasattr(warnings, "catch_warnings"):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- import MySQLdb
-else:
- import MySQLdb
-
-def findbase64(tree, name, b64type = rpki.x509.X509):
- """
- Find and extract a base64-encoded XML element, if present.
- """
- x = tree.findtext(name)
- return b64type(Base64 = x) if x else None
-
-# For simple cases we don't really care what this value is, so long as
-# we're consistant about it, so wiring this in is fine.
-
-bsc_handle = "bsc"
-
-os.environ["TZ"] = "UTC"
-time.tzset()
-
-rpki.log.init("myirbe")
-
-cfg_file = "myrpki.conf"
-
-opts, argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"])
-for o, a in opts:
- if o in ("-c", "--config"):
- cfg_file = a
- elif o in ("-h", "--help", "-?"):
- print __doc__
- sys.exit(0)
-
-cfg = rpki.config.parser(cfg_file, "myrpki")
-
-cfg.set_global_flags()
-
-myrpki.openssl = cfg.get("openssl", "openssl", "myrpki")
-
-handle = cfg.get("handle", cfg.get("handle", "Amnesiac", "myrpki"))
-
-run_pubd = cfg.getboolean("run_pubd", False)
-run_rootd = cfg.getboolean("run_rootd", False)
-
-bpki = myrpki.CA(cfg_file, cfg.get("bpki_servers_directory"))
-
-# Default values for CRL parameters are very low, for testing.
-
-self_crl_interval = cfg.getint("self_crl_interval", 900)
-self_regen_margin = cfg.getint("self_regen_margin", 300)
-pubd_base = cfg.get("pubd_base").rstrip("/") + "/"
-rpkid_base = cfg.get("rpkid_base").rstrip("/") + "/"
-
-# Nasty regexp for parsing rpkid's up-down service URLs.
-
-updown_regexp = re.compile(re.escape(rpkid_base) + "up-down/([-A-Z0-9_]+)/([-A-Z0-9_]+)$", re.I)
-
-# Wrappers to simplify calling rpkid and pubd.
-
-call_rpkid = rpki.async.sync_wrapper(rpki.https.caller(
- proto = rpki.left_right,
- client_key = rpki.x509.RSA( PEM_file = bpki.dir + "/irbe.key"),
- client_cert = rpki.x509.X509(PEM_file = bpki.dir + "/irbe.cer"),
- server_ta = rpki.x509.X509(PEM_file = bpki.cer),
- server_cert = rpki.x509.X509(PEM_file = bpki.dir + "/rpkid.cer"),
- url = rpkid_base + "left-right",
- debug = True))
-
-if run_pubd:
-
- call_pubd = rpki.async.sync_wrapper(rpki.https.caller(
- proto = rpki.publication,
- client_key = rpki.x509.RSA( PEM_file = bpki.dir + "/irbe.key"),
- client_cert = rpki.x509.X509(PEM_file = bpki.dir + "/irbe.cer"),
- server_ta = rpki.x509.X509(PEM_file = bpki.cer),
- server_cert = rpki.x509.X509(PEM_file = bpki.dir + "/pubd.cer"),
- url = pubd_base + "control",
- debug = True))
-
- # Make sure that pubd's BPKI CRL is up to date.
-
- call_pubd(rpki.publication.config_elt.make_pdu(
- action = "set",
- bpki_crl = rpki.x509.CRL(PEM_file = bpki.crl)))
-
-irdbd_cfg = rpki.config.parser(cfg.get("irdbd_conf", cfg_file), "irdbd")
-
-db = MySQLdb.connect(user = irdbd_cfg.get("sql-username"),
- db = irdbd_cfg.get("sql-database"),
- passwd = irdbd_cfg.get("sql-password"))
-
-cur = db.cursor()
-
-entitydb = myrpki.EntityDB(cfg)
-
-xmlfiles = []
-
-# If [myrpki] section includes an "xml_filename" setting, run
-# myrpki.py internally, as a convenience, and include its output at
-# the head of our list of XML files to process.
-
-if cfg.has_option("xml_filename"):
- myrpki.main(("-c", cfg_file))
- my_xmlfile = cfg.get("xml_filename")
- xmlfiles.append(my_xmlfile)
-
-# Add any other XML files specified on the command line
-
-xmlfiles.extend(argv)
-
-my_handle = None
-
-for xmlfile in xmlfiles:
-
- # Parse XML file and validate it against our scheme
-
- tree = myrpki.etree_read(xmlfile, validate = True)
-
- handle = tree.get("handle")
-
- if xmlfile == my_xmlfile:
- my_handle = handle
-
- # Update IRDB with parsed resource and roa-request data.
-
- cur.execute(
- """
- DELETE
- FROM roa_request_prefix
- USING roa_request, roa_request_prefix
- WHERE roa_request.roa_request_id = roa_request_prefix.roa_request_id AND roa_request.roa_request_handle = %s
- """, (handle,))
-
- cur.execute("DELETE FROM roa_request WHERE roa_request.roa_request_handle = %s", (handle,))
-
- for x in tree.getiterator("roa_request"):
- cur.execute("INSERT roa_request (roa_request_handle, asn) VALUES (%s, %s)", (handle, x.get("asn")))
- roa_request_id = cur.lastrowid
- for version, prefix_set in ((4, rpki.resource_set.roa_prefix_set_ipv4(x.get("v4"))), (6, rpki.resource_set.roa_prefix_set_ipv6(x.get("v6")))):
- if prefix_set:
- cur.executemany("INSERT roa_request_prefix (roa_request_id, prefix, prefixlen, max_prefixlen, version) VALUES (%s, %s, %s, %s, %s)",
- ((roa_request_id, p.prefix, p.prefixlen, p.max_prefixlen, version) for p in prefix_set))
-
- cur.execute(
- """
- DELETE
- FROM registrant_asn
- USING registrant, registrant_asn
- WHERE registrant.registrant_id = registrant_asn.registrant_id AND registrant.registry_handle = %s
- """ , (handle,))
-
- cur.execute(
- """
- DELETE FROM registrant_net USING registrant, registrant_net
- WHERE registrant.registrant_id = registrant_net.registrant_id AND registrant.registry_handle = %s
- """ , (handle,))
-
- cur.execute("DELETE FROM registrant WHERE registrant.registry_handle = %s" , (handle,))
-
- for x in tree.getiterator("child"):
- child_handle = x.get("handle")
- asns = rpki.resource_set.resource_set_as(x.get("asns"))
- ipv4 = rpki.resource_set.resource_set_ipv4(x.get("v4"))
- ipv6 = rpki.resource_set.resource_set_ipv6(x.get("v6"))
-
- cur.execute("INSERT registrant (registrant_handle, registry_handle, registrant_name, valid_until) VALUES (%s, %s, %s, %s)",
- (child_handle, handle, child_handle, rpki.sundial.datetime.fromXMLtime(x.get("valid_until")).to_sql()))
- child_id = cur.lastrowid
- if asns:
- cur.executemany("INSERT registrant_asn (start_as, end_as, registrant_id) VALUES (%s, %s, %s)",
- ((a.min, a.max, child_id) for a in asns))
- if ipv4:
- cur.executemany("INSERT registrant_net (start_ip, end_ip, version, registrant_id) VALUES (%s, %s, 4, %s)",
- ((a.min, a.max, child_id) for a in ipv4))
- if ipv6:
- cur.executemany("INSERT registrant_net (start_ip, end_ip, version, registrant_id) VALUES (%s, %s, 6, %s)",
- ((a.min, a.max, child_id) for a in ipv6))
-
- db.commit()
-
- # Check for certificates before attempting anything else
-
- hosted_cacert = findbase64(tree, "bpki_ca_certificate")
- if not hosted_cacert:
- print "Nothing else I can do without a trust anchor for the entity I'm hosting."
- continue
-
- rpkid_xcert = rpki.x509.X509(PEM_file = bpki.fxcert(b64 = hosted_cacert.get_Base64(),
- filename = handle + ".cacert.cer",
- path_restriction = 1))
-
- # See what rpkid and pubd already have on file for this entity.
-
- if run_pubd:
- client_pdus = dict((x.client_handle, x)
- for x in call_pubd(rpki.publication.client_elt.make_pdu(action = "list"))
- if isinstance(x, rpki.publication.client_elt))
-
- rpkid_reply = call_rpkid(
- rpki.left_right.self_elt.make_pdu( action = "get", tag = "self", self_handle = handle),
- rpki.left_right.bsc_elt.make_pdu( action = "list", tag = "bsc", self_handle = handle),
- rpki.left_right.repository_elt.make_pdu(action = "list", tag = "repository", self_handle = handle),
- rpki.left_right.parent_elt.make_pdu( action = "list", tag = "parent", self_handle = handle),
- rpki.left_right.child_elt.make_pdu( action = "list", tag = "child", self_handle = handle))
-
- self_pdu = rpkid_reply[0]
- bsc_pdus = dict((x.bsc_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.bsc_elt))
- repository_pdus = dict((x.repository_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.repository_elt))
- parent_pdus = dict((x.parent_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.parent_elt))
- child_pdus = dict((x.child_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.child_elt))
-
- pubd_query = []
- rpkid_query = []
-
- # There should be exactly one <self/> object per hosted entity, by definition
-
- if (isinstance(self_pdu, rpki.left_right.report_error_elt) or
- self_pdu.crl_interval != self_crl_interval or
- self_pdu.regen_margin != self_regen_margin or
- self_pdu.bpki_cert != rpkid_xcert):
- rpkid_query.append(rpki.left_right.self_elt.make_pdu(
- action = "create" if isinstance(self_pdu, rpki.left_right.report_error_elt) else "set",
- tag = "self",
- self_handle = handle,
- bpki_cert = rpkid_xcert,
- crl_interval = self_crl_interval,
- regen_margin = self_regen_margin))
-
- # In general we only need one <bsc/> per <self/>. BSC objects are a
- # little unusual in that the PKCS #10 subelement is generated by rpkid
- # in response to generate_keypair, so there's more of a separation
- # between create and set than with other objects.
-
- bsc_cert = findbase64(tree, "bpki_bsc_certificate")
- bsc_crl = findbase64(tree, "bpki_crl", rpki.x509.CRL)
-
- bsc_pdu = bsc_pdus.pop(bsc_handle, None)
-
- if bsc_pdu is None:
- rpkid_query.append(rpki.left_right.bsc_elt.make_pdu(
- action = "create",
- tag = "bsc",
- self_handle = handle,
- bsc_handle = bsc_handle,
- generate_keypair = "yes"))
- elif bsc_pdu.signing_cert != bsc_cert or bsc_pdu.signing_cert_crl != bsc_crl:
- rpkid_query.append(rpki.left_right.bsc_elt.make_pdu(
- action = "set",
- tag = "bsc",
- self_handle = handle,
- bsc_handle = bsc_handle,
- signing_cert = bsc_cert,
- signing_cert_crl = bsc_crl))
-
- rpkid_query.extend(rpki.left_right.bsc_elt.make_pdu(
- action = "destroy", self_handle = handle, bsc_handle = b) for b in bsc_pdus)
-
- bsc_req = None
-
- if bsc_pdu and bsc_pdu.pkcs10_request:
- bsc_req = bsc_pdu.pkcs10_request
-
- # At present we need one <repository/> per <parent/>, not because
- # rpkid requires that, but because pubd does. pubd probably should
- # be fixed to support a single client allowed to update multiple
- # trees, but for the moment the easiest way forward is just to
- # enforce a 1:1 mapping between <parent/> and <repository/> objects
-
- for repository in tree.getiterator("repository"):
-
- repository_handle = repository.get("handle")
- repository_pdu = repository_pdus.pop(repository_handle, None)
- repository_uri = repository.get("service_uri")
- repository_cert = findbase64(repository, "bpki_certificate")
-
- if (repository_pdu is None or
- repository_pdu.bsc_handle != bsc_handle or
- repository_pdu.peer_contact_uri != repository_uri or
- repository_pdu.bpki_cert != repository_cert):
- rpkid_query.append(rpki.left_right.repository_elt.make_pdu(
- action = "create" if repository_pdu is None else "set",
- tag = repository_handle,
- self_handle = handle,
- repository_handle = repository_handle,
- bsc_handle = bsc_handle,
- peer_contact_uri = repository_uri,
- bpki_cert = repository_cert))
-
- rpkid_query.extend(rpki.left_right.repository_elt.make_pdu(
- action = "destroy", self_handle = handle, repository_handle = r) for r in repository_pdus)
-
- # <parent/> setup code currently assumes 1:1 mapping between
- # <repository/> and <parent/>, and further assumes that the handles
- # for an associated pair are the identical (that is:
- # parent.repository_handle == parent.parent_handle).
-
- for parent in tree.getiterator("parent"):
-
- parent_handle = parent.get("handle")
- parent_pdu = parent_pdus.pop(parent_handle, None)
- parent_uri = parent.get("service_uri")
- parent_myhandle = parent.get("myhandle")
- parent_sia_base = parent.get("sia_base")
- parent_cms_cert = findbase64(parent, "bpki_cms_certificate")
- parent_https_cert = findbase64(parent, "bpki_https_certificate")
-
- if (parent_pdu is None or
- parent_pdu.bsc_handle != bsc_handle or
- parent_pdu.repository_handle != parent_handle or
- parent_pdu.peer_contact_uri != parent_uri or
- parent_pdu.sia_base != parent_sia_base or
- parent_pdu.sender_name != parent_myhandle or
- parent_pdu.recipient_name != parent_handle or
- parent_pdu.bpki_cms_cert != parent_cms_cert or
- parent_pdu.bpki_https_cert != parent_https_cert):
- rpkid_query.append(rpki.left_right.parent_elt.make_pdu(
- action = "create" if parent_pdu is None else "set",
- tag = parent_handle,
- self_handle = handle,
- parent_handle = parent_handle,
- bsc_handle = bsc_handle,
- repository_handle = parent_handle,
- peer_contact_uri = parent_uri,
- sia_base = parent_sia_base,
- sender_name = parent_myhandle,
- recipient_name = parent_handle,
- bpki_cms_cert = parent_cms_cert,
- bpki_https_cert = parent_https_cert))
-
- rpkid_query.extend(rpki.left_right.parent_elt.make_pdu(
- action = "destroy", self_handle = handle, parent_handle = p) for p in parent_pdus)
-
- # Children are simpler than parents, because they call us, so no URL
- # to construct and figuring out what certificate to use is their
- # problem, not ours.
-
- for child in tree.getiterator("child"):
-
- child_handle = child.get("handle")
- child_pdu = child_pdus.pop(child_handle, None)
- child_cert = findbase64(child, "bpki_certificate")
-
- if (child_pdu is None or
- child_pdu.bsc_handle != bsc_handle or
- child_pdu.bpki_cert != child_cert):
- rpkid_query.append(rpki.left_right.child_elt.make_pdu(
- action = "create" if child_pdu is None else "set",
- tag = child_handle,
- self_handle = handle,
- child_handle = child_handle,
- bsc_handle = bsc_handle,
- bpki_cert = child_cert))
-
- rpkid_query.extend(rpki.left_right.child_elt.make_pdu(
- action = "destroy", self_handle = handle, child_handle = c) for c in child_pdus)
-
- # Publication setup.
-
- if run_pubd:
-
- for f in entitydb.iterate("pubclients", "*.xml"):
- c = myrpki.etree_read(f)
-
- client_handle = c.get("client_handle")
- client_base_uri = c.get("sia_base")
- client_bpki_cert = rpki.x509.X509(PEM_file = bpki.fxcert(c.findtext("bpki_client_ta")))
- client_pdu = client_pdus.pop(client_handle, None)
-
- if (client_pdu is None or
- client_pdu.base_uri != client_base_uri or
- client_pdu.bpki_cert != client_bpki_cert):
- pubd_query.append(rpki.publication.client_elt.make_pdu(
- action = "create" if client_pdu is None else "set",
- client_handle = client_handle,
- bpki_cert = client_bpki_cert,
- base_uri = client_base_uri))
-
- pubd_query.extend(rpki.publication.client_elt.make_pdu(
- action = "destroy", client_handle = p) for p in client_pdus)
-
- # If we changed anything, ship updates off to daemons
-
- if rpkid_query:
- rpkid_reply = call_rpkid(*rpkid_query)
- bsc_pdus = dict((x.bsc_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.bsc_elt))
- if bsc_handle in bsc_pdus and bsc_pdus[bsc_handle].pkcs10_request:
- bsc_req = bsc_pdus[bsc_handle].pkcs10_request
- for r in rpkid_reply:
- assert not isinstance(r, rpki.left_right.report_error_elt)
-
- if pubd_query:
- assert run_pubd
- pubd_reply = call_pubd(*pubd_query)
- for r in pubd_reply:
- assert not isinstance(r, rpki.publication.report_error_elt)
-
- # Rewrite XML.
-
- e = tree.find("bpki_bsc_pkcs10")
- if e is None and bsc_req is not None:
- e = SubElement(tree, "bpki_bsc_pkcs10")
- elif bsc_req is None:
- tree.remove(e)
-
- if bsc_req is not None:
- assert e is not None
- s = bsc_req.get_Base64()
- s = "\n".join(s[64*i : 64*(i+1)] for i in xrange(1 + len(s)/64)).strip()
- e.text = "\n" + s + "\n"
-
- # Something weird going on here with lxml linked against recent
- # versions of libxml2. Looks like modifying the tree above somehow
- # produces validation errors, but it works fine if we convert it to
- # a string and parse it again. I'm not seeing any problems with any
- # of the other code that uses lxml to do validation, just this one
- # place. Weird. Kludge around it for now.
- #
- #tree = lxml.etree.fromstring(lxml.etree.tostring(tree))
-
- myrpki.etree_write(tree, xmlfile, validate = True)
-
-db.close()
diff --git a/myrpki.rototill/myrpki.py b/myrpki.rototill/myrpki.py
index 5ffbd963..6e5a6eb5 100644
--- a/myrpki.rototill/myrpki.py
+++ b/myrpki.rototill/myrpki.py
@@ -1,4 +1,17 @@
"""
+This program is now the merger of three different tools: the old
+myrpki.py script, the old myirbe.py script, and the newer setup.py CLI
+tool. As such, it is still in need of some cleanup, but the need to
+provide a saner user interface is more urgent than internal code
+prettiness at the moment. In the long run, 90% of the code in this
+file probably ought to move to well-designed library modules.
+
+The rest of the documentation in this module comment is lifted from
+the previous scripts, and needs revision. Then again, all the
+commands in this tool need documenting too....
+
+===
+
Read an OpenSSL-style config file and a bunch of .csv files to find
out about parents and children and resources and ROA requests, oh my.
Run OpenSSL command line tool to construct BPKI certificates,
@@ -30,9 +43,37 @@ this script can itself be loaded as a Python module and invoked as
part of another program. This requires a few minor contortions, but
avoids duplicating common code.
+===
+
+IRBE-side stuff for myrpki tools.
+
+The basic model here is that each entity with resources to certify
+runs the myrpki tool, but not all of them necessarily run their own
+RPKi engines. The entities that do run RPKI engines get data from the
+entities they host via the XML files output by the myrpki tool. Those
+XML files are the input to this script, which uses them to do all the
+work of constructing certificates, populating SQL databases, and so
+forth. A few operations (eg, BSC construction) generate data which
+has to be shipped back to the resource holder, which we do by updating
+the same XML file.
+
+In essence, the XML files are a sneakernet (or email, or carrier
+pigeon) communication channel between the resource holders and the
+RPKI engine operators.
+
+As a convenience, for the normal case where the RPKI engine operator
+is itself a resource holder, this script also runs the myrpki script
+directly to process the RPKI engine operator's own resources.
+
+Note that, due to the back and forth nature of some of these
+operations, it may take several cycles for data structures to stablize
+and everything to reach a steady state. This is normal.
+
+====
+
$Id$
-Copyright (C) 2009 Internet Systems Consortium ("ISC")
+Copyright (C) 2009-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
@@ -47,15 +88,19 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-# Only standard Python libraries for this program, please.
+from __future__ import with_statement
-import subprocess, csv, re, os, getopt, sys, base64, glob, copy
-import rpki.config
+import subprocess, csv, re, os, getopt, sys, base64, time, glob, copy, warnings
+import rpki.config, rpki.cli, rpki.sundial
try:
from lxml.etree import Element, SubElement, ElementTree
+ have_lxml = True
except ImportError:
from xml.etree.ElementTree import Element, SubElement, ElementTree
+ have_lxml = False
+
+
# Our XML namespace and protocol version.
@@ -741,75 +786,804 @@ def etree_read(filename, verbose = False, validate = False):
raise RuntimeError, "XML tag %r is not in namespace %r" % (i.tag, namespace)
return e
-def main(argv = ()):
- """
- Main program. Must be callable from other programs as well as being
- invoked directly when this module is run as a script.
- """
+# When this file is run as a script, run main() with command line
+# arguments. main() can't use sys.argv directly as that might be the
+# command line for some other program that loads this module.
- cfg_file = "myrpki.conf"
+
- opts, argv = getopt.getopt(argv, "c:h:?", ["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
- if argv:
- raise RuntimeError, "Unexpected arguments %r" % (argv,)
+class main(rpki.cli.Cmd):
- cfg = rpki.config.parser(cfg_file, "myrpki")
+ prompt = "setup> "
- my_handle = cfg.get("handle")
- roa_csv_file = cfg.get("roa_csv")
- children_csv_file = cfg.get("children_csv")
- prefix_csv_file = cfg.get("prefix_csv")
- asn_csv_file = cfg.get("asn_csv")
- bpki_dir = cfg.get("bpki_resources_directory")
- xml_filename = cfg.get("xml_filename")
+ completedefault = rpki.cli.Cmd.filename_complete
- global openssl
- openssl = cfg.get("openssl", "openssl")
- entitydb = EntityDB(cfg)
+ def __init__(self):
+ os.environ["TZ"] = "UTC"
+ time.tzset()
- bpki = CA(cfg_file, bpki_dir)
+ self.cfg_file = os.getenv("MYRPKI_CONF", "myrpki.conf")
- try:
- bsc_req, bsc_cer = bpki.bsc(etree_read(xml_filename).findtext("bpki_bsc_pkcs10"))
- except IOError:
- bsc_req, bsc_cer = None, None
+ opts, argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"])
+ for o, a in opts:
+ if o in ("-c", "--config"):
+ self.cfg_file = a
+ elif o in ("-h", "--help", "-?"):
+ argv = ["help"]
- e = Element("myrpki", handle = my_handle)
+ if not argv or argv[0] != "help":
+ self.read_config()
- roa_requests.from_csv(roa_csv_file).xml(e)
+ rpki.cli.Cmd.__init__(self, argv)
- children.from_csv(
- children_csv_file = children_csv_file,
- prefix_csv_file = prefix_csv_file,
- asn_csv_file = asn_csv_file,
- fxcert = bpki.fxcert,
- entitydb = entitydb).xml(e)
- parents.from_csv(fxcert = bpki.fxcert,entitydb = entitydb).xml(e)
+ def read_config(self):
- repositories.from_csv(fxcert = bpki.fxcert,entitydb = entitydb).xml(e)
+ self.cfg = rpki.config.parser(self.cfg_file, "myrpki")
- PEMElement(e, "bpki_ca_certificate", bpki.cer)
- PEMElement(e, "bpki_crl", bpki.crl)
+ global openssl
+ openssl = self.cfg.get("openssl", "openssl")
- if bsc_cer:
- PEMElement(e, "bpki_bsc_certificate", bsc_cer)
+ self.histfile = self.cfg.get("history_file", ".setup_history")
+ self.handle = self.cfg.get("handle")
+ self.run_rpkid = self.cfg.getboolean("run_rpkid")
+ self.run_pubd = self.cfg.getboolean("run_pubd")
+ self.run_rootd = self.cfg.getboolean("run_rootd")
+ self.entitydb = EntityDB(self.cfg)
- if bsc_req:
- PEMElement(e, "bpki_bsc_pkcs10", bsc_req)
+ if self.run_rootd and (not self.run_pubd or not self.run_rpkid):
+ raise RuntimeError, "Can't run rootd unless also running rpkid and pubd"
- etree_write(e, xml_filename)
+ self.bpki_resources = CA(self.cfg_file, self.cfg.get("bpki_resources_directory"))
+ if self.run_rpkid or self.run_pubd or self.run_rootd:
+ self.bpki_servers = CA(self.cfg_file, self.cfg.get("bpki_servers_directory"))
-# When this file is run as a script, run main() with command line
-# arguments. main() can't use sys.argv directly as that might be the
-# command line for some other program that loads this module.
+ self.pubd_contact_info = self.cfg.get("pubd_contact_info", "")
+
+ self.rsync_module = self.cfg.get("publication_rsync_module")
+ self.rsync_server = self.cfg.get("publication_rsync_server")
+
+
+ def do_initialize(self, arg):
+ if arg:
+ raise RuntimeError, "This command takes no arguments"
+
+ print "Generating RSA keys, this may take a little while..."
+
+ self.bpki_resources.setup(self.cfg.get("bpki_resources_ta_dn",
+ "/CN=%s BPKI Resource Trust Anchor" % self.handle))
+ if self.run_rpkid or self.run_pubd or self.run_rootd:
+ self.bpki_servers.setup(self.cfg.get("bpki_servers_ta_dn",
+ "/CN=%s BPKI Server Trust Anchor" % self.handle))
+
+ # Create entitydb directories.
+
+ for i in ("parents", "children", "repositories", "pubclients"):
+ d = self.entitydb(i)
+ if not os.path.exists(d):
+ os.makedirs(d)
+
+ if self.run_rpkid or self.run_pubd or self.run_rootd:
+
+ if self.run_rpkid:
+ self.bpki_servers.ee(self.cfg.get("bpki_rpkid_ee_dn",
+ "/CN=%s rpkid server certificate" % self.handle), "rpkid")
+ self.bpki_servers.ee(self.cfg.get("bpki_irdbd_ee_dn",
+ "/CN=%s irdbd server certificate" % self.handle), "irdbd")
+ if self.run_pubd:
+ self.bpki_servers.ee(self.cfg.get("bpki_pubd_ee_dn",
+ "/CN=%s pubd server certificate" % self.handle), "pubd")
+ if self.run_rpkid or self.run_pubd:
+ self.bpki_servers.ee(self.cfg.get("bpki_irbe_ee_dn",
+ "/CN=%s irbe client certificate" % self.handle), "irbe")
+ if self.run_rootd:
+ self.bpki_servers.ee(self.cfg.get("bpki_rootd_ee_dn",
+ "/CN=%s rootd server certificate" % self.handle), "rootd")
+
+ # Build the identity.xml file. Need to check for existing file so we don't
+ # overwrite? Worry about that later.
+
+ e = Element("identity", handle = self.handle)
+ PEMElement(e, "bpki_ta", self.bpki_resources.cer)
+ etree_write(e, self.entitydb("identity.xml"))
+
+ # If we're running rootd, construct a fake parent to go with it,
+ # and cross-certify in both directions so we can talk to rootd.
+
+ if self.run_rootd:
+
+ e = Element("parent", parent_handle = self.handle, child_handle = self.handle,
+ service_uri = "https://localhost:%s/" % self.cfg.get("rootd_server_port"),
+ valid_until = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365)))
+ PEMElement(e, "bpki_resource_ta", self.bpki_servers.cer)
+ PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
+ PEMElement(e, "bpki_child_ta", self.bpki_resources.cer)
+ SubElement(e, "repository", type = "offer")
+ etree_write(e, self.entitydb("parents", "%s.xml" % self.handle))
+
+ self.bpki_resources.xcert(self.bpki_servers.cer)
+
+ rootd_child_fn = self.cfg.get("child-bpki-cert", None, "rootd")
+ if not os.path.exists(rootd_child_fn):
+ os.link(self.bpki_servers.xcert(self.bpki_resources.cer), rootd_child_fn)
+
+ # If we're running pubd, construct repository request for it, as
+ # if we had received an offer.
+
+ if self.run_pubd:
+ e = Element("repository", type = "request", handle = self.handle, parent_handle = self.handle)
+ SubElement(e, "contact_info").text = self.pubd_contact_info
+ PEMElement(e, "bpki_ta", self.bpki_resources.cer)
+ etree_write(e, self.entitydb("repositories", "%s.xml" % self.handle))
+
+
+ def do_answer_child(self, arg):
+
+ child_handle = None
+
+ opts, argv = getopt.getopt(arg.split(), "", ["child_handle="])
+ for o, a in opts:
+ if o == "--child_handle":
+ child_handle = a
+
+ if len(argv) != 1:
+ raise RuntimeError, "Need to specify filename for child.xml"
+
+ if not self.run_rpkid:
+ raise RuntimeError, "Don't (yet) know how to set up child unless we run rpkid"
+
+ c = etree_read(argv[0])
+
+ if child_handle is None:
+ child_handle = c.get("handle")
+
+ print "Child calls itself %r, we call it %r" % (c.get("handle"), child_handle)
+
+ self.bpki_servers.fxcert(c.findtext("bpki_ta"))
+
+ e = Element("parent", parent_handle = self.handle, child_handle = child_handle,
+ service_uri = "https://%s:%s/up-down/%s/%s" % (self.cfg.get("rpkid_server_host"),
+ self.cfg.get("rpkid_server_port"),
+ self.handle, child_handle),
+ valid_until = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365)))
+
+ PEMElement(e, "bpki_resource_ta", self.bpki_resources.cer)
+ PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
+ SubElement(e, "bpki_child_ta").text = c.findtext("bpki_ta")
+
+ try:
+ repo = None
+ for f in self.entitydb.iterate("repositories", "*.xml"):
+ r = etree_read(f)
+ if r.get("type") == "confirmed":
+ if repo is not None:
+ raise RuntimeError, "Too many repositories, I don't know what to do, not giving referral"
+ repo_handle = os.path.splitext(os.path.split(f)[-1])[0]
+ repo = r
+ if repo is None:
+ raise RuntimeError, "Couldn't find any usable repositories, not giving referral"
+
+ if repo_handle == self.handle:
+ SubElement(e, "repository", type = "offer")
+ else:
+ r = SubElement(e, "repository", type = "hint",
+ proposed_sia_base = repo.get("sia_base") + child_handle + "/")
+ SubElement(r, "contact_info").text = repo.findtext("contact_info")
+ # CMS-signed blob authorizing use of part of our space by our
+ # child goes here, once I've written that code.
+
+ except RuntimeError, err:
+ print err
+
+ etree_write(e, self.entitydb("children", "%s.xml" % child_handle))
+
+
+ def do_process_parent_answer(self, arg):
+
+ parent_handle = None
+
+ opts, argv = getopt.getopt(arg.split(), "", ["parent_handle="])
+ for o, a in opts:
+ if o == "--parent_handle":
+ parent_handle = a
+
+ if len(argv) != 1:
+ raise RuntimeError, "Need to specify filename for parent.xml on command line"
+
+ p = etree_read(argv[0])
+
+ if parent_handle is None:
+ parent_handle = p.get("parent_handle")
+
+ print "Parent calls itself %r, we call it %r" % (p.get("parent_handle"), parent_handle)
+ print "Parent calls us %r" % p.get("child_handle")
+
+ self.bpki_resources.fxcert(p.findtext("bpki_resource_ta"))
+ self.bpki_resources.fxcert(p.findtext("bpki_server_ta"))
+
+ etree_write(p, self.entitydb("parents", "%s.xml" % parent_handle))
+
+ r = p.find("repository")
+
+ if r is not None and r.get("type") in ("offer", "hint"):
+ r.set("handle", self.handle)
+ r.set("parent_handle", parent_handle)
+ PEMElement(r, "bpki_ta", self.bpki_resources.cer)
+ etree_write(r, self.entitydb("repositories", "%s.xml" % parent_handle))
+
+ else:
+ print "Couldn't find repository offer or hint"
+
+
+ def do_answer_repository_client(self, arg):
+
+ sia_base = None
+
+ opts, argv = getopt.getopt(arg.split(), "", ["sia_base="])
+ for o, a in opts:
+ if o == "--sia_base":
+ sia_base = a
+
+ if len(argv) != 1:
+ raise RuntimeError, "Need to specify filename for client.xml"
+
+ c = etree_read(argv[0])
+
+ # Critical thing at this point is to figure out what client's
+ # sia_base value should be. Three cases:
+ #
+ # - client has no particular relationship to any other client:
+ # sia_base is top-level, or as close as we can make it taking
+ # rsyncd module into account (maybe homed under us, hmm, how do
+ # we detect case where we are talking to ourself?)
+ #
+ # - client is a direct child of ours to whom we (in our parent
+ # role) made an offer of publication service. client homes
+ # under us, presumably.
+ #
+ # - client is a child of a client of ours who referred the new
+ # client to us, along with a signed referral. signed referral
+ # includes sia_base of referring client, new client homes under
+ # that per referring client's wishes.
+ #
+ # ... which implies that there's a fourth case, where we are both
+ # the client and the server.
+
+ # Checking of signed referrals goes somewhere around here. Must
+ # be after reading client's XML, but before deciding what the
+ # client's sia_base and handle will be.
+
+ # For the moment we cheat egregiously, no crypto, blind trust of
+ # what we're sent, while I focus on the basic semantics.
+
+ if sia_base is None and c.get("proposed_sia_base"):
+ sia_base = c.get("proposed_sia_base")
+ elif sia_base is None and c.get("handle") == self.handle:
+ sia_base = "rsync://%s/%s/" % (self.rsync_server, self.rsync_module)
+ else:
+ sia_base = "rsync://%s/%s/%s/" % (self.rsync_server, self.rsync_module, c.get("handle"))
+
+ client_handle = "/".join(sia_base.rstrip("/").split("/")[3:])
+
+ parent_handle = c.get("parent_handle")
+
+ print "Client calls itself %r, we call it %r" % (c.get("handle"), client_handle)
+ print "Client says its parent handle is %r" % parent_handle
+
+ self.bpki_servers.fxcert(c.findtext("bpki_ta"))
+
+ e = Element("repository", type = "confirmed",
+ repository_handle = self.handle,
+ client_handle = client_handle,
+ parent_handle = parent_handle,
+ sia_base = sia_base,
+ service_uri = "https://%s:%s/client/%s" % (self.cfg.get("pubd_server_host"),
+ self.cfg.get("pubd_server_port"),
+ client_handle))
+
+ PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
+ SubElement(e, "bpki_client_ta").text = c.findtext("bpki_ta")
+ SubElement(e, "contact_info").text = self.pubd_contact_info
+ etree_write(e, self.entitydb("pubclients", "%s.xml" % client_handle.replace("/", ".")))
+
+
+ def do_process_repository_answer(self, arg):
+
+ argv = arg.split()
+
+ if len(argv) != 1:
+ raise RuntimeError, "Need to specify filename for repository.xml on command line"
+
+ r = etree_read(argv[0])
+
+ parent_handle = r.get("parent_handle")
+
+ print "Repository calls itself %r, calls us %r" % (r.get("repository_handle"), r.get("client_handle"))
+ print "Repository response associated with parent_handle %r" % parent_handle
+
+ etree_write(r, self.entitydb("repositories", "%s.xml" % parent_handle))
+
+
+ def do_compose_request_to_host(self, arg):
+ pass
+
+ def do_answer_hosted_entity(self, arg):
+ pass
+
+ def do_process_host_answer(self, arg):
+ pass
+
+
+
+
+ def myrpki_main(self):
+ """
+ Main program of old myrpki.py script.
+ """
+
+ roa_csv_file = self.cfg.get("roa_csv")
+ children_csv_file = self.cfg.get("children_csv")
+ prefix_csv_file = self.cfg.get("prefix_csv")
+ asn_csv_file = self.cfg.get("asn_csv")
+
+ # This probably should become an argument instead of (or in
+ # addition to a default from?) config file.
+ xml_filename = self.cfg.get("xml_filename")
+
+ try:
+ bsc_req, bsc_cer = self.bpki_resources.bsc(etree_read(xml_filename).findtext("bpki_bsc_pkcs10"))
+ except IOError:
+ bsc_req, bsc_cer = None, None
+
+ e = Element("myrpki", handle = self.handle)
+
+ roa_requests.from_csv(roa_csv_file).xml(e)
+
+ children.from_csv(
+ children_csv_file = children_csv_file,
+ prefix_csv_file = prefix_csv_file,
+ asn_csv_file = asn_csv_file,
+ fxcert = self.bpki_resources.fxcert,
+ entitydb = self.entitydb).xml(e)
+
+ parents.from_csv( fxcert = self.bpki_resources.fxcert, entitydb = self.entitydb).xml(e)
+ repositories.from_csv(fxcert = self.bpki_resources.fxcert, entitydb = self.entitydb).xml(e)
+
+ PEMElement(e, "bpki_ca_certificate", self.bpki_resources.cer)
+ PEMElement(e, "bpki_crl", self.bpki_resources.crl)
+
+ if bsc_cer:
+ PEMElement(e, "bpki_bsc_certificate", bsc_cer)
+
+ if bsc_req:
+ PEMElement(e, "bpki_bsc_pkcs10", bsc_req)
+
+ etree_write(e, xml_filename)
+
+
+ def do_myrpki(self, arg):
+ if arg:
+ raise RuntimeError, "Unexpected argument %r" % arg
+ self.myrpki_main()
+
+
+
+ def myirbe_main(self, argv = []):
+ """
+ Main program of old myirbe.py script.
+ """
+
+ import rpki.https, rpki.resource_set, rpki.relaxng, rpki.exceptions
+ import rpki.left_right, rpki.log, rpki.x509, rpki.async
+
+ # Silence warning while loading MySQLdb in Python 2.6, sigh
+ if hasattr(warnings, "catch_warnings"):
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ import MySQLdb
+ else:
+ import MySQLdb
+
+ def findbase64(tree, name, b64type = rpki.x509.X509):
+ """
+ Find and extract a base64-encoded XML element, if present.
+ """
+ x = tree.findtext(name)
+ return b64type(Base64 = x) if x else None
+
+ # For simple cases we don't really care what this value is, so long as
+ # we're consistant about it, so wiring this in is fine.
+
+ bsc_handle = "bsc"
+
+ rpki.log.init("myirbe")
+
+ self.cfg.set_global_flags()
+
+ # Default values for CRL parameters are low, for testing. Not
+ # quite as low as they once were, too much expired CRL whining.
+
+ self_crl_interval = self.cfg.getint("self_crl_interval", 2 * 60 * 60)
+ self_regen_margin = self.cfg.getint("self_regen_margin", 30 * 60)
+ pubd_base = self.cfg.get("pubd_base").rstrip("/") + "/"
+ rpkid_base = self.cfg.get("rpkid_base").rstrip("/") + "/"
+
+ # Nasty regexp for parsing rpkid's up-down service URLs.
+
+ updown_regexp = re.compile(re.escape(rpkid_base) + "up-down/([-A-Z0-9_]+)/([-A-Z0-9_]+)$", re.I)
+
+ # Wrappers to simplify calling rpkid and pubd.
+
+ call_rpkid = rpki.async.sync_wrapper(rpki.https.caller(
+ proto = rpki.left_right,
+ client_key = rpki.x509.RSA( PEM_file = self.bpki_servers.dir + "/irbe.key"),
+ client_cert = rpki.x509.X509(PEM_file = self.bpki_servers.dir + "/irbe.cer"),
+ server_ta = rpki.x509.X509(PEM_file = self.bpki_servers.cer),
+ server_cert = rpki.x509.X509(PEM_file = self.bpki_servers.dir + "/rpkid.cer"),
+ url = rpkid_base + "left-right",
+ debug = True))
+
+ if self.run_pubd:
+
+ call_pubd = rpki.async.sync_wrapper(rpki.https.caller(
+ proto = rpki.publication,
+ client_key = rpki.x509.RSA( PEM_file = self.bpki_servers.dir + "/irbe.key"),
+ client_cert = rpki.x509.X509(PEM_file = self.bpki_servers.dir + "/irbe.cer"),
+ server_ta = rpki.x509.X509(PEM_file = self.bpki_servers.cer),
+ server_cert = rpki.x509.X509(PEM_file = self.bpki_servers.dir + "/pubd.cer"),
+ url = pubd_base + "control",
+ debug = True))
+
+ # Make sure that pubd's BPKI CRL is up to date.
+
+ call_pubd(rpki.publication.config_elt.make_pdu(
+ action = "set",
+ bpki_crl = rpki.x509.CRL(PEM_file = self.bpki_servers.crl)))
+
+ irdbd_cfg = rpki.config.parser(self.cfg.get("irdbd_conf", self.cfg_file), "irdbd")
+
+ db = MySQLdb.connect(user = irdbd_cfg.get("sql-username"),
+ db = irdbd_cfg.get("sql-database"),
+ passwd = irdbd_cfg.get("sql-password"))
+
+ cur = db.cursor()
+
+ xmlfiles = []
+
+ # If [myrpki] section includes an "xml_filename" setting, run
+ # myrpki.py internally, as a convenience, and include its output at
+ # the head of our list of XML files to process.
+
+ my_xmlfile = self.cfg.get("xml_filename", "")
+ if my_xmlfile:
+ self.myrpki_main()
+ xmlfiles.append(my_xmlfile)
+ else:
+ my_xmlfile = None
+
+ # Add any other XML files specified on the command line
+
+ xmlfiles.extend(argv)
+
+ my_handle = None
+
+ for xmlfile in xmlfiles:
+
+ # Parse XML file and validate it against our scheme
+
+ tree = etree_read(xmlfile, validate = True)
+
+ handle = tree.get("handle")
+
+ if xmlfile == my_xmlfile:
+ my_handle = handle
+
+ # Update IRDB with parsed resource and roa-request data.
+
+ cur.execute(
+ """
+ DELETE
+ FROM roa_request_prefix
+ USING roa_request, roa_request_prefix
+ WHERE roa_request.roa_request_id = roa_request_prefix.roa_request_id AND roa_request.roa_request_handle = %s
+ """, (handle,))
+
+ cur.execute("DELETE FROM roa_request WHERE roa_request.roa_request_handle = %s", (handle,))
+
+ for x in tree.getiterator("roa_request"):
+ cur.execute("INSERT roa_request (roa_request_handle, asn) VALUES (%s, %s)", (handle, x.get("asn")))
+ roa_request_id = cur.lastrowid
+ for version, prefix_set in ((4, rpki.resource_set.roa_prefix_set_ipv4(x.get("v4"))), (6, rpki.resource_set.roa_prefix_set_ipv6(x.get("v6")))):
+ if prefix_set:
+ cur.executemany("INSERT roa_request_prefix (roa_request_id, prefix, prefixlen, max_prefixlen, version) VALUES (%s, %s, %s, %s, %s)",
+ ((roa_request_id, p.prefix, p.prefixlen, p.max_prefixlen, version) for p in prefix_set))
+
+ cur.execute(
+ """
+ DELETE
+ FROM registrant_asn
+ USING registrant, registrant_asn
+ WHERE registrant.registrant_id = registrant_asn.registrant_id AND registrant.registry_handle = %s
+ """ , (handle,))
+
+ cur.execute(
+ """
+ DELETE FROM registrant_net USING registrant, registrant_net
+ WHERE registrant.registrant_id = registrant_net.registrant_id AND registrant.registry_handle = %s
+ """ , (handle,))
+
+ cur.execute("DELETE FROM registrant WHERE registrant.registry_handle = %s" , (handle,))
+
+ for x in tree.getiterator("child"):
+ child_handle = x.get("handle")
+ asns = rpki.resource_set.resource_set_as(x.get("asns"))
+ ipv4 = rpki.resource_set.resource_set_ipv4(x.get("v4"))
+ ipv6 = rpki.resource_set.resource_set_ipv6(x.get("v6"))
+
+ cur.execute("INSERT registrant (registrant_handle, registry_handle, registrant_name, valid_until) VALUES (%s, %s, %s, %s)",
+ (child_handle, handle, child_handle, rpki.sundial.datetime.fromXMLtime(x.get("valid_until")).to_sql()))
+ child_id = cur.lastrowid
+ if asns:
+ cur.executemany("INSERT registrant_asn (start_as, end_as, registrant_id) VALUES (%s, %s, %s)",
+ ((a.min, a.max, child_id) for a in asns))
+ if ipv4:
+ cur.executemany("INSERT registrant_net (start_ip, end_ip, version, registrant_id) VALUES (%s, %s, 4, %s)",
+ ((a.min, a.max, child_id) for a in ipv4))
+ if ipv6:
+ cur.executemany("INSERT registrant_net (start_ip, end_ip, version, registrant_id) VALUES (%s, %s, 6, %s)",
+ ((a.min, a.max, child_id) for a in ipv6))
+
+ db.commit()
+
+ # Check for certificates before attempting anything else
+
+ hosted_cacert = findbase64(tree, "bpki_ca_certificate")
+ if not hosted_cacert:
+ print "Nothing else I can do without a trust anchor for the entity I'm hosting."
+ continue
+
+ rpkid_xcert = rpki.x509.X509(PEM_file = self.bpki_servers.fxcert(b64 = hosted_cacert.get_Base64(),
+ filename = handle + ".cacert.cer",
+ path_restriction = 1))
+
+ # See what rpkid and pubd already have on file for this entity.
+
+ if self.run_pubd:
+ client_pdus = dict((x.client_handle, x)
+ for x in call_pubd(rpki.publication.client_elt.make_pdu(action = "list"))
+ if isinstance(x, rpki.publication.client_elt))
+
+ rpkid_reply = call_rpkid(
+ rpki.left_right.self_elt.make_pdu( action = "get", tag = "self", self_handle = handle),
+ rpki.left_right.bsc_elt.make_pdu( action = "list", tag = "bsc", self_handle = handle),
+ rpki.left_right.repository_elt.make_pdu(action = "list", tag = "repository", self_handle = handle),
+ rpki.left_right.parent_elt.make_pdu( action = "list", tag = "parent", self_handle = handle),
+ rpki.left_right.child_elt.make_pdu( action = "list", tag = "child", self_handle = handle))
+
+ self_pdu = rpkid_reply[0]
+ bsc_pdus = dict((x.bsc_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.bsc_elt))
+ repository_pdus = dict((x.repository_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.repository_elt))
+ parent_pdus = dict((x.parent_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.parent_elt))
+ child_pdus = dict((x.child_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.child_elt))
+
+ pubd_query = []
+ rpkid_query = []
+
+ # There should be exactly one <self/> object per hosted entity, by definition
+
+ if (isinstance(self_pdu, rpki.left_right.report_error_elt) or
+ self_pdu.crl_interval != self_crl_interval or
+ self_pdu.regen_margin != self_regen_margin or
+ self_pdu.bpki_cert != rpkid_xcert):
+ rpkid_query.append(rpki.left_right.self_elt.make_pdu(
+ action = "create" if isinstance(self_pdu, rpki.left_right.report_error_elt) else "set",
+ tag = "self",
+ self_handle = handle,
+ bpki_cert = rpkid_xcert,
+ crl_interval = self_crl_interval,
+ regen_margin = self_regen_margin))
+
+ # In general we only need one <bsc/> per <self/>. BSC objects are a
+ # little unusual in that the PKCS #10 subelement is generated by rpkid
+ # in response to generate_keypair, so there's more of a separation
+ # between create and set than with other objects.
+
+ bsc_cert = findbase64(tree, "bpki_bsc_certificate")
+ bsc_crl = findbase64(tree, "bpki_crl", rpki.x509.CRL)
+
+ bsc_pdu = bsc_pdus.pop(bsc_handle, None)
+
+ if bsc_pdu is None:
+ rpkid_query.append(rpki.left_right.bsc_elt.make_pdu(
+ action = "create",
+ tag = "bsc",
+ self_handle = handle,
+ bsc_handle = bsc_handle,
+ generate_keypair = "yes"))
+ elif bsc_pdu.signing_cert != bsc_cert or bsc_pdu.signing_cert_crl != bsc_crl:
+ rpkid_query.append(rpki.left_right.bsc_elt.make_pdu(
+ action = "set",
+ tag = "bsc",
+ self_handle = handle,
+ bsc_handle = bsc_handle,
+ signing_cert = bsc_cert,
+ signing_cert_crl = bsc_crl))
+
+ rpkid_query.extend(rpki.left_right.bsc_elt.make_pdu(
+ action = "destroy", self_handle = handle, bsc_handle = b) for b in bsc_pdus)
+
+ bsc_req = None
+
+ if bsc_pdu and bsc_pdu.pkcs10_request:
+ bsc_req = bsc_pdu.pkcs10_request
+
+ # At present we need one <repository/> per <parent/>, not because
+ # rpkid requires that, but because pubd does. pubd probably should
+ # be fixed to support a single client allowed to update multiple
+ # trees, but for the moment the easiest way forward is just to
+ # enforce a 1:1 mapping between <parent/> and <repository/> objects
+
+ for repository in tree.getiterator("repository"):
+
+ repository_handle = repository.get("handle")
+ repository_pdu = repository_pdus.pop(repository_handle, None)
+ repository_uri = repository.get("service_uri")
+ repository_cert = findbase64(repository, "bpki_certificate")
+
+ if (repository_pdu is None or
+ repository_pdu.bsc_handle != bsc_handle or
+ repository_pdu.peer_contact_uri != repository_uri or
+ repository_pdu.bpki_cert != repository_cert):
+ rpkid_query.append(rpki.left_right.repository_elt.make_pdu(
+ action = "create" if repository_pdu is None else "set",
+ tag = repository_handle,
+ self_handle = handle,
+ repository_handle = repository_handle,
+ bsc_handle = bsc_handle,
+ peer_contact_uri = repository_uri,
+ bpki_cert = repository_cert))
+
+ rpkid_query.extend(rpki.left_right.repository_elt.make_pdu(
+ action = "destroy", self_handle = handle, repository_handle = r) for r in repository_pdus)
+
+ # <parent/> setup code currently assumes 1:1 mapping between
+ # <repository/> and <parent/>, and further assumes that the handles
+ # for an associated pair are the identical (that is:
+ # parent.repository_handle == parent.parent_handle).
+
+ for parent in tree.getiterator("parent"):
+
+ parent_handle = parent.get("handle")
+ parent_pdu = parent_pdus.pop(parent_handle, None)
+ parent_uri = parent.get("service_uri")
+ parent_myhandle = parent.get("myhandle")
+ parent_sia_base = parent.get("sia_base")
+ parent_cms_cert = findbase64(parent, "bpki_cms_certificate")
+ parent_https_cert = findbase64(parent, "bpki_https_certificate")
+
+ if (parent_pdu is None or
+ parent_pdu.bsc_handle != bsc_handle or
+ parent_pdu.repository_handle != parent_handle or
+ parent_pdu.peer_contact_uri != parent_uri or
+ parent_pdu.sia_base != parent_sia_base or
+ parent_pdu.sender_name != parent_myhandle or
+ parent_pdu.recipient_name != parent_handle or
+ parent_pdu.bpki_cms_cert != parent_cms_cert or
+ parent_pdu.bpki_https_cert != parent_https_cert):
+ rpkid_query.append(rpki.left_right.parent_elt.make_pdu(
+ action = "create" if parent_pdu is None else "set",
+ tag = parent_handle,
+ self_handle = handle,
+ parent_handle = parent_handle,
+ bsc_handle = bsc_handle,
+ repository_handle = parent_handle,
+ peer_contact_uri = parent_uri,
+ sia_base = parent_sia_base,
+ sender_name = parent_myhandle,
+ recipient_name = parent_handle,
+ bpki_cms_cert = parent_cms_cert,
+ bpki_https_cert = parent_https_cert))
+
+ rpkid_query.extend(rpki.left_right.parent_elt.make_pdu(
+ action = "destroy", self_handle = handle, parent_handle = p) for p in parent_pdus)
+
+ # Children are simpler than parents, because they call us, so no URL
+ # to construct and figuring out what certificate to use is their
+ # problem, not ours.
+
+ for child in tree.getiterator("child"):
+
+ child_handle = child.get("handle")
+ child_pdu = child_pdus.pop(child_handle, None)
+ child_cert = findbase64(child, "bpki_certificate")
+
+ if (child_pdu is None or
+ child_pdu.bsc_handle != bsc_handle or
+ child_pdu.bpki_cert != child_cert):
+ rpkid_query.append(rpki.left_right.child_elt.make_pdu(
+ action = "create" if child_pdu is None else "set",
+ tag = child_handle,
+ self_handle = handle,
+ child_handle = child_handle,
+ bsc_handle = bsc_handle,
+ bpki_cert = child_cert))
+
+ rpkid_query.extend(rpki.left_right.child_elt.make_pdu(
+ action = "destroy", self_handle = handle, child_handle = c) for c in child_pdus)
+
+ # Publication setup.
+
+ if self.run_pubd:
+
+ for f in self.entitydb.iterate("pubclients", "*.xml"):
+ c = etree_read(f)
+
+ client_handle = c.get("client_handle")
+ client_base_uri = c.get("sia_base")
+ client_bpki_cert = rpki.x509.X509(PEM_file = self.bpki_servers.fxcert(c.findtext("bpki_client_ta")))
+ client_pdu = client_pdus.pop(client_handle, None)
+
+ if (client_pdu is None or
+ client_pdu.base_uri != client_base_uri or
+ client_pdu.bpki_cert != client_bpki_cert):
+ pubd_query.append(rpki.publication.client_elt.make_pdu(
+ action = "create" if client_pdu is None else "set",
+ client_handle = client_handle,
+ bpki_cert = client_bpki_cert,
+ base_uri = client_base_uri))
+
+ pubd_query.extend(rpki.publication.client_elt.make_pdu(
+ action = "destroy", client_handle = p) for p in client_pdus)
+
+ # If we changed anything, ship updates off to daemons
+
+ if rpkid_query:
+ rpkid_reply = call_rpkid(*rpkid_query)
+ bsc_pdus = dict((x.bsc_handle, x) for x in rpkid_reply if isinstance(x, rpki.left_right.bsc_elt))
+ if bsc_handle in bsc_pdus and bsc_pdus[bsc_handle].pkcs10_request:
+ bsc_req = bsc_pdus[bsc_handle].pkcs10_request
+ for r in rpkid_reply:
+ assert not isinstance(r, rpki.left_right.report_error_elt)
+
+ if pubd_query:
+ assert self.run_pubd
+ pubd_reply = call_pubd(*pubd_query)
+ for r in pubd_reply:
+ assert not isinstance(r, rpki.publication.report_error_elt)
+
+ # Rewrite XML.
+
+ e = tree.find("bpki_bsc_pkcs10")
+ if e is None and bsc_req is not None:
+ e = SubElement(tree, "bpki_bsc_pkcs10")
+ elif bsc_req is None:
+ tree.remove(e)
+
+ if bsc_req is not None:
+ assert e is not None
+ s = bsc_req.get_Base64()
+ s = "\n".join(s[64*i : 64*(i+1)] for i in xrange(1 + len(s)/64)).strip()
+ e.text = "\n" + s + "\n"
+
+ # Something weird going on here with lxml linked against recent
+ # versions of libxml2. Looks like modifying the tree above somehow
+ # produces validation errors, but it works fine if we convert it to
+ # a string and parse it again. I'm not seeing any problems with any
+ # of the other code that uses lxml to do validation, just this one
+ # place. Weird. Kludge around it for now.
+ #
+ #tree = lxml.etree.fromstring(lxml.etree.tostring(tree))
+
+ etree_write(tree, xmlfile, validate = True)
+
+ db.close()
+
+
+ def do_myirbe(self, arg):
+ self.myirbe_main(arg.split())
+
+
if __name__ == "__main__":
- main(sys.argv[1:])
+ main()
diff --git a/myrpki.rototill/setup.py b/myrpki.rototill/setup.py
deleted file mode 100644
index 5e04a8fb..00000000
--- a/myrpki.rototill/setup.py
+++ /dev/null
@@ -1,357 +0,0 @@
-"""
-$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, time, glob
-import myrpki, rpki.config, rpki.cli, rpki.sundial
-
-try:
- from lxml.etree import Element, SubElement, ElementTree
-except ImportError:
- from xml.etree.ElementTree import Element, SubElement, ElementTree
-
-PEMElement = myrpki.PEMElement
-
-class main(rpki.cli.Cmd):
-
- prompt = "setup> "
-
- completedefault = rpki.cli.Cmd.filename_complete
-
- me = None
- parents = {}
- children = {}
- repositories = {}
-
-
- def __init__(self):
- os.environ["TZ"] = "UTC"
- time.tzset()
-
- self.cfg_file = os.getenv("MYRPKI_CONF", "myrpki.conf")
-
- opts, argv = getopt.getopt(sys.argv[1:], "c:h?", ["config=", "help"])
- for o, a in opts:
- if o in ("-c", "--config"):
- self.cfg_file = a
- elif o in ("-h", "--help", "-?"):
- argv = ["help"]
-
- if not argv or argv[0] != "help":
- self.read_config()
-
- rpki.cli.Cmd.__init__(self, argv)
-
-
- def read_config(self):
-
- self.cfg = rpki.config.parser(self.cfg_file, "myrpki")
- myrpki.openssl = self.cfg.get("openssl", "openssl")
- self.histfile = self.cfg.get("history_file", ".setup_history")
-
- self.handle = self.cfg.get("handle")
- self.run_rpkid = self.cfg.getboolean("run_rpkid")
- self.run_pubd = self.cfg.getboolean("run_pubd")
- self.run_rootd = self.cfg.getboolean("run_rootd")
-
- self.entitydb = myrpki.EntityDB(self.cfg)
-
- if self.run_rootd and (not self.run_pubd or not self.run_rpkid):
- raise RuntimeError, "Can't run rootd unless also running rpkid and pubd"
-
- self.bpki_resources = myrpki.CA(self.cfg_file, self.cfg.get("bpki_resources_directory"))
- if self.run_rpkid or self.run_pubd or self.run_rootd:
- self.bpki_servers = myrpki.CA(self.cfg_file, self.cfg.get("bpki_servers_directory"))
-
- self.pubd_contact_info = self.cfg.get("pubd_contact_info", "")
-
- self.rsync_module = self.cfg.get("publication_rsync_module")
- self.rsync_server = self.cfg.get("publication_rsync_server")
-
-
- def do_initialize(self, arg):
- if arg:
- raise RuntimeError, "This command takes no arguments"
-
- print "Generating RSA keys, this may take a little while..."
-
- self.bpki_resources.setup(self.cfg.get("bpki_resources_ta_dn",
- "/CN=%s BPKI Resource Trust Anchor" % self.handle))
- if self.run_rpkid or self.run_pubd or self.run_rootd:
- self.bpki_servers.setup(self.cfg.get("bpki_servers_ta_dn",
- "/CN=%s BPKI Server Trust Anchor" % self.handle))
-
- # Create entitydb directories.
-
- for i in ("parents", "children", "repositories", "pubclients"):
- d = self.entitydb(i)
- if not os.path.exists(d):
- os.makedirs(d)
-
- if self.run_rpkid or self.run_pubd or self.run_rootd:
-
- if self.run_rpkid:
- self.bpki_servers.ee(self.cfg.get("bpki_rpkid_ee_dn",
- "/CN=%s rpkid server certificate" % self.handle), "rpkid")
- self.bpki_servers.ee(self.cfg.get("bpki_irdbd_ee_dn",
- "/CN=%s irdbd server certificate" % self.handle), "irdbd")
- if self.run_pubd:
- self.bpki_servers.ee(self.cfg.get("bpki_pubd_ee_dn",
- "/CN=%s pubd server certificate" % self.handle), "pubd")
- if self.run_rpkid or self.run_pubd:
- self.bpki_servers.ee(self.cfg.get("bpki_irbe_ee_dn",
- "/CN=%s irbe client certificate" % self.handle), "irbe")
- if self.run_rootd:
- self.bpki_servers.ee(self.cfg.get("bpki_rootd_ee_dn",
- "/CN=%s rootd server certificate" % self.handle), "rootd")
-
- # Build the identity.xml file. Need to check for existing file so we don't
- # overwrite? Worry about that later.
-
- e = Element("identity", handle = self.handle)
- PEMElement(e, "bpki_ta", self.bpki_resources.cer)
- myrpki.etree_write(e, self.entitydb("identity.xml"))
-
- # If we're running rootd, construct a fake parent to go with it,
- # and cross-certify in both directions so we can talk to rootd.
-
- if self.run_rootd:
-
- e = Element("parent", parent_handle = self.handle, child_handle = self.handle,
- service_uri = "https://localhost:%s/" % self.cfg.get("rootd_server_port"),
- valid_until = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365)))
- PEMElement(e, "bpki_resource_ta", self.bpki_servers.cer)
- PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
- PEMElement(e, "bpki_child_ta", self.bpki_resources.cer)
- SubElement(e, "repository", type = "offer")
- myrpki.etree_write(e, self.entitydb("parents", "%s.xml" % self.handle))
-
- self.bpki_resources.xcert(self.bpki_servers.cer)
-
- rootd_child_fn = self.cfg.get("child-bpki-cert", None, "rootd")
- if not os.path.exists(rootd_child_fn):
- os.link(self.bpki_servers.xcert(self.bpki_resources.cer), rootd_child_fn)
-
- # If we're running pubd, construct repository request for it, as
- # if we had received an offer.
-
- if self.run_pubd:
- e = Element("repository", type = "request", handle = self.handle, parent_handle = self.handle)
- SubElement(e, "contact_info").text = self.pubd_contact_info
- PEMElement(e, "bpki_ta", self.bpki_resources.cer)
- myrpki.etree_write(e, self.entitydb("repositories", "%s.xml" % self.handle))
-
-
- def do_answer_child(self, arg):
-
- child_handle = None
-
- opts, argv = getopt.getopt(arg.split(), "", ["child_handle="])
- for o, a in opts:
- if o == "--child_handle":
- child_handle = a
-
- if len(argv) != 1:
- raise RuntimeError, "Need to specify filename for child.xml"
-
- if not self.run_rpkid:
- raise RuntimeError, "Don't (yet) know how to set up child unless we run rpkid"
-
- c = myrpki.etree_read(argv[0])
-
- if child_handle is None:
- child_handle = c.get("handle")
-
- print "Child calls itself %r, we call it %r" % (c.get("handle"), child_handle)
-
- self.bpki_servers.fxcert(c.findtext("bpki_ta"))
-
- e = Element("parent", parent_handle = self.handle, child_handle = child_handle,
- service_uri = "https://%s:%s/up-down/%s/%s" % (self.cfg.get("rpkid_server_host"),
- self.cfg.get("rpkid_server_port"),
- self.handle, child_handle),
- valid_until = str(rpki.sundial.now() + rpki.sundial.timedelta(days = 365)))
-
- PEMElement(e, "bpki_resource_ta", self.bpki_resources.cer)
- PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
- SubElement(e, "bpki_child_ta").text = c.findtext("bpki_ta")
-
- try:
- repo = None
- for f in self.entitydb.iterate("repositories", "*.xml"):
- r = myrpki.etree_read(f)
- if r.get("type") == "confirmed":
- if repo is not None:
- raise RuntimeError, "Too many repositories, I don't know what to do, not giving referral"
- repo_handle = os.path.splitext(os.path.split(f)[-1])[0]
- repo = r
- if repo is None:
- raise RuntimeError, "Couldn't find any usable repositories, not giving referral"
-
- if repo_handle == self.handle:
- SubElement(e, "repository", type = "offer")
- else:
- r = SubElement(e, "repository", type = "hint",
- proposed_sia_base = repo.get("sia_base") + child_handle + "/")
- SubElement(r, "contact_info").text = repo.findtext("contact_info")
- # CMS-signed blob authorizing use of part of our space by our
- # child goes here, once I've written that code.
-
- except RuntimeError, err:
- print err
-
- myrpki.etree_write(e, self.entitydb("children", "%s.xml" % child_handle))
-
-
- def do_process_parent_answer(self, arg):
-
- parent_handle = None
-
- opts, argv = getopt.getopt(arg.split(), "", ["parent_handle="])
- for o, a in opts:
- if o == "--parent_handle":
- parent_handle = a
-
- if len(argv) != 1:
- raise RuntimeError, "Need to specify filename for parent.xml on command line"
-
- p = myrpki.etree_read(argv[0])
-
- if parent_handle is None:
- parent_handle = p.get("parent_handle")
-
- print "Parent calls itself %r, we call it %r" % (p.get("parent_handle"), parent_handle)
- print "Parent calls us %r" % p.get("child_handle")
-
- self.bpki_resources.fxcert(p.findtext("bpki_resource_ta"))
- self.bpki_resources.fxcert(p.findtext("bpki_server_ta"))
-
- myrpki.etree_write(p, self.entitydb("parents", "%s.xml" % parent_handle))
-
- r = p.find("repository")
-
- if r is not None and r.get("type") in ("offer", "hint"):
- r.set("handle", self.handle)
- r.set("parent_handle", parent_handle)
- PEMElement(r, "bpki_ta", self.bpki_resources.cer)
- myrpki.etree_write(r, self.entitydb("repositories", "%s.xml" % parent_handle))
-
- else:
- print "Couldn't find repository offer or hint"
-
-
- def do_answer_repository_client(self, arg):
-
- sia_base = None
-
- opts, argv = getopt.getopt(arg.split(), "", ["sia_base="])
- for o, a in opts:
- if o == "--sia_base":
- sia_base = a
-
- if len(argv) != 1:
- raise RuntimeError, "Need to specify filename for client.xml"
-
- c = myrpki.etree_read(argv[0])
-
- # Critical thing at this point is to figure out what client's
- # sia_base value should be. Three cases:
- #
- # - client has no particular relationship to any other client:
- # sia_base is top-level, or as close as we can make it taking
- # rsyncd module into account (maybe homed under us, hmm, how do
- # we detect case where we are talking to ourself?)
- #
- # - client is a direct child of ours to whom we (in our parent
- # role) made an offer of publication service. client homes
- # under us, presumably.
- #
- # - client is a child of a client of ours who referred the new
- # client to us, along with a signed referral. signed referral
- # includes sia_base of referring client, new client homes under
- # that per referring client's wishes.
- #
- # ... which implies that there's a fourth case, where we are both
- # the client and the server.
-
- # Checking of signed referrals goes somewhere around here. Must
- # be after reading client's XML, but before deciding what the
- # client's sia_base and handle will be.
-
- # For the moment we cheat egregiously, no crypto, blind trust of
- # what we're sent, while I focus on the basic semantics.
-
- if sia_base is None and c.get("proposed_sia_base"):
- sia_base = c.get("proposed_sia_base")
- elif sia_base is None and c.get("handle") == self.handle:
- sia_base = "rsync://%s/%s/" % (self.rsync_server, self.rsync_module)
- else:
- sia_base = "rsync://%s/%s/%s/" % (self.rsync_server, self.rsync_module, c.get("handle"))
-
- client_handle = "/".join(sia_base.rstrip("/").split("/")[3:])
-
- parent_handle = c.get("parent_handle")
-
- print "Client calls itself %r, we call it %r" % (c.get("handle"), client_handle)
- print "Client says its parent handle is %r" % parent_handle
-
- self.bpki_servers.fxcert(c.findtext("bpki_ta"))
-
- e = Element("repository", type = "confirmed",
- repository_handle = self.handle,
- client_handle = client_handle,
- parent_handle = parent_handle,
- sia_base = sia_base,
- service_uri = "https://%s:%s/client/%s" % (self.cfg.get("pubd_server_host"),
- self.cfg.get("pubd_server_port"),
- client_handle))
-
- PEMElement(e, "bpki_server_ta", self.bpki_servers.cer)
- SubElement(e, "bpki_client_ta").text = c.findtext("bpki_ta")
- SubElement(e, "contact_info").text = self.pubd_contact_info
- myrpki.etree_write(e, self.entitydb("pubclients", "%s.xml" % client_handle.replace("/", ".")))
-
-
- def do_process_repository_answer(self, arg):
-
- argv = arg.split()
-
- if len(argv) != 1:
- raise RuntimeError, "Need to specify filename for repository.xml on command line"
-
- r = myrpki.etree_read(argv[0])
-
- parent_handle = r.get("parent_handle")
-
- print "Repository calls itself %r, calls us %r" % (r.get("repository_handle"), r.get("client_handle"))
- print "Repository response associated with parent_handle %r" % parent_handle
-
- myrpki.etree_write(r, self.entitydb("repositories", "%s.xml" % parent_handle))
-
-
- def do_compose_request_to_host(self, arg):
- pass
-
- def do_answer_hosted_entity(self, arg):
- pass
-
- def do_process_host_answer(self, arg):
- pass
-
-
-if __name__ == "__main__":
- main()
diff --git a/myrpki.rototill/yamltest.py b/myrpki.rototill/yamltest.py
index 7fb7b169..0871498c 100644
--- a/myrpki.rototill/yamltest.py
+++ b/myrpki.rototill/yamltest.py
@@ -67,9 +67,7 @@ this_dir = os.getcwd()
test_dir = cleanpath(this_dir, "test")
rpkid_dir = cleanpath(this_dir, "../rpkid")
-prog_myirbe = cleanpath(this_dir, "myirbe.py")
-prog_myrpki = cleanpath(this_dir, "myrpki.py")
-prog_setup = cleanpath(this_dir, "setup.py")
+prog_setup = cleanpath(this_dir, "myrpki.py")
prog_rpkid = cleanpath(rpkid_dir, "rpkid.py")
prog_irdbd = cleanpath(rpkid_dir, "irdbd.py")
prog_pubd = cleanpath(rpkid_dir, "pubd.py")
@@ -475,23 +473,19 @@ class allocation(object):
Run myirbe.py if this entity is not hosted by another engine.
"""
if not self.is_hosted():
- print "Running myirbe.py for", self.name
- cmd = ["python", prog_myirbe]
- cmd.extend(h.path("myrpki.xml") for h in self.hosts)
- subprocess.check_call(cmd, cwd = self.path())
+ self.run_setup("myirbe", *[h.path("myrpki.xml") for h in self.hosts])
def run_myrpki(self):
"""
Run myrpki.py for this entity.
"""
- print "Running myrpki.py for", self.name
- subprocess.check_call(("python", prog_myrpki), cwd = self.path())
+ self.run_setup("myrpki")
def run_setup(self, *args):
"""
Run setup.py for this entity.
"""
- print 'Running "%s" for %s' % (" ".join(("setup.py",) + args), self.name)
+ print 'Running "%s" for %s' % (" ".join(("myrpki",) + args), self.name)
subprocess.check_call(("python", prog_setup) + args, cwd = self.path())
def run_python_daemon(self, prog):