diff options
author | Rob Austein <sra@hactrn.net> | 2009-07-08 17:56:37 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2009-07-08 17:56:37 +0000 |
commit | b0efb7fe8e09cefd2ef7a595809efc8b33c2a06a (patch) | |
tree | 4d21c9d2566a0df43287785330470b8bd2241326 /myrpki/myirbe.py | |
parent | 8893d6699c8c1cda621e616a8074cbdaada6b732 (diff) |
Ready for initial smoketest.
svn path=/myrpki/Makefile; revision=2598
Diffstat (limited to 'myrpki/myirbe.py')
-rw-r--r-- | myrpki/myirbe.py | 206 |
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") |