diff options
Diffstat (limited to 'rpkid')
-rw-r--r-- | rpkid/left-right-schema.rnc | 2 | ||||
-rw-r--r-- | rpkid/left-right-schema.rng | 4 | ||||
-rw-r--r-- | rpkid/rpki/http.py | 9 | ||||
-rw-r--r-- | rpkid/rpki/left_right.py | 100 | ||||
-rw-r--r-- | rpkid/rpki/publication.py | 11 | ||||
-rw-r--r-- | rpkid/rpki/relaxng.py | 4 | ||||
-rw-r--r-- | rpkid/rpki/rootd.py | 73 | ||||
-rw-r--r-- | rpkid/rpki/rpkid.py | 78 | ||||
-rw-r--r-- | rpkid/tests/revoke.yaml | 198 | ||||
-rw-r--r-- | rpkid/tests/smoketest.py | 1 |
10 files changed, 414 insertions, 66 deletions
diff --git a/rpkid/left-right-schema.rnc b/rpkid/left-right-schema.rnc index 3b058502..a2759f56 100644 --- a/rpkid/left-right-schema.rnc +++ b/rpkid/left-right-schema.rnc @@ -247,7 +247,7 @@ list_roa_requests_query = element list_roa_requests { list_roa_requests_reply = element list_roa_requests { tag, self_handle, - attribute asn { xsd:positiveInteger }, + attribute asn { xsd:nonNegativeInteger }, attribute ipv4 { ipv4_list }?, attribute ipv6 { ipv6_list }? } diff --git a/rpkid/left-right-schema.rng b/rpkid/left-right-schema.rng index 1ab21668..80beb1f5 100644 --- a/rpkid/left-right-schema.rng +++ b/rpkid/left-right-schema.rng @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - $Id: left-right-schema.rnc 3730 2011-03-21 12:42:43Z sra $ + $Id: left-right-schema.rnc 4346 2012-02-17 01:11:06Z sra $ RelaxNG Schema for RPKI left-right protocol. @@ -875,7 +875,7 @@ <ref name="tag"/> <ref name="self_handle"/> <attribute name="asn"> - <data type="positiveInteger"/> + <data type="nonNegativeInteger"/> </attribute> <optional> <attribute name="ipv4"> diff --git a/rpkid/rpki/http.py b/rpkid/rpki/http.py index 7d7e81ba..a0055ac9 100644 --- a/rpkid/rpki/http.py +++ b/rpkid/rpki/http.py @@ -766,7 +766,14 @@ class http_client(http_stream): self.update_timeout() if self.msg.code != 200: - raise rpki.exceptions.HTTPRequestFailed, "HTTP request failed with status %s, reason %s, response %s" % (self.msg.code, self.msg.reason, self.msg.body) + errmsg = "HTTP request failed" + if self.msg.code is not None: + errmsg += " with status %s" % self.msg.code + if self.msg.reason: + errmsg += ", reason %s" % self.msg.reason + if self.msg.body: + errmsg += ", response %s" % self.msg.body + raise rpki.exceptions.HTTPRequestFailed(errmsg) self.queue.return_result(self, self.msg, detach = self.expect_close) def handle_close(self): diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py index ac480ff0..17d665c9 100644 --- a/rpkid/rpki/left_right.py +++ b/rpkid/rpki/left_right.py @@ -190,6 +190,7 @@ class self_elt(data_elt): """ return rpki.rpkid.ghostbuster_obj.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + def serve_post_save_hook(self, q_pdu, r_pdu, cb, eb): """ Extra server actions for self_elt. @@ -248,6 +249,16 @@ class self_elt(data_elt): parent.serve_revoke_forgotten(iterator, eb) rpki.async.iterator(self.parents, loop, cb) + def serve_destroy_hook(self, cb, eb): + """ + Extra cleanup actions when destroying a self_elt. + """ + rpki.log.trace() + def loop(iterator, parent): + parent.delete(iterator) + rpki.async.iterator(self.parents, loop, cb) + + def serve_publish_world_now(self, cb, eb): """ Handle a left-right publish_world_now action for this self. @@ -704,6 +715,7 @@ class self_elt(data_elt): self.gctx.sql.sweep() self.gctx.irdb_query_roa_requests(self.self_handle, got_roa_requests, roa_requests_failed) + class bsc_elt(data_elt): """ <bsc/> (Business Signing Context) element. @@ -931,6 +943,39 @@ class parent_elt(data_elt): ca.reissue(cb = iterator, eb = eb) rpki.async.iterator(self.cas, loop, cb) + + def get_skis(self, cb, eb): + """ + Fetch SKIs that this parent thinks we have. In theory this should + agree with our own database, but in practice stuff can happen, so + sometimes we need to know what our parent thinks. + + Result is a dictionary with the resource class name as key and a + set of SKIs as value. + """ + + def done(r_msg): + cb(dict((rc.class_name, set(c.cert.gSKI() for c in rc.certs)) + for rc in r_msg.payload.classes)) + + rpki.up_down.list_pdu.query(self, done, eb) + + + def revoke_skis(self, rc_name, skis_to_revoke, cb, eb): + """ + Revoke a set of SKIs within a particular resource class. + """ + + def loop(iterator, ski): + rpki.log.debug("Asking parent %r to revoke class %r, SKI %s" % (self, rc_name, ski)) + q_pdu = rpki.up_down.revoke_pdu() + q_pdu.class_name = rc_name + q_pdu.ski = ski + self.query_up_down(q_pdu, lambda r_pdu: iterator(), eb) + + rpki.async.iterator(skis_to_revoke, loop, cb) + + def serve_revoke_forgotten(self, cb, eb): """ Handle a left-right revoke_forgotten action for this parent. @@ -945,30 +990,55 @@ class parent_elt(data_elt): require an explicit trigger. """ - def got_list(r_msg): + def got_skis(skis_from_parent): + + def loop(iterator, item): + rc_name, skis_to_revoke = item + if rc_name in ca_map: + for ca_detail in ca_map[rc_name].issue_response_candidate_ca_details: + skis_to_revoke.discard(ca_detail.latest_ca_cert.gSKI()) + self.revoke_skis(rc_name, skis_to_revoke, iterator, eb) ca_map = dict((ca.parent_resource_class, ca) for ca in self.cas) + rpki.async.iterator(skis_from_parent.items(), loop, cb) - def rc_loop(rc_iterator, rc): + self.get_skis(got_skis, eb) - if rc.class_name in ca_map: - def ski_loop(ski_iterator, ski): - rpki.log.warn("Revoking certificates missing from our database, class %r, SKI %s" % (rc.class_name, ski)) - rpki.up_down.revoke_pdu.query(ca, ski, lambda x: ski_iterator(), eb) + def delete(self, cb, delete_parent = True): + """ + Delete all the CA stuff under this parent, and perhaps the parent + itself. + """ - ca = ca_map[rc.class_name] - skis_parent_knows_about = set(c.cert.gSKI() for c in rc.certs) - skis_ca_knows_about = set(ca_detail.latest_ca_cert.gSKI() for ca_detail in ca.issue_response_candidate_ca_details) - skis_only_parent_knows_about = skis_parent_knows_about - skis_ca_knows_about - rpki.async.iterator(skis_only_parent_knows_about, ski_loop, rc_iterator) + def loop(iterator, ca): + self.gctx.checkpoint() + ca.delete(self, iterator) - else: - rc_iterator() + def revoke(): + self.gctx.checkpoint() + self.serve_revoke_forgotten(done, fail) + + def fail(e): + rpki.log.warn("Trouble getting parent to revoke certificates, blundering onwards: %s" % e) + done() - rpki.async.iterator(r_msg.payload.classes, rc_loop, cb) + def done(): + self.gctx.checkpoint() + self.gctx.sql.sweep() + if delete_parent: + self.sql_delete() + cb() + + rpki.async.iterator(self.cas, loop, revoke) + + + def serve_destroy_hook(self, cb, eb): + """ + Extra server actions when destroying a parent_elt. + """ - rpki.up_down.list_pdu.query(self, got_list, eb) + self.delete(cb, delete_parent = False) def query_up_down(self, q_pdu, cb, eb): diff --git a/rpkid/rpki/publication.py b/rpkid/rpki/publication.py index 14e3d36a..f60e3af5 100644 --- a/rpkid/rpki/publication.py +++ b/rpkid/rpki/publication.py @@ -219,7 +219,7 @@ class publication_object_elt(rpki.xml_utils.base_elt, publication_namespace): def serve_withdraw(self): """ - Withdraw an object. + Withdraw an object, then recursively delete empty directories. """ rpki.log.info("Withdrawing %s" % self.uri) filename = self.uri_to_filename() @@ -230,6 +230,15 @@ class publication_object_elt(rpki.xml_utils.base_elt, publication_namespace): raise rpki.exceptions.NoObjectAtURI, "No object published at %s" % self.uri else: raise + min_path_len = len(self.gctx.publication_base.rstrip("/")) + dirname = os.path.dirname(filename) + while len(dirname) > min_path_len: + try: + os.rmdir(dirname) + except OSError: + break + else: + dirname = os.path.dirname(dirname) def uri_to_filename(self): """ diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py index 24b3ab75..28fbe64a 100644 --- a/rpkid/rpki/relaxng.py +++ b/rpkid/rpki/relaxng.py @@ -6,7 +6,7 @@ import lxml.etree ## Parsed RelaxNG left_right schema left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" encoding="UTF-8"?> <!-- - $Id: left-right-schema.rnc 3730 2011-03-21 12:42:43Z sra $ + $Id: left-right-schema.rnc 4346 2012-02-17 01:11:06Z sra $ RelaxNG Schema for RPKI left-right protocol. @@ -881,7 +881,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <ref name="tag"/> <ref name="self_handle"/> <attribute name="asn"> - <data type="positiveInteger"/> + <data type="nonNegativeInteger"/> </attribute> <optional> <attribute name="ipv4"> diff --git a/rpkid/rpki/rootd.py b/rpkid/rpki/rootd.py index 8f3e6264..feceffc5 100644 --- a/rpkid/rpki/rootd.py +++ b/rpkid/rpki/rootd.py @@ -58,11 +58,15 @@ class issue_pdu(rpki.up_down.issue_pdu): class revoke_pdu(rpki.up_down.revoke_pdu): def serve_pdu(self, q_msg, r_msg, ignored, callback, errback): - rootd.subject_cert = get_subject_cert() + rpki.log.debug("Revocation requested for SKI %s" % self.ski) + subject_cert = rootd.get_subject_cert() if subject_cert is None or subject_cert.gSKI() != self.ski: raise rpki.exceptions.NotInDatabase + now = rpki.sundial.now() + rootd.revoke_subject_cert(now) rootd.del_subject_cert() rootd.del_subject_pkcs10() + rootd.generate_crl_and_manifest(now) r_msg.payload = rpki.up_down.revoke_response_pdu() r_msg.payload.class_name = self.class_name r_msg.payload.ski = self.ski @@ -95,8 +99,6 @@ class cms_msg(rpki.up_down.cms_msg): class main(object): - rpki_root_cert = None - def get_root_cert(self): rpki.log.debug("Read root cert %s" % self.rpki_root_cert_file) self.rpki_root_cert = rpki.x509.X509(Auto_file = self.rpki_root_cert_file) @@ -172,54 +174,65 @@ class main(object): rpki.log.info("Generating subject cert with resources " + str(resources)) req_key = pkcs10.getPublicKey() req_sia = pkcs10.get_SIA() - crldp = self.rpki_base_uri + self.rpki_root_crl - serial = now.totimestamp() + self.next_serial_number() subject_cert = self.rpki_root_cert.issue( keypair = self.rpki_root_key, subject_key = req_key, - serial = serial, + serial = self.serial_number, sia = req_sia, aia = self.rpki_root_cert_uri, - crldp = crldp, + crldp = self.rpki_base_uri + self.rpki_root_crl, resources = resources, notAfter = now + self.rpki_subject_lifetime) + self.set_subject_cert(subject_cert) + self.generate_crl_and_manifest(now) + return subject_cert + + def generate_crl_and_manifest(self, now): + subject_cert = self.get_subject_cert() + self.next_serial_number() + self.next_crl_number() crl = rpki.x509.CRL.generate( keypair = self.rpki_root_key, issuer = self.rpki_root_cert, - serial = serial, + serial = self.crl_number, thisUpdate = now, nextUpdate = now + self.rpki_subject_lifetime, - revokedCertificates = ()) + revokedCertificates = self.revoked) rpki.log.debug("Writing CRL %s" % (self.rpki_root_dir + self.rpki_root_crl)) f = open(self.rpki_root_dir + self.rpki_root_crl, "wb") f.write(crl.get_DER()) f.close() + manifest_content = [(self.rpki_root_crl, crl)] + if subject_cert is not None: + manifest_content.append((self.rpki_subject_cert, subject_cert)) manifest_resources = rpki.resource_set.resource_bag.from_inheritance() manifest_keypair = rpki.x509.RSA.generate() manifest_cert = self.rpki_root_cert.issue( keypair = self.rpki_root_key, subject_key = manifest_keypair.get_RSApublic(), - serial = serial + 1, + serial = self.serial_number, sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.rpki_base_uri + self.rpki_root_manifest)),), aia = self.rpki_root_cert_uri, - crldp = crldp, + crldp = self.rpki_base_uri + self.rpki_root_crl, resources = manifest_resources, notAfter = now + self.rpki_subject_lifetime, is_ca = False) manifest = rpki.x509.SignedManifest.build( - serial = serial, + serial = self.crl_number, thisUpdate = now, nextUpdate = now + self.rpki_subject_lifetime, - names_and_objs = [(self.rpki_subject_cert, subject_cert), (self.rpki_root_crl, crl)], + names_and_objs = manifest_content, keypair = manifest_keypair, certs = manifest_cert) rpki.log.debug("Writing manifest %s" % (self.rpki_root_dir + self.rpki_root_manifest)) f = open(self.rpki_root_dir + self.rpki_root_manifest, "wb") f.write(manifest.get_DER()) f.close() - self.set_subject_cert(subject_cert) - return subject_cert + + def revoke_subject_cert(self, now): + self.revoked.append((self.get_subject_cert().getSerial(), now.toASN1tuple(), ())) def compose_response(self, r_msg, pkcs10 = None): subject_cert = self.issue_subject_cert_maybe(pkcs10) @@ -260,11 +273,39 @@ class main(object): rpki.log.traceback() cb(500, reason = "Could not process PDU: %s" % e) + + def next_crl_number(self): + if self.crl_number is None: + try: + crl = rpki.x509.CRL(DER_file = self.rpki_root_dir + self.rpki_root_crl) + self.crl_number = crl.get_POWpkix().getExtension(rpki.oids.name2oid["cRLNumber"])[2] + except: + self.crl_number = 0 + self.crl_number += 1 + return self.crl_number + + + def next_serial_number(self): + if self.serial_number is None: + subject_cert = self.get_subject_cert() + if subject_cert is not None: + self.serial_number = subject_cert.getSerial() + 1 + else: + self.serial_number = 0 + self.serial_number += 1 + return self.serial_number + + def __init__(self): global rootd rootd = self # Gross, but simpler than what we'd have to do otherwise + self.rpki_root_cert = None + self.serial_number = None + self.crl_number = None + self.revoked = [] + os.environ["TZ"] = "UTC" time.tzset() @@ -286,6 +327,8 @@ class main(object): self.cfg = rpki.config.parser(self.cfg_file, "rootd") + rpki.log.enable_tracebacks = True + self.cfg.set_global_flags() self.bpki_ta = rpki.x509.X509(Auto_update = self.cfg.get("bpki-ta")) diff --git a/rpkid/rpki/rpkid.py b/rpkid/rpki/rpkid.py index 715a8aa2..7501a16a 100644 --- a/rpkid/rpki/rpkid.py +++ b/rpkid/rpki/rpkid.py @@ -462,8 +462,8 @@ class ca_obj(rpki.sql.sql_persistent): if rc_cert is None: - rpki.log.warn("SKI %s in resource class %s is in my database but missing from list_response received from %s, maybe parent certificate went away?" - % (ca_detail.public_key.gSKI(), rc.class_name, parent.parent_handle)) + rpki.log.warn("SKI %s in resource class %s is in database but missing from list_response to %s from %s, maybe parent certificate went away?" + % (ca_detail.public_key.gSKI(), rc.class_name, parent.self.self_handle, parent.parent_handle)) publisher = publication_queue() ca_detail.delete(ca = ca_detail.ca, publisher = publisher) return publisher.call_pubd(iterator, eb) @@ -495,8 +495,10 @@ class ca_obj(rpki.sql.sql_persistent): def done(): if cert_map: - rpki.log.warn("Certificate SKIs in resource class %s in list_response from parent %s that are missing from our database: %s" - % (rc.class_name, parent.parent_handle, ", ".join(c.cert.gSKI() for c in cert_map.values()))) + rpki.log.warn("Unknown certificate SKI%s %s in resource class %s in list_response to %s from %s, maybe you want to \"revoke_forgotten\"?" + % ("" if len(cert_map) == 1 else "s", + ", ".join(c.cert.gSKI() for c in cert_map.values()), + rc.class_name, parent.self.self_handle, parent.parent_handle)) self.gctx.checkpoint() cb() @@ -509,19 +511,19 @@ class ca_obj(rpki.sql.sql_persistent): for x in ca_details if x.latest_ca_cert is not None) for ski in skis_parent & skis_me: - rpki.log.debug("Parent %s and I agree that I have SKI %s in resource class %s" - % (parent.parent_handle, ski, rc.class_name)) + rpki.log.debug("Parent %s agrees that %s has SKI %s in resource class %s" + % (parent.parent_handle, parent.self.self_handle, ski, rc.class_name)) for ski in skis_parent - skis_me: - rpki.log.debug("Parent %s thinks I have SKI %s in resource class %s but I don't think so" - % (parent.parent_handle, ski, rc.class_name)) + rpki.log.debug("Parent %s thinks %s has SKI %s in resource class %s but I don't think so" + % (parent.parent_handle, parent.self.self_handle, ski, rc.class_name)) for ski in skis_me - skis_parent: - rpki.log.debug("I think I have SKI %s in resource class %s but parent %s doesn't think so" - % (ski, rc.class_name, parent.parent_handle)) + rpki.log.debug("I think %s has SKI %s in resource class %s but parent %s doesn't think so" + % (parent.self.self_handle, ski, rc.class_name, parent.parent_handle)) if ca_details: rpki.async.iterator(ca_details, loop, done) else: - rpki.log.warn("Existing resource class %s from parent %s with no certificates, rekeying" % (rc.class_name, parent.parent_handle)) + rpki.log.warn("Existing resource class %s to %s from %s with no certificates, rekeying" % (rc.class_name, parent.self.self_handle, parent.parent_handle)) self.gctx.checkpoint() self.rekey(cb, eb) @@ -625,9 +627,10 @@ class ca_obj(rpki.sql.sql_persistent): rpki.up_down.issue_pdu.query(parent, self, new_detail, done, eb) - def revoke(self, cb, eb): + def revoke(self, cb, eb, revoke_all = False): """ - Revoke deprecated ca_detail objects associated with this ca. + Revoke deprecated ca_detail objects associated with this CA, or + all ca_details associated with this CA if revoke_all is set. """ rpki.log.trace() @@ -635,7 +638,9 @@ class ca_obj(rpki.sql.sql_persistent): def loop(iterator, ca_detail): ca_detail.revoke(cb = iterator, eb = eb) - rpki.async.iterator(self.deprecated_ca_details, loop, cb) + ca_details = self.ca_details if revoke_all else self.deprecated_ca_details + + rpki.async.iterator(ca_details, loop, cb) def reissue(self, cb, eb): """ @@ -763,17 +768,23 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.state = "active" self.generate_crl(publisher = publisher) self.generate_manifest(publisher = publisher) - self.sql_mark_dirty() + self.sql_store() if predecessor is not None: predecessor.state = "deprecated" - predecessor.sql_mark_dirty() + predecessor.sql_store() for child_cert in predecessor.child_certs: child_cert.reissue(ca_detail = self, publisher = publisher) for roa in predecessor.roas: roa.regenerate(publisher = publisher) # Need to do something to regenerate ghostbusters here? + # Yes, I suspect so, since presumably we want the ghostbuster to + # be issued by the new ca_detail at this point. But check code. + + if predecessor.ghostbusters: + rpki.log.warn("Probably should be regenerating Ghostbusters %r here" % ghostbuster) + publisher.call_pubd(callback, errback) @@ -842,6 +853,8 @@ class ca_detail_obj(rpki.sql.sql_persistent): if r_msg.payload.ski != self.latest_ca_cert.gSKI(): raise rpki.exceptions.SKIMismatch + rpki.log.debug("Parent revoked %s, starting cleanup" % self.latest_ca_cert.gSKI()) + crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval) nextUpdate = rpki.sundial.now() @@ -881,6 +894,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.sql_mark_dirty() publisher.call_pubd(cb, eb) + rpki.log.debug("Asking parent to revoke CA certificate %s" % self.latest_ca_cert.gSKI()) rpki.up_down.revoke_pdu.query(ca, self.latest_ca_cert.gSKI(), parent_revoked, eb) def update(self, parent, ca, rc, sia_uri_changed, old_resources, callback, errback): @@ -963,8 +977,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): containing the newly issued cert. """ - assert child_cert is None or (child_cert.child_id == child.child_id and - child_cert.ca_detail_id == self.ca_detail_id) + assert child_cert is None or child_cert.child_id == child.child_id cert = self.latest_ca_cert.issue( keypair = self.private_key_id, @@ -985,6 +998,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): rpki.log.debug("Created new child_cert %r" % child_cert) else: child_cert.cert = cert + child_cert.ca_detail_id = self.ca_detail_id rpki.log.debug("Reusing existing child_cert %r" % child_cert) child_cert.ski = cert.get_SKI() @@ -1155,7 +1169,7 @@ class child_cert_obj(rpki.sql.sql_persistent): """ return self.ca_detail.ca.sia_uri + self.uri_tail - def revoke(self, publisher, generate_crl_and_manifest = False): + def revoke(self, publisher, generate_crl_and_manifest = True): """ Revoke a child cert. """ @@ -1207,7 +1221,7 @@ class child_cert_obj(rpki.sql.sql_persistent): needed = True if ca_detail != old_ca_detail: - rpki.log.debug("Issuer changed for %r" % self) + rpki.log.debug("Issuer changed for %r %s" % (self, self.uri)) needed = True must_revoke = old_resources.oversized(resources) or old_resources.valid_until > resources.valid_until @@ -1215,11 +1229,6 @@ class child_cert_obj(rpki.sql.sql_persistent): rpki.log.debug("Must revoke any existing cert(s) for %r" % self) needed = True - new_issuer = ca_detail != old_ca_detail - if new_issuer: - rpki.log.debug("Issuer changed for %r" % self) - needed = True - if resources.valid_until != old_resources.valid_until: rpki.log.debug("Validity changed for %r: %s %s" % (self, old_resources.valid_until, resources.valid_until)) needed = True @@ -1245,7 +1254,7 @@ class child_cert_obj(rpki.sql.sql_persistent): subject_key = self.cert.getPublicKey(), sia = sia, resources = resources, - child_cert = None if must_revoke or new_issuer else self, + child_cert = None if must_revoke else self, publisher = publisher) rpki.log.debug("New child_cert %r uri %s" % (child_cert, child_cert.uri)) @@ -1496,10 +1505,12 @@ class roa_obj(rpki.sql.sql_persistent): ca_detail = self.ca_detail if ca_detail is None or ca_detail.state != "active" or ca_detail.has_expired(): + rpki.log.debug("Searching for new ca_detail for ROA %r" % self) ca_detail = None for parent in self.self.parents: for ca in parent.cas: ca_detail = ca.active_ca_detail + assert ca_detail is None or ca_detail.state == "active" if ca_detail is not None and not ca_detail.has_expired(): resources = ca_detail.latest_ca_cert.get_3779resources() if v4.issubset(resources.v4) and v6.issubset(resources.v6): @@ -1507,10 +1518,15 @@ class roa_obj(rpki.sql.sql_persistent): ca_detail = None if ca_detail is not None: break + else: + rpki.log.debug("Keeping old ca_detail for ROA %r" % self) if ca_detail is None: raise rpki.exceptions.NoCoveringCertForROA, "Could not find a certificate covering %r" % self + rpki.log.debug("Using new ca_detail %r for ROA %r, ca_detail_state %s" % ( + ca_detail, self, ca_detail.state)) + ca = ca_detail.ca resources = rpki.resource_set.resource_bag(v4 = v4, v6 = v6) keypair = rpki.x509.RSA.generate() @@ -1530,6 +1546,7 @@ class roa_obj(rpki.sql.sql_persistent): if not fast: ca_detail.generate_manifest(publisher = publisher) + def published_callback(self, pdu): """ Check publication result. @@ -1559,8 +1576,8 @@ class roa_obj(rpki.sql.sql_persistent): roa = self.roa uri = self.uri - if ca_detail.state != 'active': - self.ca_detail_id = None + rpki.log.debug("Regenerating ROA %r, ca_detail %r state is %s" % ( + self, ca_detail, ca_detail.state)) if regenerate: self.generate(publisher = publisher, fast = fast) @@ -1569,7 +1586,10 @@ class roa_obj(rpki.sql.sql_persistent): rpki.rpkid.revoked_cert_obj.revoke(cert = cert, ca_detail = ca_detail) publisher.withdraw(cls = rpki.publication.roa_elt, uri = uri, obj = roa, repository = ca_detail.ca.parent.repository, handler = False if allow_failure else None) - self.sql_mark_deleted() + + if not regenerate: + self.sql_mark_deleted() + if not fast: ca_detail.generate_crl(publisher = publisher) ca_detail.generate_manifest(publisher = publisher) diff --git a/rpkid/tests/revoke.yaml b/rpkid/tests/revoke.yaml new file mode 100644 index 00000000..c006460d --- /dev/null +++ b/rpkid/tests/revoke.yaml @@ -0,0 +1,198 @@ +# $Id: smoketest.1.yaml 3881 2011-06-17 18:32:54Z sra $ + +# Copyright (C) 2009-2012 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. +# +# Portions copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") +# +# 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 ARIN DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ARIN 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. + +name: RIR +crl_interval: 5m +regen_margin: 2m +valid_for: 2d +kids: + - name: R0 + kids: + - name: Alice + ipv4: 192.0.2.1-192.0.2.33 + asn: 64533 + roa_request: + - asn: 42 + ipv4: 192.0.2.32/32 + - name: Bob + ipv4: 192.0.2.44-192.0.2.100 + ipv4: 10.3.0.0/16 + roa_request: + - asn: 666 + ipv4: 10.3.0.44/32 + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 + + +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + rekey: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- name: R0 + revoke: +- sleep 10 +--- +- shell sleep 1; dir=rcynic.`date +%s`.data; mkdir $dir; cd rcynic-data; pax -rwl . ../$dir; find . -type f -name '*.cer' | sort | xargs ../../../../utils/uri/uri -s >../${dir%.data}.uris; sleep 1 +- sleep 30 diff --git a/rpkid/tests/smoketest.py b/rpkid/tests/smoketest.py index fa686afd..3cb90d11 100644 --- a/rpkid/tests/smoketest.py +++ b/rpkid/tests/smoketest.py @@ -1264,6 +1264,7 @@ def run_rcynic(): subprocess.check_call((prog_rcynic, "-c", rcynic_name + ".conf"), env = env) subprocess.call(rcynic_stats, shell = True, env = env) last_rcynic_run = int(time.time()) + os.link("%s.xml" % rcynic_name, "%s.%s.xml" % (rcynic_name, last_rcynic_run)) def mangle_sql(filename): """ |