diff options
-rw-r--r-- | rpkid/Makefile.in | 2 | ||||
-rw-r--r-- | rpkid/irdbd.sql | 11 | ||||
-rw-r--r-- | rpkid/left-right-schema.rnc | 15 | ||||
-rw-r--r-- | rpkid/left-right-schema.rng | 24 | ||||
-rw-r--r-- | rpkid/rpki-sql-setup.py | 4 | ||||
-rw-r--r-- | rpkid/rpki/http.py | 7 | ||||
-rw-r--r-- | rpkid/rpki/irdbd.py | 32 | ||||
-rw-r--r-- | rpkid/rpki/left_right.py | 232 | ||||
-rw-r--r-- | rpkid/rpki/oids.py | 18 | ||||
-rw-r--r-- | rpkid/rpki/publication.py | 4 | ||||
-rw-r--r-- | rpkid/rpki/relaxng.py | 24 | ||||
-rw-r--r-- | rpkid/rpki/rpki_engine.py | 213 | ||||
-rw-r--r-- | rpkid/rpki/up_down.py | 26 | ||||
-rw-r--r-- | rpkid/rpki/x509.py | 35 | ||||
-rw-r--r-- | rpkid/rpki/xml_utils.py | 4 | ||||
-rw-r--r-- | rpkid/rpkid.sql | 18 | ||||
-rw-r--r-- | rpkid/tests/smoketest.py | 55 |
17 files changed, 529 insertions, 195 deletions
diff --git a/rpkid/Makefile.in b/rpkid/Makefile.in index 05c42252..11012218 100644 --- a/rpkid/Makefile.in +++ b/rpkid/Makefile.in @@ -116,7 +116,7 @@ tags: Makefile find . -type f \( -name '*.py' -o -name '*.sql' -o -name '*.rnc' -o -name '*.py.in' \) ! -name relaxng.py ! -name __doc__.py | etags - lint: - pylint --rcfile ../scripts/pylint.rc rpki/[a-z]*.py irbe_cli.py irdbd.py pubd.py rootd.py rpkid.py tests/smoketest.py tests/testpoke.py ../myrpki/myrpki.py ../myrpki/yamltest.py + pylint --rcfile ../scripts/pylint.rc rpki/[a-z]*.py *d.py rpki-*.py myrpki.py irbe_cli.py tests/*.py # Documentation diff --git a/rpkid/irdbd.sql b/rpkid/irdbd.sql index 577bb4f9..fd461b42 100644 --- a/rpkid/irdbd.sql +++ b/rpkid/irdbd.sql @@ -1,6 +1,6 @@ -- $Id$ --- Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +-- Copyright (C) 2009--2011 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 @@ -41,6 +41,7 @@ DROP TABLE IF EXISTS roa_request; DROP TABLE IF EXISTS registrant_net; DROP TABLE IF EXISTS registrant_asn; DROP TABLE IF EXISTS registrant; +DROP TABLE IF EXISTS gbr_request; CREATE TABLE registrant ( registrant_id SERIAL NOT NULL, @@ -91,6 +92,14 @@ CREATE TABLE roa_request_prefix ( FOREIGN KEY (roa_request_id) REFERENCES roa_request (roa_request_id) ON DELETE CASCADE ) ENGINE=InnoDB; +CREATE TABLE gbr_request ( + gbr_request_id SERIAL NOT NULL, + self_handle VARCHAR(40) NOT NULL, + parent_handle VARCHAR(40), + vcard LONGBLOB NOT NULL, + PRIMARY KEY (gbr_request_id) +) ENGINE=InnoDB; + -- Local Variables: -- indent-tabs-mode: nil -- End: diff --git a/rpkid/left-right-schema.rnc b/rpkid/left-right-schema.rnc index 28f26cae..85f2348a 100644 --- a/rpkid/left-right-schema.rnc +++ b/rpkid/left-right-schema.rnc @@ -5,7 +5,7 @@ # libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so # run the compact syntax through trang to get XML syntax. # -# Copyright (C) 2009-2010 Internet Systems Consortium ("ISC") +# Copyright (C) 2009-2011 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 @@ -50,6 +50,7 @@ query_elt |= parent_query query_elt |= child_query query_elt |= repository_query query_elt |= list_roa_requests_query +query_elt |= list_gbr_requests_query query_elt |= list_resources_query query_elt |= list_published_objects_query query_elt |= list_received_resources_query @@ -62,6 +63,7 @@ reply_elt |= child_reply reply_elt |= repository_reply reply_elt |= list_resources_reply reply_elt |= list_roa_requests_reply +reply_elt |= list_gbr_requests_reply reply_elt |= list_published_objects_reply reply_elt |= list_received_resources_reply reply_elt |= report_error_reply @@ -250,6 +252,17 @@ list_roa_requests_reply = element list_roa_requests { attribute ipv6 { ipv6_list }? } +# <list_gbr_requests/> element + +list_gbr_requests_query = element list_gbr_requests { + tag, self_handle, parent_handle +} + +list_gbr_requests_reply = element list_gbr_requests { + tag, self_handle, parent_handle, + xsd:string +} + # <list_published_objects/> element list_published_objects_query = element list_published_objects { diff --git a/rpkid/left-right-schema.rng b/rpkid/left-right-schema.rng index 3f223b45..a3e74de6 100644 --- a/rpkid/left-right-schema.rng +++ b/rpkid/left-right-schema.rng @@ -7,7 +7,7 @@ libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so run the compact syntax through trang to get XML syntax. - Copyright (C) 2009-2010 Internet Systems Consortium ("ISC") + Copyright (C) 2009-2011 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 @@ -84,6 +84,9 @@ <ref name="list_roa_requests_query"/> </define> <define name="query_elt" combine="choice"> + <ref name="list_gbr_requests_query"/> + </define> + <define name="query_elt" combine="choice"> <ref name="list_resources_query"/> </define> <define name="query_elt" combine="choice"> @@ -115,6 +118,9 @@ <ref name="list_roa_requests_reply"/> </define> <define name="reply_elt" combine="choice"> + <ref name="list_gbr_requests_reply"/> + </define> + <define name="reply_elt" combine="choice"> <ref name="list_published_objects_reply"/> </define> <define name="reply_elt" combine="choice"> @@ -883,6 +889,22 @@ </optional> </element> </define> + <!-- <list_gbr_requests/> element --> + <define name="list_gbr_requests_query"> + <element name="list_gbr_requests"> + <ref name="tag"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> + </element> + </define> + <define name="list_gbr_requests_reply"> + <element name="list_gbr_requests"> + <ref name="tag"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> + <data type="string"/> + </element> + </define> <!-- <list_published_objects/> element --> <define name="list_published_objects_query"> <element name="list_published_objects"> diff --git a/rpkid/rpki-sql-setup.py b/rpkid/rpki-sql-setup.py index 360b76a9..dc463620 100644 --- a/rpkid/rpki-sql-setup.py +++ b/rpkid/rpki-sql-setup.py @@ -4,7 +4,7 @@ root password, pulls other information from rpki.conf. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -21,7 +21,7 @@ PERFORMANCE OF THIS SOFTWARE. from __future__ import with_statement -import os, getopt, sys, time, rpki.config, getpass, warnings +import os, getopt, sys, rpki.config, getpass, warnings # Silence warning while loading MySQLdb in Python 2.6, sigh if hasattr(warnings, "catch_warnings"): diff --git a/rpkid/rpki/http.py b/rpkid/rpki/http.py index 042542b2..90b8c758 100644 --- a/rpkid/rpki/http.py +++ b/rpkid/rpki/http.py @@ -3,7 +3,7 @@ HTTP utilities, both client and server. $Id$ -Copyright (C) 2009-2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009-2011 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 @@ -198,6 +198,7 @@ class http_message(object): raise rpki.exceptions.HTTPBadVersion, "Couldn't parse version %s" % version self.version = tuple(int(i) for i in version[5:].split(".")) + @property def persistent(self): """ Figure out whether this HTTP message encourages a persistent connection. @@ -492,7 +493,7 @@ class http_server(http_stream): pass the message body, path, and a reply callback to the handler. """ self.log("Received request %s %s" % (self.msg.cmd, self.msg.path)) - if not self.msg.persistent(): + if not self.msg.persistent: self.expect_close = True handler = self.find_handler(self.msg.path) error = None @@ -717,7 +718,7 @@ class http_client(http_stream): self.log("Message received, state %s" % self.state) - if not self.msg.persistent(): + if not self.msg.persistent: self.expect_close = True if self.state != "request-sent": diff --git a/rpkid/rpki/irdbd.py b/rpkid/rpki/irdbd.py index b5edf70e..bb05fee3 100644 --- a/rpkid/rpki/irdbd.py +++ b/rpkid/rpki/irdbd.py @@ -5,7 +5,7 @@ Usage: python irdbd.py [ { -c | --config } configfile ] [ { -h | --help } ] $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -50,6 +50,7 @@ else: class main(object): + def handle_list_resources(self, q_pdu, r_msg): r_pdu = rpki.left_right.list_resources_elt() @@ -87,6 +88,7 @@ class main(object): r_msg.append(r_pdu) + def handle_list_roa_requests(self, q_pdu, r_msg): self.cur.execute( @@ -112,10 +114,37 @@ class main(object): r_msg.append(r_pdu) + + def handle_list_gbr_requests(self, q_pdu, r_msg): + + self.cur.execute( + "SELECT vcard FROM gbr_request self_handle = %s and parent_handle = %s", + (q_pdu.self_handle, q_pdu.parent_handle)) + + vcards = [result[0] for result in self.cur.fetchall()] + + if not vcards: + + self.cur.execute( + "SELECT vcard FROM gbr_request self_handle = %s and parent_handle IS NULL", + (q_pdu.self_handle,)) + + vcards = [result[0] for result in self.cur.fetchall()] + + for vcard in vcards: + r_pdu = rpki.left_right.list_gbr_requests_elt() + r_pdu.tag = q_pdu.tag + r_pdu.self_handle = q_pdu.self_handle + r_pdu.parent_handle = q_pdu.parent_handle + r_pdu.vcard = vcard + r_msg.append(r_pdu) + + handle_dispatch = { rpki.left_right.list_resources_elt : handle_list_resources, rpki.left_right.list_roa_requests_elt : handle_list_roa_requests } + def handler(self, query, path, cb): try: @@ -168,6 +197,7 @@ class main(object): cb(500, "Unhandled exception %s: %s" % (data.__class__.__name__, data)) + def __init__(self): os.environ["TZ"] = "UTC" diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py index d74c1ef7..80583d47 100644 --- a/rpkid/rpki/left_right.py +++ b/rpkid/rpki/left_right.py @@ -3,7 +3,7 @@ RPKI "left-right" protocol. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -57,12 +57,14 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name self_id = None self_handle = None + @property def self(self): """ Fetch self object to which this object links. """ return self_elt.sql_fetch(self.gctx, self.self_id) + @property def bsc(self): """ Return BSC object to which this object links. @@ -146,30 +148,35 @@ class self_elt(data_elt): bpki_cert = None bpki_glue = None + @property def bscs(self): """ Fetch all BSC objects that link to this self object. """ return bsc_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + @property def repositories(self): """ Fetch all repository objects that link to this self object. """ return repository_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + @property def parents(self): """ Fetch all parent objects that link to this self object. """ return parent_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + @property def children(self): """ Fetch all child objects that link to this self object. """ return child_elt.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,)) + @property def roas(self): """ Fetch all ROA objects that link to this self object. @@ -205,7 +212,7 @@ class self_elt(data_elt): rpki.log.trace() def loop(iterator, parent): parent.serve_rekey(iterator, eb) - rpki.async.iterator(self.parents(), loop, cb) + rpki.async.iterator(self.parents, loop, cb) def serve_revoke(self, cb, eb): """ @@ -214,7 +221,7 @@ class self_elt(data_elt): rpki.log.trace() def loop(iterator, parent): parent.serve_revoke(iterator, eb) - rpki.async.iterator(self.parents(), loop, cb) + rpki.async.iterator(self.parents, loop, cb) def serve_reissue(self, cb, eb): """ @@ -223,7 +230,7 @@ class self_elt(data_elt): rpki.log.trace() def loop(iterator, parent): parent.serve_reissue(iterator, eb) - rpki.async.iterator(self.parents(), loop, cb) + rpki.async.iterator(self.parents, loop, cb) def serve_revoke_forgotten(self, cb, eb): """ @@ -232,7 +239,7 @@ class self_elt(data_elt): rpki.log.trace() def loop(iterator, parent): parent.serve_revoke_forgotten(iterator, eb) - rpki.async.iterator(self.parents(), loop, cb) + rpki.async.iterator(self.parents, loop, cb) def serve_publish_world_now(self, cb, eb): """ @@ -255,16 +262,16 @@ class self_elt(data_elt): def loop(iterator, parent): q_msg = rpki.publication.msg.query() - for ca in parent.cas(): + for ca in parent.cas: ca_detail = ca.fetch_active() if ca_detail is not None: - q_msg.append(rpki.publication.crl_elt.make_publish(ca_detail.crl_uri(ca), ca_detail.latest_crl)) - q_msg.append(rpki.publication.manifest_elt.make_publish(ca_detail.manifest_uri(ca), ca_detail.latest_manifest)) - q_msg.extend(rpki.publication.certificate_elt.make_publish(c.uri(ca), c.cert) for c in ca_detail.child_certs()) - q_msg.extend(rpki.publication.roa_elt.make_publish(r.uri(), r.roa) for r in ca_detail.roas() if r.roa is not None) - parent.repository().call_pubd(iterator, eb, q_msg) + q_msg.append(rpki.publication.crl_elt.make_publish(ca_detail.crl_uri, ca_detail.latest_crl)) + q_msg.append(rpki.publication.manifest_elt.make_publish(ca_detail.manifest_uri, ca_detail.latest_manifest)) + q_msg.extend(rpki.publication.certificate_elt.make_publish(c.uri, c.cert) for c in ca_detail.child_certs) + q_msg.extend(rpki.publication.roa_elt.make_publish(r.uri, r.roa) for r in ca_detail.roas if r.roa is not None) + parent.repository.call_pubd(iterator, eb, q_msg) - rpki.async.iterator(self.parents(), loop, cb) + rpki.async.iterator(self.parents, loop, cb) def serve_run_now(self, cb, eb): """ @@ -334,7 +341,7 @@ class self_elt(data_elt): def parent_loop(parent_iterator, parent): def got_list(r_msg): - ca_map = dict((ca.parent_resource_class, ca) for ca in parent.cas()) + ca_map = dict((ca.parent_resource_class, ca) for ca in parent.cas) self.gctx.checkpoint() def class_loop(class_iterator, rc): @@ -379,7 +386,7 @@ class self_elt(data_elt): rpki.up_down.list_pdu.query(parent, got_list, list_failed) - rpki.async.iterator(self.parents(), parent_loop, callback) + rpki.async.iterator(self.parents, parent_loop, callback) def update_children(self, cb): @@ -404,8 +411,8 @@ class self_elt(data_elt): def got_resources(irdb_resources): try: for child_cert in child_certs: - ca_detail = child_cert.ca_detail() - ca = ca_detail.ca() + ca_detail = child_cert.ca_detail + ca = ca_detail.ca if ca_detail.state == "active": old_resources = child_cert.cert.get_3779resources() new_resources = irdb_resources.intersection(old_resources).intersection(ca_detail.latest_ca_cert.get_3779resources()) @@ -427,7 +434,7 @@ class self_elt(data_elt): rpki.log.debug("Child certificate SKI %s has expired: cert.valid_until %s, irdb.valid_until %s" % (child_cert.cert.gSKI(), old_resources.valid_until, irdb_resources.valid_until)) child_cert.sql_delete() - publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri(ca), obj = child_cert.cert, repository = ca.parent().repository()) + publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri, obj = child_cert.cert, repository = ca.parent.repository) ca_detail.generate_manifest(publisher = publisher) except (SystemExit, rpki.async.ExitNow): @@ -440,9 +447,9 @@ class self_elt(data_elt): iterator() self.gctx.checkpoint() - child_certs = child.child_certs() + child_certs = child.child_certs if child_certs: - self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, got_resources, lose) + self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, got_resources, lose) else: iterator() @@ -455,7 +462,7 @@ class self_elt(data_elt): self.gctx.checkpoint() publisher.call_pubd(cb, lose) - rpki.async.iterator(self.children(), loop, done) + rpki.async.iterator(self.children, loop, done) def regenerate_crls_and_manifests(self, cb): @@ -475,14 +482,14 @@ class self_elt(data_elt): regen_margin = rpki.sundial.timedelta(seconds = self.regen_margin) publisher = rpki.rpki_engine.publication_queue() - for parent in self.parents(): - for ca in parent.cas(): + for parent in self.parents: + for ca in parent.cas: try: for ca_detail in ca.fetch_revoked(): if now > ca_detail.latest_crl.getNextUpdate(): ca_detail.delete(ca = ca, publisher = publisher) ca_detail = ca.fetch_active() - if ca_detail is not None and now + regen_margin> ca_detail.latest_crl.getNextUpdate(): + if ca_detail is not None and now + regen_margin > ca_detail.latest_crl.getNextUpdate(): ca_detail.generate_crl(publisher = publisher) ca_detail.generate_manifest(publisher = publisher) except (SystemExit, rpki.async.ExitNow): @@ -501,6 +508,90 @@ class self_elt(data_elt): publisher.call_pubd(cb, lose) + def update_ghostbusters(self, cb): + """ + Generate or update Ghostbusters records for this self. + + This is heavily based on .update_roas(), and probably both of them + need refactoring. + """ + + raise rpki.exceptions.NotImplementedYet + + parents = dict((p.parent_handle, p) for p in self.parents) + + def got_gbr_requests(gbr_requests): + + self.gctx.checkpoint() + + if self.gctx.sql.dirty: + rpki.log.warn("Unexpected dirty SQL cache, flushing") + self.gctx.sql.sweep() + + ghostbusters = {} + orphans = [] + for ghostbuster in self.ghostbusters: + k = (ghostbuster.ca_detail.ca.parent.parent_handle, ghostbuster.vcard) + if k not in ghostbusters: + ghostbusters[k] = ghostbuster + elif ghostbuster.ca_detail.state == "active" and ghostbusters[k].ca_detail.state != "active": + orphans.append(ghostbusters[k]) + ghostbusters[k] = ghostbuster + else: + orphans.append(ghostbusters[k]) + + publisher = rpki.rpki_engine.publication_queue() + ca_details = set() + + seen = set() + for gbr_request in gbr_requests: + if gbr_request.parent_handle not in parents: + rpki.log.warn("Unknown parent_handle %r in Ghostbuster request, skipping" % gbr_request.parent_handle) + continue + k = (gbr_request.parent_handle, gbr_request.vcard) + if k in seen: + rpki.log.warn("Skipping duplicate Ghostbuster request %r" % gbr_request) + continue + see.add(k) + ghostbuster = ghostbusters.pop(k, None) + if ghostbuster is None: + ghostbuster = rpki.rpki_engine.ghostbuster_obj(self.gctx, self.self_id, parents[gbr_request.parent_handle], vcard) + rpki.log.debug("Created new Ghostbuster request for %r" % gbr_request.parent_handle) + else: + rpki.log.debug("Found existing Ghostbuster request for %r" % gbr_request.parent_handle) + ghostbuster.update(publisher = publisher, fast = True) + ca_details.add(ghostbuster.ca_detail) + + orphans.extend(ghostbusters.itervalues()) + for ghostbuster in orphans: + ca_details.add(ghostbuster.ca_detail) + ghostbuster.revoke(publisher = publisher, fast = True) + + for ca_detail in ca_details: + ca_detail.generate_crl(publisher = publisher) + ca_detail.generate_manifest(publisher = publisher) + + self.gctx.sql.sweep() + + def publication_failed(e): + rpki.log.traceback() + rpki.log.warn("Couldn't publish Ghostbuster updates for %s, skipping: %s" % (self.self_handle, e)) + self.gctx.checkpoint() + cb() + + self.gctx.checkpoint() + publisher.call_pubd(cb, publication_failed) + + def gbr_requests_failed(e): + rpki.log.traceback() + rpki.log.warn("Could not fetch Ghostbusters record requests for %s, skipping: %s" % (self.self_handle, e)) + cb() + + self.gctx.checkpoint() + self.gctx.irdb_query_gbr_requests(self.self_handle, parents.iterkeys(), + got_gbr_requests, gbr_requests_failed) + + def update_roas(self, cb): """ Generate or update ROAs for this self. @@ -516,12 +607,12 @@ class self_elt(data_elt): roas = {} orphans = [] - for roa in self.roas(): + for roa in self.roas: k = (roa.asn, str(roa.ipv4), str(roa.ipv6)) if k not in roas: roas[k] = roa - elif (roa.roa is not None and roa.cert is not None and roa.ca_detail() is not None and roa.ca_detail().state == "active" and - (roas[k].roa is None or roas[k].cert is None or roas[k].ca_detail() is None or roas[k].ca_detail().state != "active")): + elif (roa.roa is not None and roa.cert is not None and roa.ca_detail is not None and roa.ca_detail.state == "active" and + (roas[k].roa is None or roas[k].cert is None or roas[k].ca_detail is None or roas[k].ca_detail.state != "active")): orphans.append(roas[k]) roas[k] = roa else: @@ -545,7 +636,7 @@ class self_elt(data_elt): else: rpki.log.debug("Found existing ROA %r matching %r" % (roa, k)) roa.update(publisher = publisher, fast = True) - ca_details.add(roa.ca_detail()) + ca_details.add(roa.ca_detail) except (SystemExit, rpki.async.ExitNow): raise except Exception, e: @@ -556,7 +647,7 @@ class self_elt(data_elt): orphans.extend(roas.itervalues()) for roa in orphans: try: - ca_details.add(roa.ca_detail()) + ca_details.add(roa.ca_detail) roa.revoke(publisher = publisher, fast = True) except (SystemExit, rpki.async.ExitNow): raise @@ -610,18 +701,21 @@ class bsc_elt(data_elt): signing_cert = None signing_cert_crl = None + @property def repositories(self): """ Fetch all repository objects that link to this BSC object. """ return repository_elt.sql_fetch_where(self.gctx, "bsc_id = %s", (self.bsc_id,)) + @property def parents(self): """ Fetch all parent objects that link to this BSC object. """ return parent_elt.sql_fetch_where(self.gctx, "bsc_id = %s", (self.bsc_id,)) + @property def children(self): """ Fetch all child objects that link to this BSC object. @@ -660,6 +754,7 @@ class repository_elt(data_elt): bpki_cert = None bpki_glue = None + @property def parents(self): """ Fetch all parent objects that link to this repository object. @@ -701,9 +796,9 @@ class repository_elt(data_elt): for q_pdu in q_msg: rpki.log.info("Sending <%s %r %r> to pubd" % (q_pdu.action, q_pdu.uri, q_pdu.payload)) - bsc = self.bsc() + bsc = self.bsc q_der = rpki.publication.cms_msg().wrap(q_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl) - bpki_ta_path = (self.gctx.bpki_ta, self.self().bpki_cert, self.self().bpki_glue, self.bpki_cert, self.bpki_glue) + bpki_ta_path = (self.gctx.bpki_ta, self.self.bpki_cert, self.self.bpki_glue, self.bpki_cert, self.bpki_glue) def done(r_der): try: @@ -755,12 +850,14 @@ class parent_elt(data_elt): bpki_cms_cert = None bpki_cms_glue = None + @property def repository(self): """ Fetch repository object to which this parent object links. """ return repository_elt.sql_fetch(self.gctx, self.repository_id) + @property def cas(self): """ Fetch all CA objects that link to this parent object. @@ -790,7 +887,7 @@ class parent_elt(data_elt): """ def loop(iterator, ca): ca.rekey(iterator, eb) - rpki.async.iterator(self.cas(), loop, cb) + rpki.async.iterator(self.cas, loop, cb) def serve_revoke(self, cb, eb): """ @@ -798,7 +895,7 @@ class parent_elt(data_elt): """ def loop(iterator, ca): ca.revoke(cb = iterator, eb = eb) - rpki.async.iterator(self.cas(), loop, cb) + rpki.async.iterator(self.cas, loop, cb) def serve_reissue(self, cb, eb): """ @@ -806,7 +903,7 @@ class parent_elt(data_elt): """ def loop(iterator, ca): ca.reissue(cb = iterator, eb = eb) - rpki.async.iterator(self.cas(), loop, cb) + rpki.async.iterator(self.cas, loop, cb) def serve_revoke_forgotten(self, cb, eb): """ @@ -824,7 +921,7 @@ class parent_elt(data_elt): def got_list(r_msg): - ca_map = dict((ca.parent_resource_class, ca) for ca in self.cas()) + ca_map = dict((ca.parent_resource_class, ca) for ca in self.cas) def rc_loop(rc_iterator, rc): @@ -855,7 +952,7 @@ class parent_elt(data_elt): rpki.log.trace() - bsc = self.bsc() + bsc = self.bsc if bsc is None: raise rpki.exceptions.BSCNotFound, "Could not find BSC %s" % self.bsc_id @@ -874,8 +971,8 @@ class parent_elt(data_elt): def unwrap(r_der): try: r_msg = rpki.up_down.cms_msg(DER = r_der).unwrap((self.gctx.bpki_ta, - self.self().bpki_cert, - self.self().bpki_glue, + self.self.bpki_cert, + self.self.bpki_glue, self.bpki_cms_cert, self.bpki_cms_glue)) r_msg.payload.check_response() @@ -913,12 +1010,20 @@ class child_elt(data_elt): bpki_cert = None bpki_glue = None - def child_certs(self, ca_detail = None, ski = None, unique = False): + def fetch_child_certs(self, ca_detail = None, ski = None, unique = False): """ Fetch all child_cert objects that link to this child object. """ return rpki.rpki_engine.child_cert_obj.fetch(self.gctx, self, ca_detail, ski, unique) + @property + def child_certs(self): + """ + Fetch all child_cert objects that link to this child object. + """ + return self.fetch_child_certs() + + @property def parents(self): """ Fetch all parent objects that link to self object to which this child object links. @@ -939,8 +1044,8 @@ class child_elt(data_elt): Handle a left-right reissue action for this child. """ publisher = rpki.rpki_engine.publication_queue() - for child_cert in self.child_certs(): - child_cert.reissue(child_cert.ca_detail(), publisher, force = True) + for child_cert in self.child_certs: + child_cert.reissue(child_cert.ca_detail, publisher, force = True) publisher.call_pubd(cb, eb) def ca_from_class_name(self, class_name): @@ -952,7 +1057,7 @@ class child_elt(data_elt): ca = rpki.rpki_engine.ca_obj.sql_fetch(self.gctx, long(class_name)) if ca is None: raise rpki.exceptions.ClassNameUnknown, "Unknown class name %s" % class_name - parent = ca.parent() + parent = ca.parent if self.self_id != parent.self_id: raise rpki.exceptions.ClassNameMismatch, "Class name mismatch: child.self_id = %d, parent.self_id = %d" % (self.self_id, parent.self_id) return ca @@ -962,7 +1067,7 @@ class child_elt(data_elt): Extra server actions when destroying a child_elt. """ publisher = rpki.rpki_engine.publication_queue() - for child_cert in self.child_certs(): + for child_cert in self.child_certs: child_cert.revoke(publisher = publisher, generate_crl_and_manifest = True) publisher.call_pubd(cb, eb) @@ -974,12 +1079,12 @@ class child_elt(data_elt): rpki.log.trace() - bsc = self.bsc() + bsc = self.bsc if bsc is None: raise rpki.exceptions.BSCNotFound, "Could not find BSC %s" % self.bsc_id q_msg = rpki.up_down.cms_msg(DER = query).unwrap((self.gctx.bpki_ta, - self.self().bpki_cert, - self.self().bpki_glue, + self.self.bpki_cert, + self.self.bpki_glue, self.bpki_cert, self.bpki_glue)) q_msg.payload.gctx = self.gctx @@ -1061,6 +1166,18 @@ class list_roa_requests_elt(rpki.xml_utils.base_elt, left_right_namespace): if self.ipv6 is not None: self.ipv6 = rpki.resource_set.roa_prefix_set_ipv6(self.ipv6) +class list_gbr_requests_elt(rpki.xml_utils.text_elt, left_right_namespace): + """ + <list_gbr_requests/> element. + """ + + element_name = "list_gbr_requests" + attributes = ("self_handle", "tag", "parent_handle") + text_attribute = "vcard" + + vcard = None + + class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace): """ <list_published_objects/> element. @@ -1078,14 +1195,14 @@ class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace): misnomer here, there's no action attribute and no dispatch, we just dump every published object for the specified <self/> and return. """ - for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents(): - for ca in parent.cas(): + for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents: + for ca in parent.cas: ca_detail = ca.fetch_active() if ca_detail is not None: - r_msg.append(self.make_reply(ca_detail.crl_uri(ca), ca_detail.latest_crl)) - r_msg.append(self.make_reply(ca_detail.manifest_uri(ca), ca_detail.latest_manifest)) - r_msg.extend(self.make_reply(c.uri(ca), c.cert) for c in ca_detail.child_certs()) - r_msg.extend(self.make_reply(r.uri(), r.roa) for r in ca_detail.roas() if r.roa is not None) + r_msg.append(self.make_reply(ca_detail.crl_uri, ca_detail.latest_crl)) + r_msg.append(self.make_reply(ca_detail.manifest_uri, ca_detail.latest_manifest)) + r_msg.extend(self.make_reply(c.uri, c.cert) for c in ca_detail.child_certs) + r_msg.extend(self.make_reply(r.uri, r.roa) for r in ca_detail.roas if r.roa is not None) cb() def make_reply(self, uri, obj): @@ -1112,8 +1229,8 @@ class list_received_resources_elt(rpki.xml_utils.base_elt, left_right_namespace) just dump a bunch of data about every certificate issued to us by one of our parents, then return. """ - for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents(): - for ca in parent.cas(): + for parent in self_elt.serve_fetch_handle(self.gctx, None, self.self_handle).parents: + for ca in parent.cas: ca_detail = ca.fetch_active() if ca_detail is not None and ca_detail.latest_ca_cert is not None: r_msg.append(self.make_reply(parent.parent_handle, ca_detail.ca_cert_uri, ca_detail.latest_ca_cert)) @@ -1172,10 +1289,11 @@ class msg(rpki.xml_utils.msg, left_right_namespace): ## @var pdus # Dispatch table of PDUs for this protocol. pdus = dict((x.element_name, x) - for x in (self_elt, child_elt, parent_elt, bsc_elt, repository_elt, - list_resources_elt, list_roa_requests_elt, - list_published_objects_elt, list_received_resources_elt, - report_error_elt)) + for x in (self_elt, child_elt, parent_elt, bsc_elt, + repository_elt, list_resources_elt, + list_roa_requests_elt, list_gbr_requests_elt, + list_published_objects_elt, + list_received_resources_elt, report_error_elt)) def serve_top_level(self, gctx, cb): """ diff --git a/rpkid/rpki/oids.py b/rpkid/rpki/oids.py index 90e486b7..2b1ffdd9 100644 --- a/rpkid/rpki/oids.py +++ b/rpkid/rpki/oids.py @@ -3,7 +3,22 @@ OID database. $Id$ -Copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") +Copyright (C) 2009--2011 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 @@ -31,6 +46,7 @@ oid2name = { (1, 2, 840, 113549, 1, 9, 16, 1, 24) : "id-ct-routeOriginAttestation", (1, 2, 840, 113549, 1, 9, 16, 1, 26) : "id-ct-rpkiManifest", (1, 2, 840, 113549, 1, 9, 16, 1, 28) : "id-ct-xml", + (1, 2, 840, 113549, 1, 9, 16, 1, 35) : "id-ct-rpkiGhostbusters", (1, 3, 6, 1, 5, 5, 7, 1, 1) : "authorityInfoAccess", (1, 3, 6, 1, 5, 5, 7, 1, 11) : "subjectInfoAccess", (1, 3, 6, 1, 5, 5, 7, 1, 7) : "sbgp-ipAddrBlock", diff --git a/rpkid/rpki/publication.py b/rpkid/rpki/publication.py index 1f5ed812..4c6df14b 100644 --- a/rpkid/rpki/publication.py +++ b/rpkid/rpki/publication.py @@ -3,7 +3,7 @@ RPKI "publication" protocol. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -import base64, os, errno +import os, errno import rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.xml_utils import rpki.http, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa diff --git a/rpkid/rpki/relaxng.py b/rpkid/rpki/relaxng.py index d42b213a..3e6de5f6 100644 --- a/rpkid/rpki/relaxng.py +++ b/rpkid/rpki/relaxng.py @@ -13,7 +13,7 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc libxml2 (including xmllint) only groks the XML syntax of RelaxNG, so run the compact syntax through trang to get XML syntax. - Copyright (C) 2009-2010 Internet Systems Consortium ("ISC") + Copyright (C) 2009-2011 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 @@ -90,6 +90,9 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <ref name="list_roa_requests_query"/> </define> <define name="query_elt" combine="choice"> + <ref name="list_gbr_requests_query"/> + </define> + <define name="query_elt" combine="choice"> <ref name="list_resources_query"/> </define> <define name="query_elt" combine="choice"> @@ -121,6 +124,9 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc <ref name="list_roa_requests_reply"/> </define> <define name="reply_elt" combine="choice"> + <ref name="list_gbr_requests_reply"/> + </define> + <define name="reply_elt" combine="choice"> <ref name="list_published_objects_reply"/> </define> <define name="reply_elt" combine="choice"> @@ -889,6 +895,22 @@ left_right = lxml.etree.RelaxNG(lxml.etree.fromstring('''<?xml version="1.0" enc </optional> </element> </define> + <!-- <list_gbr_requests/> element --> + <define name="list_gbr_requests_query"> + <element name="list_gbr_requests"> + <ref name="tag"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> + </element> + </define> + <define name="list_gbr_requests_reply"> + <element name="list_gbr_requests"> + <ref name="tag"/> + <ref name="self_handle"/> + <ref name="parent_handle"/> + <data type="string"/> + </element> + </define> <!-- <list_published_objects/> element --> <define name="list_published_objects_query"> <element name="list_published_objects"> diff --git a/rpkid/rpki/rpki_engine.py b/rpkid/rpki/rpki_engine.py index d7ff9c5e..4a70ca0e 100644 --- a/rpkid/rpki/rpki_engine.py +++ b/rpkid/rpki/rpki_engine.py @@ -3,7 +3,7 @@ Global context for rpkid. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -83,25 +83,30 @@ class rpkid_context(object): else: rpki.log.debug("Not using internal clock, start_cron() call ignored") - def irdb_query(self, q_pdu, callback, errback, expected_pdu_count = None): + def irdb_query(self, callback, errback, *q_pdus, **kwargs): """ Perform an IRDB callback query. """ rpki.log.trace() + q_types = tuple(type(q_pdu) for q_pdu in q_pdus) + + expected_pdu_count = kwargs.pop("expected_pdu_count", None) + assert len(kwargs) == 0 + q_msg = rpki.left_right.msg.query() - q_msg.append(q_pdu) + q_msg.extend(q_pdus) q_der = rpki.left_right.cms_msg().wrap(q_msg, self.rpkid_key, self.rpkid_cert) def unwrap(r_der): r_cms = rpki.left_right.cms_msg(DER = r_der) r_msg = r_cms.unwrap((self.bpki_ta, self.irdb_cert)) - if not r_msg.is_reply() or not all(type(r_pdu) is type(q_pdu) for r_pdu in r_msg): + if not r_msg.is_reply() or not all(type(r_pdu) in q_types for r_pdu in r_msg): raise rpki.exceptions.BadIRDBReply, "Unexpected response to IRDB query: %s" % r_cms.pretty_print_content() if expected_pdu_count is not None and len(r_msg) != expected_pdu_count: assert isinstance(expected_pdu_count, (int, long)) - raise rpki.exceptions.BadIRDBReply, "Expected exactly %d PDU%s from IRDB: %s" ( + raise rpki.exceptions.BadIRDBReply, "Expected exactly %d PDU%s from IRDB: %s" % ( expected_pdu_count, "" if expected_pdu_count == 1 else "s", r_cms.pretty_print_content()) callback(r_msg) @@ -129,7 +134,7 @@ class rpkid_context(object): v6 = r_msg[0].ipv6, valid_until = r_msg[0].valid_until)) - self.irdb_query(q_pdu, done, errback, expected_pdu_count = 1) + self.irdb_query(done, errback, q_pdu, expected_pdu_count = 1) def irdb_query_roa_requests(self, self_handle, callback, errback): """ @@ -141,7 +146,24 @@ class rpkid_context(object): q_pdu = rpki.left_right.list_roa_requests_elt() q_pdu.self_handle = self_handle - self.irdb_query(q_pdu, callback, errback) + self.irdb_query(callback, errback, q_pdu) + + def irdb_query_gbr_requests(self, self_handle, parent_handles, callback, errback): + """ + Ask IRDB about self's ghostbuster record requests. + """ + + rpki.log.trace() + + q_pdus = [] + + for parent_handle in parent_handles: + q_pdu = rpki.left_right.list_gbr_requests_elt() + q_pdu.self_handle = self_handle + q_pdu.parent_handle = parent_handle + q_pdus.append(q_pdu) + + self.irdb_query(callback, errback, *q_pdus) def left_right_handler(self, query, path, cb): """ @@ -290,12 +312,14 @@ class ca_obj(rpki.sql.sql_persistent): last_issued_sn = 0 last_manifest_sn = 0 + @property def parent(self): """ Fetch parent object to which this CA object links. """ return rpki.left_right.parent_elt.sql_fetch(self.gctx, self.parent_id) + @property def ca_details(self): """ Fetch all ca_detail objects that link to this CA object. @@ -375,7 +399,7 @@ class ca_obj(rpki.sql.sql_persistent): rpki.log.warn("Certificate in database missing from list_response, class %r, SKI %s, maybe parent certificate went away?" % (rc.class_name, ca_detail.public_key.gSKI())) publisher = publication_queue() - ca_detail.delete(ca = ca_detail.ca(), publisher = publisher) + ca_detail.delete(ca = ca_detail.ca, publisher = publisher) return publisher.call_pubd(iterator, eb) else: @@ -473,7 +497,7 @@ class ca_obj(rpki.sql.sql_persistent): callback() publisher = publication_queue() - for ca_detail in self.ca_details(): + for ca_detail in self.ca_details: ca_detail.delete(ca = self, publisher = publisher) publisher.call_pubd(done, lose) @@ -511,7 +535,7 @@ class ca_obj(rpki.sql.sql_persistent): rpki.log.trace() - parent = self.parent() + parent = self.parent old_detail = self.fetch_active() new_detail = ca_detail_obj.create(self) @@ -583,47 +607,60 @@ class ca_detail_obj(rpki.sql.sql_persistent): assert self.public_key is None or self.private_key_id is None or self.public_key.get_DER() == self.private_key_id.get_public_DER() assert self.manifest_public_key is None or self.manifest_private_key_id is None or self.manifest_public_key.get_DER() == self.manifest_private_key_id.get_public_DER() + @property def ca(self): """ Fetch CA object to which this ca_detail links. """ return ca_obj.sql_fetch(self.gctx, self.ca_id) - def child_certs(self, child = None, ski = None, unique = False): + def fetch_child_certs(self, child = None, ski = None, unique = False): """ Fetch all child_cert objects that link to this ca_detail. """ return rpki.rpki_engine.child_cert_obj.fetch(self.gctx, child, self, ski, unique) + @property + def child_certs(self): + """ + Fetch all child_cert objects that link to this ca_detail. + """ + return self.fetch_child_certs() + + @property def revoked_certs(self): """ Fetch all revoked_cert objects that link to this ca_detail. """ return revoked_cert_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,)) + @property def roas(self): """ Fetch all ROA objects that link to this ca_detail. """ return rpki.rpki_engine.roa_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,)) - def crl_uri(self, ca): + @property + def crl_uri(self): """ Return publication URI for this ca_detail's CRL. """ - return ca.sia_uri + self.crl_uri_tail() + return self.ca.sia_uri + self.crl_uri_tail + @property def crl_uri_tail(self): """ Return tail (filename portion) of publication URI for this ca_detail's CRL. """ return self.public_key.gSKI() + ".crl" - def manifest_uri(self, ca): + @property + def manifest_uri(self): """ Return publication URI for this ca_detail's manifest. """ - return ca.sia_uri + self.public_key.gSKI() + ".mnf" + return self.ca.sia_uri + self.public_key.gSKI() + ".mnf" def activate(self, ca, cert, uri, callback, errback, predecessor = None): """ @@ -634,7 +671,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.latest_ca_cert = cert self.ca_cert_uri = uri.rsync() - self.generate_manifest_cert(ca) + self.generate_manifest_cert() self.state = "active" self.generate_crl(publisher = publisher) self.generate_manifest(publisher = publisher) @@ -643,9 +680,9 @@ class ca_detail_obj(rpki.sql.sql_persistent): if predecessor is not None: predecessor.state = "deprecated" predecessor.sql_mark_dirty() - for child_cert in predecessor.child_certs(): + for child_cert in predecessor.child_certs: child_cert.reissue(ca_detail = self, publisher = publisher) - for roa in predecessor.roas(): + for roa in predecessor.roas: roa.regenerate(publisher = publisher) publisher.call_pubd(callback, errback) @@ -658,27 +695,27 @@ class ca_detail_obj(rpki.sql.sql_persistent): raise an exception. """ - repository = ca.parent().repository() - for child_cert in self.child_certs(): - publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri(ca), obj = child_cert.cert, repository = repository, + repository = ca.parent.repository + for child_cert in self.child_certs: + publisher.withdraw(cls = rpki.publication.certificate_elt, uri = child_cert.uri, obj = child_cert.cert, repository = repository, handler = False if allow_failure else None) - for roa in self.roas(): + for roa in self.roas: roa.revoke(publisher = publisher, allow_failure = allow_failure) try: latest_manifest = self.latest_manifest except AttributeError: latest_manifest = None if latest_manifest is not None: - publisher.withdraw(cls = rpki.publication.manifest_elt, uri = self.manifest_uri(ca), obj = self.latest_manifest, repository = repository, + publisher.withdraw(cls = rpki.publication.manifest_elt, uri = self.manifest_uri, obj = self.latest_manifest, repository = repository, handler = False if allow_failure else None) try: latest_crl = self.latest_crl except AttributeError: latest_crl = None if latest_crl is not None: - publisher.withdraw(cls = rpki.publication.crl_elt, uri = self.crl_uri(ca), obj = self.latest_crl, repository = repository, + publisher.withdraw(cls = rpki.publication.crl_elt, uri = self.crl_uri, obj = self.latest_crl, repository = repository, handler = False if allow_failure else None) - for cert in self.child_certs() + self.revoked_certs(): + for cert in self.child_certs + self.revoked_certs: cert.sql_delete() self.sql_delete() @@ -705,15 +742,15 @@ class ca_detail_obj(rpki.sql.sql_persistent): time has passed. """ - ca = self.ca() - parent = ca.parent() + ca = self.ca + parent = ca.parent def parent_revoked(r_msg): if r_msg.payload.ski != self.latest_ca_cert.gSKI(): raise rpki.exceptions.SKIMismatch - crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval) + crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval) nextUpdate = rpki.sundial.now() @@ -729,7 +766,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): publisher = publication_queue() - for child_cert in self.child_certs(): + for child_cert in self.child_certs: nextUpdate = nextUpdate.later(child_cert.cert.getNotAfter()) child_cert.revoke(publisher = publisher) @@ -758,7 +795,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): publisher = publication_queue() if sia_uri_changed or old_resources.oversized(new_resources): - for child_cert in self.child_certs(): + for child_cert in self.child_certs: child_resources = child_cert.cert.get_3779resources() if sia_uri_changed or child_resources.oversized(new_resources): child_cert.reissue( @@ -800,19 +837,19 @@ class ca_detail_obj(rpki.sql.sql_persistent): serial = ca.next_serial_number(), sia = sia, aia = self.ca_cert_uri, - crldp = self.crl_uri(ca), + crldp = self.crl_uri, resources = resources, notAfter = self.latest_ca_cert.getNotAfter(), is_ca = False) - def generate_manifest_cert(self, ca): + def generate_manifest_cert(self): """ Generate a new manifest certificate for this ca_detail. """ resources = rpki.resource_set.resource_bag.from_inheritance() - self.latest_manifest_cert = self.issue_ee(ca, resources, self.manifest_public_key) + self.latest_manifest_cert = self.issue_ee(self.ca, resources, self.manifest_public_key) def issue(self, ca, child, subject_key, sia, resources, publisher, child_cert = None): """ @@ -830,7 +867,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): subject_key = subject_key, serial = ca.next_serial_number(), aia = self.ca_cert_uri, - crldp = self.crl_uri(ca), + crldp = self.crl_uri, sia = sia, resources = resources, notAfter = resources.valid_until) @@ -851,9 +888,9 @@ class ca_detail_obj(rpki.sql.sql_persistent): child_cert.sql_store() publisher.publish( cls = rpki.publication.certificate_elt, - uri = child_cert.uri(ca), + uri = child_cert.uri, obj = child_cert.cert, - repository = ca.parent().repository(), + repository = ca.parent.repository, handler = child_cert.published_callback) self.generate_manifest(publisher = publisher) return child_cert @@ -865,16 +902,16 @@ class ca_detail_obj(rpki.sql.sql_persistent): new CRL is needed. """ - ca = self.ca() - parent = ca.parent() - crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval) + ca = self.ca + parent = ca.parent + crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval) now = rpki.sundial.now() if nextUpdate is None: nextUpdate = now + crl_interval certlist = [] - for revoked_cert in self.revoked_certs(): + for revoked_cert in self.revoked_certs: if now > revoked_cert.expires + crl_interval: revoked_cert.sql_delete() else: @@ -891,7 +928,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.crl_published = rpki.sundial.now() self.sql_mark_dirty() - publisher.publish(cls = rpki.publication.crl_elt, uri = self.crl_uri(ca), obj = self.latest_crl, repository = parent.repository(), + publisher.publish(cls = rpki.publication.crl_elt, uri = self.crl_uri, obj = self.latest_crl, repository = parent.repository, handler = self.crl_published_callback) def crl_published_callback(self, pdu): @@ -907,20 +944,20 @@ class ca_detail_obj(rpki.sql.sql_persistent): Generate a new manifest for this ca_detail. """ - ca = self.ca() - parent = ca.parent() - crl_interval = rpki.sundial.timedelta(seconds = parent.self().crl_interval) + ca = self.ca + parent = ca.parent + crl_interval = rpki.sundial.timedelta(seconds = parent.self.crl_interval) now = rpki.sundial.now() if nextUpdate is None: nextUpdate = now + crl_interval if self.latest_manifest_cert is None or self.latest_manifest_cert.getNotAfter() < nextUpdate: - self.generate_manifest_cert(ca) + self.generate_manifest_cert() - objs = [(self.crl_uri_tail(), self.latest_crl)] - objs.extend((c.uri_tail(), c.cert) for c in self.child_certs()) - objs.extend((r.uri_tail(), r.roa) for r in self.roas() if r.roa is not None) + objs = [(self.crl_uri_tail, self.latest_crl)] + objs.extend((c.uri_tail, c.cert) for c in self.child_certs) + objs.extend((r.uri_tail, r.roa) for r in self.roas if r.roa is not None) self.latest_manifest = rpki.x509.SignedManifest.build( serial = ca.next_manifest_number(), @@ -933,7 +970,7 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.manifest_published = rpki.sundial.now() self.sql_mark_dirty() - publisher.publish(cls = rpki.publication.manifest_elt, uri = self.manifest_uri(ca), obj = self.latest_manifest, repository = parent.repository(), + publisher.publish(cls = rpki.publication.manifest_elt, uri = self.manifest_uri, obj = self.latest_manifest, repository = parent.repository, handler = self.manifest_published_callback) def manifest_published_callback(self, pdu): @@ -950,9 +987,9 @@ class ca_detail_obj(rpki.sql.sql_persistent): """ publisher = publication_queue() - for roa in self.roas(): + for roa in self.roas: roa.regenerate(publisher, fast = True) - for child_cert in self.child_certs(): + for child_cert in self.child_certs: child_cert.reissue(self, publisher, force = True) publisher.call_pubd(cb, eb) @@ -983,40 +1020,44 @@ class child_cert_obj(rpki.sql.sql_persistent): if child_id or ca_detail_id or cert: self.sql_mark_dirty() + @property def child(self): """ Fetch child object to which this child_cert object links. """ return rpki.left_right.child_elt.sql_fetch(self.gctx, self.child_id) + @property def ca_detail(self): """ Fetch ca_detail object to which this child_cert object links. """ return ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id) + @property def uri_tail(self): """ Return the tail (filename) portion of the URI for this child_cert. """ return self.cert.gSKI() + ".cer" - def uri(self, ca): + @property + def uri(self): """ Return the publication URI for this child_cert. """ - return ca.sia_uri + self.uri_tail() + return self.ca_detail.ca.sia_uri + self.uri_tail def revoke(self, publisher, generate_crl_and_manifest = False): """ Revoke a child cert. """ - ca_detail = self.ca_detail() - ca = ca_detail.ca() - rpki.log.debug("Revoking %r %r" % (self, self.uri(ca))) + ca_detail = self.ca_detail + ca = ca_detail.ca + rpki.log.debug("Revoking %r %r" % (self, self.uri)) revoked_cert_obj.revoke(cert = self.cert, ca_detail = ca_detail) - publisher.withdraw(cls = rpki.publication.certificate_elt, uri = self.uri(ca), obj = self.cert, repository = ca.parent().repository()) + publisher.withdraw(cls = rpki.publication.certificate_elt, uri = self.uri, obj = self.cert, repository = ca.parent.repository) self.gctx.sql.sweep() self.sql_delete() if generate_crl_and_manifest: @@ -1033,12 +1074,12 @@ class child_cert_obj(rpki.sql.sql_persistent): updated child_cert_obj must use the return value from this method. """ - ca = ca_detail.ca() - child = self.child() + ca = ca_detail.ca + child = self.child old_resources = self.cert.get_3779resources() old_sia = self.cert.get_SIA() - old_ca_detail = self.ca_detail() + old_ca_detail = self.ca_detail needed = False @@ -1085,7 +1126,7 @@ class child_cert_obj(rpki.sql.sql_persistent): return self if must_revoke: - for x in child.child_certs(ca_detail = ca_detail, ski = self.ski): + for x in child.fetch_child_certs(ca_detail = ca_detail, ski = self.ski): rpki.log.debug("Revoking child_cert %r" % x) x.revoke(publisher = publisher) ca_detail.generate_crl(publisher = publisher) @@ -1100,7 +1141,7 @@ class child_cert_obj(rpki.sql.sql_persistent): child_cert = None if must_revoke or new_issuer else self, publisher = publisher) - rpki.log.debug("New child_cert %r uri %s" % (child_cert, child_cert.uri(ca))) + rpki.log.debug("New child_cert %r uri %s" % (child_cert, child_cert.uri)) return child_cert @@ -1171,6 +1212,7 @@ class revoked_cert_obj(rpki.sql.sql_persistent): if serial or revoked or expires or ca_detail_id: self.sql_mark_dirty() + @property def ca_detail(self): """ Fetch ca_detail object to which this revoked_cert_obj links. @@ -1209,12 +1251,14 @@ class roa_obj(rpki.sql.sql_persistent): roa = None published = None + @property def self(self): """ Fetch self object to which this roa_obj links. """ return rpki.left_right.self_elt.sql_fetch(self.gctx, self.self_id) + @property def ca_detail(self): """ Fetch ca_detail object to which this roa_obj links. @@ -1282,7 +1326,7 @@ class roa_obj(rpki.sql.sql_persistent): rpki.log.debug("ROA doesn't exist, generating %s" % me) return self.generate(publisher = publisher, fast = fast) - ca_detail = self.ca_detail() + ca_detail = self.ca_detail if ca_detail is None: rpki.log.debug("ROA has no associated ca_detail, generating %s" % me) @@ -1292,7 +1336,7 @@ class roa_obj(rpki.sql.sql_persistent): rpki.log.debug("ROA's associated ca_detail not active (state %r), regenerating %s" % (ca_detail.state, me)) return self.regenerate(publisher = publisher, fast = fast) - regen_time = self.cert.getNotAfter() - rpki.sundial.timedelta(seconds = self.self().regen_margin) + regen_time = self.cert.getNotAfter() - rpki.sundial.timedelta(seconds = self.self.regen_margin) if rpki.sundial.now() > regen_time: rpki.log.debug("ROA past threshold %s, regenerating %s" % (regen_time, me)) @@ -1313,9 +1357,6 @@ class roa_obj(rpki.sql.sql_persistent): """ Generate a ROA. - At present this does not support ROAs with multiple signatures - (neither does the current CMS code). - At present we have no way of performing a direct lookup from a desired set of resources to a covering certificate, so we have to search. This could be quite slow if we have a lot of active @@ -1343,11 +1384,11 @@ class roa_obj(rpki.sql.sql_persistent): v4 = self.ipv4.to_resource_set() if self.ipv4 is not None else rpki.resource_set.resource_set_ipv4() v6 = self.ipv6.to_resource_set() if self.ipv6 is not None else rpki.resource_set.resource_set_ipv6() - ca_detail = self.ca_detail() + ca_detail = self.ca_detail if ca_detail is None or ca_detail.state != "active": ca_detail = None - for parent in self.self().parents(): - for ca in parent.cas(): + for parent in self.self.parents: + for ca in parent.cas: ca_detail = ca.fetch_active() if ca_detail is not None: resources = ca_detail.latest_ca_cert.get_3779resources() @@ -1360,7 +1401,7 @@ class roa_obj(rpki.sql.sql_persistent): if ca_detail is None: raise rpki.exceptions.NoCoveringCertForROA, "generate() could not find a certificate covering %s %s" % (v4, v6) - ca = ca_detail.ca() + ca = ca_detail.ca resources = rpki.resource_set.resource_bag(v4 = v4, v6 = v6) keypair = rpki.x509.RSA.generate() @@ -1369,13 +1410,13 @@ class roa_obj(rpki.sql.sql_persistent): ca = ca, resources = resources, subject_key = keypair.get_RSApublic(), - sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.uri(keypair))),)) + sia = ((rpki.oids.name2oid["id-ad-signedObject"], ("uri", self.uri_from_key(keypair))),)) self.roa = rpki.x509.ROA.build(self.asn, self.ipv4, self.ipv6, keypair, (self.cert,)) self.published = rpki.sundial.now() self.sql_store() - rpki.log.debug("Generating ROA %r" % self.uri()) - publisher.publish(cls = rpki.publication.roa_elt, uri = self.uri(), obj = self.roa, repository = ca.parent().repository(), handler = self.published_callback) + rpki.log.debug("Generating ROA %r" % self.uri) + publisher.publish(cls = rpki.publication.roa_elt, uri = self.uri, obj = self.roa, repository = ca.parent.repository, handler = self.published_callback) if not fast: ca_detail.generate_manifest(publisher = publisher) @@ -1403,10 +1444,10 @@ class roa_obj(rpki.sql.sql_persistent): flushing the SQL cache. """ - ca_detail = self.ca_detail() + ca_detail = self.ca_detail cert = self.cert roa = self.roa - uri = self.uri() + uri = self.uri if ca_detail.state != 'active': self.ca_detail_id = None @@ -1416,7 +1457,7 @@ class roa_obj(rpki.sql.sql_persistent): rpki.log.debug("Withdrawing ROA %r and revoking its EE cert" % uri) rpki.rpki_engine.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(), + 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 fast: @@ -1428,23 +1469,31 @@ class roa_obj(rpki.sql.sql_persistent): """ Reissue ROA associated with this roa_obj. """ - if self.ca_detail() is None: + if self.ca_detail is None: self.generate(publisher = publisher, fast = fast) else: self.revoke(publisher = publisher, regenerate = True, fast = fast) - def uri(self, key = None): + def uri_from_key(self, key): + """ + Return publication URI for a public key. + """ + return self.ca_detail.ca.sia_uri + key.gSKI() + ".roa" + + @property + def uri(self): """ Return the publication URI for this roa_obj's ROA. """ - return self.ca_detail().ca().sia_uri + self.uri_tail(key) + return self.ca_detail.ca.sia_uri + self.uri_tail - def uri_tail(self, key = None): + @property + def uri_tail(self): """ Return the tail (filename portion) of the publication URI for this roa_obj's ROA. """ - return (key or self.cert).gSKI() + ".roa" + return self.cert.gSKI() + ".roa" class publication_queue(object): diff --git a/rpkid/rpki/up_down.py b/rpkid/rpki/up_down.py index dcfa54bb..b8fc212b 100644 --- a/rpkid/rpki/up_down.py +++ b/rpkid/rpki/up_down.py @@ -3,7 +3,7 @@ RPKI "up-down" protocol. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -251,8 +251,8 @@ class list_pdu(base_elt): r_msg.payload = list_response_pdu() - for parent in child.parents(): - for ca in parent.cas(): + for parent in child.parents: + for ca in parent.cas: ca_detail = ca.fetch_active() if not ca_detail: continue @@ -263,16 +263,16 @@ class list_pdu(base_elt): rc.class_name = str(ca.ca_id) rc.cert_url = multi_uri(ca_detail.ca_cert_uri) rc.from_resource_bag(resources) - for child_cert in child.child_certs(ca_detail = ca_detail): + for child_cert in child.fetch_child_certs(ca_detail = ca_detail): c = certificate_elt() - c.cert_url = multi_uri(child_cert.uri(ca)) + c.cert_url = multi_uri(child_cert.uri) c.cert = child_cert.cert rc.certs.append(c) rc.issuer = ca_detail.latest_ca_cert r_msg.payload.classes.append(rc) callback() - self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, handle, errback) + self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, handle, errback) @classmethod def query(cls, parent, cb, eb): @@ -378,7 +378,7 @@ class issue_pdu(base_elt): resources = irdb_resources.intersection(ca_detail.latest_ca_cert.get_3779resources()) req_key = self.pkcs10.getPublicKey() req_sia = self.pkcs10.get_SIA() - child_cert = child.child_certs(ca_detail = ca_detail, ski = req_key.get_SKI(), unique = True) + child_cert = child.fetch_child_certs(ca_detail = ca_detail, ski = req_key.get_SKI(), unique = True) # Generate new cert or regenerate old one if necessary @@ -401,7 +401,7 @@ class issue_pdu(base_elt): def done(): c = certificate_elt() - c.cert_url = multi_uri(child_cert.uri(ca)) + c.cert_url = multi_uri(child_cert.uri) c.cert = child_cert.cert rc = class_elt() rc.class_name = self.class_name @@ -417,7 +417,7 @@ class issue_pdu(base_elt): assert child_cert and child_cert.sql_in_db publisher.call_pubd(done, errback) - self.gctx.irdb_query_child_resources(child.self().self_handle, child.child_handle, got_resources, errback) + self.gctx.irdb_query_child_resources(child.self.self_handle, child.child_handle, got_resources, errback) @classmethod def query(cls, parent, ca, ca_detail, callback, errback): @@ -426,7 +426,7 @@ class issue_pdu(base_elt): """ assert ca_detail is not None and ca_detail.state in ("pending", "active") sia = ((rpki.oids.name2oid["id-ad-caRepository"], ("uri", ca.sia_uri)), - (rpki.oids.name2oid["id-ad-rpkiManifest"], ("uri", ca_detail.manifest_uri(ca)))) + (rpki.oids.name2oid["id-ad-rpkiManifest"], ("uri", ca_detail.manifest_uri))) self = cls() self.class_name = ca.parent_resource_class self.pkcs10 = rpki.x509.PKCS10.create_ca(ca_detail.private_key_id, sia) @@ -484,8 +484,8 @@ class revoke_pdu(revoke_syntax): ca = child.ca_from_class_name(self.class_name) publisher = rpki.rpki_engine.publication_queue() - for ca_detail in ca.ca_details(): - for child_cert in child.child_certs(ca_detail = ca_detail, ski = self.get_SKI()): + for ca_detail in ca.ca_details: + for child_cert in child.fetch_child_certs(ca_detail = ca_detail, ski = self.get_SKI()): child_cert.revoke(publisher = publisher) self.gctx.sql.sweep() publisher.call_pubd(done, eb) @@ -495,7 +495,7 @@ class revoke_pdu(revoke_syntax): """ Send a "revoke" request for certificate(s) named by gski to parent associated with ca. """ - parent = ca.parent() + parent = ca.parent self = cls() self.class_name = ca.parent_resource_class self.ski = gski diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py index ebf8e089..7fda419d 100644 --- a/rpkid/rpki/x509.py +++ b/rpkid/rpki/x509.py @@ -13,7 +13,7 @@ some of the nasty details. This involves a lot of format conversion. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -1218,6 +1218,39 @@ class XML_CMS_object(CMS_object): self.schema_check() return self.saxify(self.get_content()) +class GBR_object(CMS_object): + """ + Class to hold CMS-wrapped VCard (Ghostbuster record). + """ + + pem_converter = PEM_converter("GHOSTBUSTERS RECORD") + econtent_oid = POWify_OID("id-ct-rpkiGhostbusters") + + def encode(self): + """ + Encode inner content for signing. At the moment we're treating + the VCard as an opaque byte string, so no encoding needed here. + """ + return self.get_content() + + def decode(self, vcard): + """ + Decode XML and set inner content. At the moment we're treating + the VCard as an opaque byte string, so no encoding needed here. + """ + self.content = vcard + + @classmethod + def build(cls, vcard, keypair, certs): + """ + Build a Ghostbusters record. + """ + self = cls() + self.set_content(vcard) + self.sign(keypair, certs) + return self + + class CRL(DER_object): """ Class to hold a Certificate Revocation List. diff --git a/rpkid/rpki/xml_utils.py b/rpkid/rpki/xml_utils.py index 7b8297a4..27c1f1e6 100644 --- a/rpkid/rpki/xml_utils.py +++ b/rpkid/rpki/xml_utils.py @@ -3,7 +3,7 @@ XML utilities. $Id$ -Copyright (C) 2009 Internet Systems Consortium ("ISC") +Copyright (C) 2009-2011 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 @@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -import xml.sax, lxml.sax, lxml.etree, base64 +import xml.sax, lxml.sax, lxml.etree import rpki.exceptions class sax_handler(xml.sax.handler.ContentHandler): diff --git a/rpkid/rpkid.sql b/rpkid/rpkid.sql index 2bf868b5..2813c1dc 100644 --- a/rpkid/rpkid.sql +++ b/rpkid/rpkid.sql @@ -1,6 +1,6 @@ -- $Id$ --- Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +-- Copyright (C) 2009--2011 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 @@ -33,6 +33,7 @@ -- DROP TABLE commands must be in correct (reverse dependency) order -- to satisfy FOREIGN KEY constraints. +DROP TABLE IF EXISTS ghostbuster; DROP TABLE IF EXISTS roa_prefix; DROP TABLE IF EXISTS roa; DROP TABLE IF EXISTS revoked_cert; @@ -214,6 +215,21 @@ CREATE TABLE roa_prefix ( FOREIGN KEY (roa_id) REFERENCES roa (roa_id) ON DELETE CASCADE ) ENGINE=InnoDB; +CREATE TABLE ghostbuster ( + ghostbuster_id SERIAL NOT NULL, + vcard LONGBLOB NOT NULL, + cert LONGBLOB NOT NULL, + gbr LONGBLOB NOT NULL, + published DATETIME, + self_id BIGINT UNSIGNED NOT NULL, + ca_detail_id BIGINT UNSIGNED NOT NULL, + PRIMARY KEY (ghostbuster_id), + CONSTRAINT ghostbuster_self_id + FOREIGN KEY (self_id) REFERENCES self (self_id) ON DELETE CASCADE, + CONSTRAINT ghostbuster_ca_detail_id + FOREIGN KEY (ca_detail_id) REFERENCES ca_detail (ca_detail_id) ON DELETE CASCADE +) ENGINE=InnoDB; + -- Local Variables: -- indent-tabs-mode: nil -- End: diff --git a/rpkid/tests/smoketest.py b/rpkid/tests/smoketest.py index 448d93b4..63528a77 100644 --- a/rpkid/tests/smoketest.py +++ b/rpkid/tests/smoketest.py @@ -17,7 +17,7 @@ things that don't belong in yaml_script. $Id$ -Copyright (C) 2009--2010 Internet Systems Consortium ("ISC") +Copyright (C) 2009--2011 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 @@ -390,14 +390,14 @@ class allocation_db(list): list.__init__(self) self.root = allocation(yaml, self) - assert self.root.is_root() + assert self.root.is_root if self.root.crl_interval is None: self.root.crl_interval = rpki.sundial.timedelta.parse(cfg.get("crl_interval", "1d")).convert_to_seconds() if self.root.regen_margin is None: self.root.regen_margin = rpki.sundial.timedelta.parse(cfg.get("regen_margin", "1d")).convert_to_seconds() for a in self: if a.sia_base is None: - a.sia_base = (rootd_sia if a.is_root() else a.parent.sia_base) + a.name + "/" + a.sia_base = (rootd_sia if a.is_root else a.parent.sia_base) + a.name + "/" if a.base.valid_until is None: a.base.valid_until = a.parent.base.valid_until if a.crl_interval is None: @@ -410,16 +410,16 @@ class allocation_db(list): a.client_handle = a.sia_base[i:].rstrip("/") self.root.closure() self.map = dict((a.name, a) for a in self) - self.engines = [a for a in self if a.is_engine()] - self.leaves = [a for a in self if a.is_leaf()] + self.engines = [a for a in self if a.is_engine] + self.leaves = [a for a in self if a.is_leaf] for i, a in enumerate(self.engines): a.set_engine_number(i) for a in self: - if a.is_hosted(): + if a.is_hosted: a.hosted_by = self.map[a.hosted_by] a.hosted_by.hosts.append(a) - assert a.is_twig(), "%s is not twig" % a.name - assert not a.hosted_by.is_hosted(), "%s is hosted by a hosted entity" % a.name + assert a.is_twig, "%s is not twig" % a.name + assert not a.hosted_by.is_hosted, "%s is hosted by a hosted entity" % a.name def apply_delta(self, delta, cb): """ @@ -579,7 +579,7 @@ class allocation(object): raise e cb() - if self.is_leaf(): + if self.is_leaf: raise RuntimeError, "Can't rekey YAML leaf %s, sorry" % self.name elif target is None: rpki.log.info("Rekeying <self/> %s" % self.name) @@ -596,7 +596,7 @@ class allocation(object): raise e cb() - if self.is_leaf(): + if self.is_leaf: rpki.log.info("Attempting to revoke YAML leaf %s" % self.name) subprocess.check_call((prog_python, prog_poke, "-y", self.name + ".yaml", "-r", "revoke")) cb() @@ -617,21 +617,26 @@ class allocation(object): if self.sia_base: s += " SIA: %s\n" % self.sia_base return s + "Until: %s\n" % self.resources.valid_until + @property def is_leaf(self): #return not self.kids and not self.roa_requests return False + @property def is_root(self): return self.parent is None + @property def is_twig(self): - return not self.is_leaf() and not self.is_root() + return not self.is_leaf and not self.is_root + @property def is_hosted(self): return self.hosted_by is not None + @property def is_engine(self): - return not self.is_leaf() and not self.is_hosted() + return not self.is_leaf and not self.is_hosted def set_engine_number(self, n): """ @@ -646,7 +651,7 @@ class allocation(object): """ Get rpki port to use for this entity. """ - if self.is_hosted(): + if self.is_hosted: assert self.hosted_by.rpki_port is not None return self.hosted_by.rpki_port else: @@ -658,7 +663,7 @@ class allocation(object): Create BPKI certificates for this entity. """ rpki.log.info("Constructing BPKI keys and certs for %s" % self.name) - if self.is_leaf(): + if self.is_leaf: setup_bpki_cert_chain(self.name, ee = ("RPKI",)) else: setup_bpki_cert_chain(name = self.name, @@ -779,10 +784,10 @@ class allocation(object): rpki.log.info("Calling rpkid for %s" % self.name) - if self.is_hosted(): + if self.is_hosted: rpki.log.info("rpkid %s is hosted by rpkid %s, switching" % (self.name, self.hosted_by.name)) self = self.hosted_by - assert not self.is_hosted() + assert not self.is_hosted assert isinstance(pdus, (list, tuple)) assert self.rpki_port is not None @@ -799,7 +804,7 @@ class allocation(object): r_cms = rpki.left_right.cms_msg(DER = r_der) r_msg = r_cms.unwrap((self.rpkid_ta, self.rpkid_cert)) rpki.log.debug(r_cms.pretty_print_content()) - assert r_msg.is_reply() + assert r_msg.is_reply for r_pdu in r_msg: assert not isinstance(r_pdu, rpki.left_right.report_error_elt) cb(r_msg) @@ -821,7 +826,7 @@ class allocation(object): if reverse: certifier = certificant certificant = self.name + "-SELF" - elif self.is_leaf(): + elif self.is_leaf: certifier = self.name + "-TA" else: certifier = self.name + "-SELF" @@ -871,7 +876,7 @@ class allocation(object): #10 requests we get back when we tell rpkid to generate BSC keys. """ - assert not self.is_hosted() and not self.is_leaf() + assert not self.is_hosted and not self.is_leaf selves = [self] + self.hosts @@ -889,7 +894,7 @@ class allocation(object): crl_interval = s.crl_interval, regen_margin = s.regen_margin, bpki_cert = (s.cross_certify(s.hosted_by.name + "-TA", reverse = True) - if s.is_hosted() else + if s.is_hosted else rpki.x509.X509(Auto_file = s.name + "-SELF.cer")))) rpkid_pdus.append(rpki.left_right.bsc_elt.make_pdu( @@ -918,9 +923,9 @@ class allocation(object): self_handle = s.name, child_handle = k.name, bsc_handle = "b", - bpki_cert = s.cross_certify(k.name + ("-TA" if k.is_leaf() else "-SELF")))) + bpki_cert = s.cross_certify(k.name + ("-TA" if k.is_leaf else "-SELF")))) - if s.is_root(): + if s.is_root: rootd_cert = s.cross_certify(rootd_name + "-TA") rpkid_pdus.append(rpki.left_right.parent_elt.make_pdu( action = "create", @@ -1009,7 +1014,7 @@ class allocation(object): stdout = subprocess.PIPE, stderr = subprocess.STDOUT) ski = rpki.x509.RSA(PEM_file = self.name + ".key").gSKI() - if self.parent.is_hosted(): + if self.parent.is_hosted: parent_host = self.parent.hosted_by.name else: parent_host = self.parent.name @@ -1024,7 +1029,7 @@ class allocation(object): "parent_host" : parent_host, "my_name" : self.name, "http_port" : self.parent.get_rpki_port(), - "class_name" : 2 if self.parent.is_hosted() else 1, + "class_name" : 2 if self.parent.is_hosted else 1, "sia" : self.sia_base, "ski" : ski }) f.close() @@ -1190,7 +1195,7 @@ def call_pubd(pdus, cb): r_cms = rpki.publication.cms_msg(DER = r_der) r_msg = r_cms.unwrap((pubd_ta, pubd_pubd_cert)) rpki.log.debug(r_cms.pretty_print_content()) - assert r_msg.is_reply() + assert r_msg.is_reply for r_pdu in r_msg: assert not isinstance(r_pdu, rpki.publication.report_error_elt) cb(r_msg) |