aboutsummaryrefslogtreecommitdiff
path: root/myrpki/myirbe.py
diff options
context:
space:
mode:
Diffstat (limited to 'myrpki/myirbe.py')
-rw-r--r--myrpki/myirbe.py206
1 files changed, 106 insertions, 100 deletions
diff --git a/myrpki/myirbe.py b/myrpki/myirbe.py
index ac14c7f3..c392f9bb 100644
--- a/myrpki/myirbe.py
+++ b/myrpki/myirbe.py
@@ -18,7 +18,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import lxml.etree, base64, subprocess, sys, os, time, getopt, MySQLdb
+import lxml.etree, base64, subprocess, sys, os, time, re, getopt, MySQLdb
import rpki.https, rpki.config, rpki.resource_set, rpki.relaxng
import rpki.exceptions, rpki.left_right, rpki.log, rpki.x509, rpki.async
import myrpki
@@ -32,9 +32,11 @@ def findbase64(tree, name, b64type = rpki.x509.X509):
x = tree.findtext(tag(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 it in is fine.
+# For simple cases we don't really care what these value are, so long
+# as we're consistant about them, so wiring them in is fine.
+
bsc_handle = "bsc"
+repository_handle = "repository"
class caller(object):
"""
@@ -91,36 +93,38 @@ for o, a in opts:
cfg = rpki.config.parser(cfg_file, "myirbe")
-modified = False
+bpki_modified = False
# I suppose the distinguished names in these certificates might need
# to become configurable eventually.
bpki_rpkid = myrpki.CA(cfg_file, cfg.get("rpkid_ca_directory"))
-modified |= bpki_rpkid.setup("/CN=rpkid TA")
+bpki_modified |= bpki_rpkid.setup("/CN=rpkid TA")
for name in ("rpkid", "irdbd", "irbe_cli"):
- modified |= bpki_rpkid.ee("/CN=%s EE" % name, name)
+ bpki_modified |= bpki_rpkid.ee("/CN=%s EE" % name, name)
bpki_pubd = myrpki.CA(cfg_file, cfg.get("pubd_ca_directory"))
-modified |= bpki_pubd.setup("/CN=pubd TA")
+bpki_modified |= bpki_pubd.setup("/CN=pubd TA")
for name in ("pubd", "irbe_cli"):
- modified |= bpki_pubd.ee("/CN=%s EE" % name, name)
+ bpki_modified |= bpki_pubd.ee("/CN=%s EE" % name, name)
bpki_rootd = myrpki.CA(cfg_file, cfg.get("rootd_ca_directory"))
-modified |= bpki_rootd.setup("/CN=rootd TA")
-modified |= bpki_rootd.ee("/CN=rootd EE", "rootd")
+bpki_modified |= bpki_rootd.setup("/CN=rootd TA")
+bpki_modified |= bpki_rootd.ee("/CN=rootd EE", "rootd")
-if modified:
+if bpki_modified:
print "BPKI (re)initialized. You need to (re)start daemons before continuing."
sys.exit()
self_crl_interval = cfg.get("self_crl_interval", 300)
self_regen_margin = cfg.get("self_regen_margin", 120)
+rsync_base = cfg.get("rsync_base")
+pubd_base = cfg.get("pubd_base")
+rpkid_base = cfg.get("rpkid_base")
+
+# Nasty regexp for parsing rpkid's up-down service URLs
-# These probably come from the .conf file
-rsync_base = "rsync://server.example/"
-pubd_base = "https://localhost:4402"
-rpkid_base = "https://localhost:4404"
+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
@@ -244,19 +248,6 @@ for xmlfile in xmlfiles:
client_pdu = pubd_reply[0]
- # This is doubly wrong -- both the wrong value and (probably) set in the wrong place.
- # Do it anyway for now, for testing.
- pubd_base_uri = rsync_base + handle + "/"
-
- if isinstance(client_pdu, rpki.publication.report_error_elt) or client_pdu.base_uri != pubd_base_uri or client_pdu.bpki_cert != pubd_xcert:
- pubd_reply = call_pubd((rpki.publication.client_elt.make_pdu(
- action = "create" if isinstance(client_pdu, rpki.publication.report_error_elt) else "set",
- tag = "client",
- client_handle = handle,
- bpki_cert = pubd_xcert,
- base_uri = pubd_base_uri),))
- assert len(pubd_reply) == 1 and isinstance(pubd_reply[0], rpki.publication.client_elt) and pubd_reply[0].client_handle == handle
-
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),
@@ -270,6 +261,7 @@ for xmlfile in xmlfiles:
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
@@ -286,7 +278,7 @@ for xmlfile in xmlfiles:
crl_interval = self_crl_interval,
regen_margin = self_regen_margin))
- # In general we only need one BSC per <self/>. BSC objects are a
+ # 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.
@@ -320,53 +312,17 @@ for xmlfile in xmlfiles:
if bsc_pdu and bsc_pdu.pkcs10_request:
bsc_req = bsc_pdu.pkcs10_request
+ # In general we need one <repository/> per publication daemon with
+ # whom this <self/> has a relationship. In practice there is rarely
+ # (never?) a good reason for a single <self/> to use multiple
+ # publication services, so in normal use we only need one
+ # <repository/> object.
- for parent in tree.getiterator(tag("parent")):
-
- # Perhaps what we need here is to have the hosting entity's handle and
- # sia base in the .conf file, then as we go we check each hosted
- # entity to see whether (a) it's the right .xml file and (b) its
- # handle matches the hosting handle. We can put hosted entities under
- # the self-hosted entity automatically, but the self-hosted entity
- # will need another .conf file entry telling it the parent's service
- # uri (or do we get that from the .xml somehow?)
- #
- # Ok, so part of my confusion is that I've never tested multiple
- # parents before. The parent sia_base and pubd client base_uri are
- # almost the same thing, but not quite. pubd base_uri is what pubd
- # insists upon as the head of the publication URI, or it won't
- # publish. parent sia_base is either the base URI at which rpkid will
- # publish stuff issued by the cert issued by this parent, or is the
- # head of that base URI (if the parent made an acceptable suggestion,
- # where acceptable means that the configured sia_base is the head of
- # the parent's suggestion).
- #
- # I think this boils down to meaning that if we have multiple
- # parents, we also need multiple repository objects, which -may- in
- # turn mean multiple pubd client objects -- if our pubd is relevant
- # at all. Assume for now that if we're running pubd at all,
- # everything our rpkid generates goes into it.
- #
- # We also need to compare all these URIs against pubd's publication
- # base, so we know whether this is our problem or not. For testbed,
- # we probably are, at least initially.
-
- parent_handle = parent.get("handle")
-
- repository_pdu = repository_pdus.pop(parent_handle, None)
- parent_pdu = parent_pdus.pop(parent_handle, None)
-
- parent_uri = parent.get("parent_service_uri")
- parent_cert = findbase64(parent, "parent_bpki_certificate")
-
- repository_uri = parent.get("repository_service_uri")
- repository_cert = findbase64(parent, "repository_bpki_certificate")
-
- # This is wrong, should be parent's sia_base + handle + "/", but
- # how do we get parent's sia_base in this setup?
- #
- parent_sia_base = rsync_base + handle + "/"
- pubd_base_uri = parent_sia_base
+ repository_cert = findbase64(tree, "bpki_repository_certificate")
+ if repository_cert:
+
+ repository_pdu = repository_pdus.pop(repository_handle, None)
+ repository_uri = pubd_base + "/client/" + handle
if (repository_pdu is None or
repository_pdu.bsc_handle != bsc_handle or
@@ -375,40 +331,86 @@ for xmlfile in xmlfiles:
repository_pdu.bpki_https_cert != repository_cert):
rpkid_query.append(rpki.left_right.repository_elt.make_pdu(
action = "create" if repository_pdu is None else "set",
- tag = parent_handle,
+ tag = repository_handle,
self_handle = handle,
- repository_handle = parent_handle,
+ repository_handle = repository_handle,
bsc_handle = bsc_handle,
peer_contact_uri = repository_uri,
bpki_cms_cert = repository_cert,
bpki_https_cert = repository_cert))
- 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 != handle or
- parent_pdu.recipient_name != parent_handle or
- parent_pdu.bpki_cms_cert != parent_cert or
- parent_pdu.bpki_https_cert != parent_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 = handle,
- recipient_name = parent_handle,
- bpki_cms_cert = parent_cert,
- bpki_https_cert = parent_cert))
-
rpkid_query.extend(rpki.left_right.repository_elt.make_pdu(
action = "destroy", self_handle = handle, repository_handle = r) for r in repository_pdus)
+ # Ok, here's where the fun starts. We need to figure out what the
+ # publication naming scheme is for this <self/>, based on how many
+ # <parent/> object this <self/> has and what the relationship is
+ # between this <self/> and the entity operating this irbe and pubd.
+ #
+ # For now we only handle the simplest cases: if a hosted entity is a
+ # direct child of the hosting entity, we place it under the hosting
+ # entity; in all other cases, we use a separate subtree. This is
+ # suboptimal in the long run.
+
+ parents = tree.getiterator(tag("parent"))
+
+ if parents:
+
+ need_own_pub_point = True
+ if handle != my_handle and len(parents) == 1 and parents[0].get("service_uri").startwith(rpkid_base):
+ m = updown_regexp.match(parents[0].get("service_uri"))
+ if m:
+ self_part, child_part = m.groups()
+ if self_part == my_handle and child_part == handle:
+ need_own_pub_point = False
+
+ if need_own_pub_point:
+ pubd_base_uri = rsync_base + handle + "/"
+ else:
+ pubd_base_uri = rsync_base + my_handle + "/" + handle + "/"
+
+ if isinstance(client_pdu, rpki.publication.report_error_elt) or client_pdu.base_uri != pubd_base_uri or client_pdu.bpki_cert != pubd_xcert:
+ pubd_query.append(rpki.publication.client_elt.make_pdu(
+ action = "create" if isinstance(client_pdu, rpki.publication.report_error_elt) else "set",
+ client_handle = handle,
+ bpki_cert = pubd_xcert,
+ base_uri = pubd_base_uri))
+
+ for parent in parents:
+
+ parent_handle = parent.get("handle")
+ parent_pdu = parent_pdus.pop(parent_handle, None)
+ parent_uri = parent.get("service_uri")
+ parent_cert = findbase64(parent, "bpki_certificate")
+
+ if need_own_pub_point:
+ parent_sia_base = pubd_base_uri + parent_handle + "/"
+ else:
+ parent_sia_base = pubd_base_uri
+
+ if (parent_pdu is None or
+ parent_pdu.bsc_handle != bsc_handle or
+ parent_pdu.repository_handle != repository_handle or
+ parent_pdu.peer_contact_uri != parent_uri or
+ parent_pdu.sia_base != parent_sia_base or
+ parent_pdu.sender_name != handle or
+ parent_pdu.recipient_name != parent_handle or
+ parent_pdu.bpki_cms_cert != parent_cert or
+ parent_pdu.bpki_https_cert != parent_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 = repository_handle,
+ peer_contact_uri = parent_uri,
+ sia_base = parent_sia_base,
+ sender_name = handle,
+ recipient_name = parent_handle,
+ bpki_cms_cert = parent_cert,
+ bpki_https_cert = parent_cert))
+
rpkid_query.extend(rpki.left_right.parent_elt.make_pdu(
action = "destroy", self_handle = handle, parent_handle = p) for p in parent_pdus)
@@ -438,6 +440,10 @@ for xmlfile in xmlfiles:
if bsc_handle in bsc_pdus and bsc_pdus[bsc_handle].pkcs10_request:
bsc_req = bsc_pdus[bsc_handle].pkcs10_request
+ if pubd_query:
+ pubd_reply = call_pubd(pubd_query)
+ assert len(pubd_reply) == 1 and isinstance(pubd_reply[0], rpki.publication.client_elt) and pubd_reply[0].client_handle == handle
+
e = tree.find(tag("bpki_bsc_pkcs10"))
if e is None and bsc_req is not None:
e = lxml.etree.SubElement(tree, "bpki_bsc_pkcs10")