aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/left_right.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki/left_right.py')
-rw-r--r--rpkid/rpki/left_right.py232
1 files changed, 175 insertions, 57 deletions
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):
"""