diff options
-rw-r--r-- | rpkid/rpki/irdb/models.py | 8 | ||||
-rw-r--r-- | rpkid/rpki/rpkic.py | 236 | ||||
-rw-r--r-- | scripts/convert-from-entitydb-to-sql.py | 5 |
3 files changed, 118 insertions, 131 deletions
diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py index 20f38d6c..34656363 100644 --- a/rpkid/rpki/irdb/models.py +++ b/rpkid/rpki/irdb/models.py @@ -296,7 +296,8 @@ class CrossCertification(Certificate): return self.handle class HostedCA(Certificate): - hosted_ca = OneToOneField(CA, related_name = "hosting_ca") + issuer = django.db.models.ForeignKey(CA) + hosted = django.db.models.OneToOneField(CA, related_name = "hosted_by") def avow(self): self.certificate = self.issuer.certify( @@ -306,6 +307,9 @@ class HostedCA(Certificate): is_ca = True, pathLenConstraint = 1) + class Meta: + unique_together = ("issuer", "hosted") + def __unicode__(self): return self.hosted_ca.handle @@ -412,3 +416,5 @@ class Repository(CrossCertification): class Client(CrossCertification): issuer = django.db.models.ForeignKey(CA, related_name = "clients") + sia_base = django.db.models.TextField() + diff --git a/rpkid/rpki/rpkic.py b/rpkid/rpki/rpkic.py index f77eefbb..5a0aff85 100644 --- a/rpkid/rpki/rpkic.py +++ b/rpkid/rpki/rpkic.py @@ -178,6 +178,8 @@ class main(rpki.cli.Cmd): self.cfg = rpki.config.parser(self.cfg_file, "myrpki") + self.cfg.set_global_flags() + if self.handle is None: self.handle = self.cfg.get("handle") @@ -592,7 +594,8 @@ class main(rpki.cli.Cmd): rpki.irdb.Client.get_or_certify( issuer = self.server_ca, handle = client_handle, - ta = client_ta) + ta = client_ta, + sia_base = sia_base) e = Element("repository", type = "confirmed", client_handle = client_handle, @@ -828,8 +831,6 @@ class main(rpki.cli.Cmd): bsc_handle = "bsc" - 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. @@ -870,32 +871,18 @@ class main(rpki.cli.Cmd): for ca in rpki.irdb.CA.objects.exclude(handle = ""): - # rpkid_xcert is the server CA cross-certifying this resource CA - # so that stuff trusted by this resource CA will validate for - # rpkid. The resource cross-certifies parents and children with - # PathLen 0 so that parent and child EE certs can be rolled; - # this cross-certification therefore needs to be PathLen 1. - # - # HostedCA class in models is an attempt to represent this. - # Not yet hacked into other code. - - rpkid_xcert = rpki.x509.X509(PEM_file = self.bpki_servers.fxcert( - b64 = hosted_cacert.get_Base64(), - 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)) + pubd_reply = call_pubd(rpki.publication.client_elt.make_pdu(action = "list")) + client_pdus = dict((x.client_handle, x) for x in pubd_reply 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)) + rpki.left_right.self_elt.make_pdu( action = "get", tag = "self", self_handle = ca.handle), + rpki.left_right.bsc_elt.make_pdu( action = "list", tag = "bsc", self_handle = ca.handle), + rpki.left_right.repository_elt.make_pdu(action = "list", tag = "repository", self_handle = ca.handle), + rpki.left_right.parent_elt.make_pdu( action = "list", tag = "parent", self_handle = ca.handle), + rpki.left_right.child_elt.make_pdu( action = "list", tag = "child", self_handle = ca.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)) @@ -906,27 +893,28 @@ class main(rpki.cli.Cmd): pubd_query = [] rpkid_query = [] + self_cert = rpki.irdb.HostedCA.objects.get_or_certify( + issuer = self.server_ca, + hosted = ca)[0] + # 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): + self_pdu.bpki_cert != self_cert.certificate): 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, + self_handle = ca.handle, + bpki_cert = self.cert.certificate, 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) + # In general we only need one <bsc/> per <self/>. BSC objects + # are a little unusual in that the keypair and PKCS #10 + # subelement is generated by rpkid, so complete setup requires + # two round trips. bsc_pdu = bsc_pdus.pop(bsc_handle, None) @@ -934,25 +922,53 @@ class main(rpki.cli.Cmd): rpkid_query.append(rpki.left_right.bsc_elt.make_pdu( action = "create", tag = "bsc", - self_handle = handle, + self_handle = ca.handle, bsc_handle = bsc_handle, generate_keypair = "yes")) - elif bsc_pdu.signing_cert != bsc_cert or bsc_pdu.signing_cert_crl != bsc_crl: + + elif bsc_pdu.pkcs10_request is None: rpkid_query.append(rpki.left_right.bsc_elt.make_pdu( action = "set", tag = "bsc", - self_handle = handle, + self_handle = ca.handle, bsc_handle = bsc_handle, - signing_cert = bsc_cert, - signing_cert_crl = bsc_crl)) + generate_keypair = "yes")) rpkid_query.extend(rpki.left_right.bsc_elt.make_pdu( - action = "destroy", self_handle = handle, bsc_handle = b) for b in bsc_pdus) + action = "destroy", self_handle = ca.handle, bsc_handle = b) for b in bsc_pdus) + + # If we've already got actions queued up, run them now, so we + # can finish setting up the BSC before anything tries to use it. + + 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)) + bsc_pdu = bsc_pdus.pop(bsc_handle, None) + for r in rpkid_reply: + if isinstance(r, rpki.left_right.report_error_elt): + print "rpkid reported failure:", r.error_code + if r.error_text: + print r.error_text + if any(isinstance(r, rpki.left_right.report_error_elt) for r in rpkid_reply): + raise CouldntTalkToDaemon + + rpkid_query = [] - bsc_req = None + assert bsc_pdu.pkcs10_request is not None - if bsc_pdu and bsc_pdu.pkcs10_request: - bsc_req = bsc_pdu.pkcs10_request + bsc = rpki.irdb.BSC.get_or_certify( + issuer = ca, + handle = bsc_handle, + pkcs10 = bsc_pdu.pkcs10_request)[0] + + if bsc_pdu.signing_cert != bsc.certificate or bsc_pdu.signing_cert_crl != ca.latest_crl: + rpkid_query.append(rpki.left_right.bsc_elt.make_pdu( + action = "set", + tag = "bsc", + self_handle = ca.handle, + bsc_handle = bsc_handle, + signing_cert = bsc.certificate, + signing_cert_crl = ca.latest_crl)) # At present we need one <repository/> per <parent/>, not because # rpkid requires that, but because pubd does. pubd probably should @@ -960,122 +976,105 @@ class main(rpki.cli.Cmd): # 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"): + for repository in ca.repositories: - 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") + repository_pdu = repository_pdus.pop(repository.handle, None) 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): + repository_pdu.peer_contact_uri != repository.service_uri or + repository_pdu.bpki_cert != repository.certificate): 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, + tag = repository.handle, + self_handle = ca.handle, + repository_handle = repository.handle, bsc_handle = bsc_handle, - peer_contact_uri = repository_uri, - bpki_cert = repository_cert)) + peer_contact_uri = repository.service_uri, + bpki_cert = repository.certificate)) rpkid_query.extend(rpki.left_right.repository_elt.make_pdu( - action = "destroy", self_handle = handle, repository_handle = r) for r in repository_pdus) + action = "destroy", self_handle = ca.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"): + for parent in ca.parents: - 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_pdu = parent_pdus.pop(parent.handle, None) 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): + parent_pdu.repository_handle != parent.handle or + parent_pdu.peer_contact_uri != parent.service_uri or + parent_pdu.sia_base != parent.repository.sia_base or + parent_pdu.sender_name != parent.child_handle or + parent_pdu.recipient_name != parent.parent_handle or + parent_pdu.bpki_cms_cert != parent.certificate): 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, + tag = parent.handle, + self_handle = ca.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)) + repository_handle = parent.handle, + peer_contact_uri = parent.service_uri, + sia_base = parent.repository.sia_base, + sender_name = parent.child_handle, + recipient_name = parent.parent_handle, + bpki_cms_cert = parent.certificate)) rpkid_query.extend(rpki.left_right.parent_elt.make_pdu( - action = "destroy", self_handle = handle, parent_handle = p) for p in parent_pdus) + action = "destroy", self_handle = ca.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"): + for child in ca.children: - child_handle = child.get("handle") - child_pdu = child_pdus.pop(child_handle, None) - child_cert = findbase64(child, "bpki_certificate") + child_pdu = child_pdus.pop(child.handle, None) if (child_pdu is None or child_pdu.bsc_handle != bsc_handle or - child_pdu.bpki_cert != child_cert): + child_pdu.bpki_cert != child.certificate): 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, + tag = child.handle, + self_handle = ca.handle, + child_handle = child.handle, bsc_handle = bsc_handle, - bpki_cert = child_cert)) + bpki_cert = child.certificate)) rpkid_query.extend(rpki.left_right.child_elt.make_pdu( - action = "destroy", self_handle = handle, child_handle = c) for c in child_pdus) + action = "destroy", self_handle = ca.handle, child_handle = c) for c in child_pdus) # Publication setup. + # Um, why are we doing this per resource holder? + if self.run_pubd: - for f in self.entitydb.iterate("pubclients"): - c = etree_read(f) + for client in self.server_ca.clients: - 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( - b64 = c.findtext("bpki_client_ta"), - handle = client_handle, - bpki_type = rpki.irdb.Client)) - client_pdu = client_pdus.pop(client_handle, None) + 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): + client_pdu.base_uri != client.sia_base or + client_pdu.bpki_cert != client.certificate): 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)) + client_handle = client.handle, + bpki_cert = client.certificate, + base_uri = client.sia_base)) 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 - failed = False - 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)) @@ -1083,38 +1082,19 @@ class main(rpki.cli.Cmd): bsc_req = bsc_pdus[bsc_handle].pkcs10_request for r in rpkid_reply: if isinstance(r, rpki.left_right.report_error_elt): - failed = True print "rpkid reported failure:", r.error_code if r.error_text: print r.error_text - - if failed: - raise CouldntTalkToDaemon + if any(isinstance(r, rpki.left_right.report_error_elt) for r in rpkid_reply): + raise CouldntTalkToDaemon if pubd_query: assert self.run_pubd pubd_reply = call_pubd(*pubd_query) for r in pubd_reply: if isinstance(r, rpki.publication.report_error_elt): - failed = True print "pubd reported failure:", r.error_code if r.error_text: print r.error_text - - if failed: - raise CouldntTalkToDaemon - - # Rewrite XML. - - e = tree.find("bpki_bsc_pkcs10") - if e is not None: - tree.remove(e) - if bsc_req is not None: - SubElement(tree, "bpki_bsc_pkcs10").text = bsc_req.get_Base64() - - tree.set("service_uri", rpkid_base + "up-down/" + handle) - - etree_write(tree, xmlfile, - msg = None if xmlfile is my_xmlfile else 'Send this file back to the hosted entity ("%s")' % handle) - - irdb.close() + if any(isinstance(r, rpki.publication.report_error_elt) for r in pubd_reply): + raise CouldntTalkToDaemon diff --git a/scripts/convert-from-entitydb-to-sql.py b/scripts/convert-from-entitydb-to-sql.py index aa15b461..8c1e6bbb 100644 --- a/scripts/convert-from-entitydb-to-sql.py +++ b/scripts/convert-from-entitydb-to-sql.py @@ -363,11 +363,12 @@ for filename in glob.iglob(os.path.join(entitydb, "pubclients", "*.xml")): xcert_filenames.discard(xcfn) xcert = rpki.x509.X509(Auto_file = xcfn) - rpki.irdb.Repository.objects.get_or_create( + rpki.irdb.Client.objects.get_or_create( handle = client_handle, ta = ta, certificate = xcert, - issuer = server_ca) + issuer = server_ca, + sia_base = e.get("sia_base")) if copy_csv_data: |