aboutsummaryrefslogtreecommitdiff
path: root/rpki/left_right.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/left_right.py')
-rw-r--r--rpki/left_right.py113
1 files changed, 85 insertions, 28 deletions
diff --git a/rpki/left_right.py b/rpki/left_right.py
index 68ead08f..e4cf25fe 100644
--- a/rpki/left_right.py
+++ b/rpki/left_right.py
@@ -67,6 +67,7 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
"""
Fetch self object to which this object links.
"""
+
return self_elt.sql_fetch(self.gctx, self.self_id)
@property
@@ -75,12 +76,14 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
"""
Return BSC object to which this object links.
"""
+
return bsc_elt.sql_fetch(self.gctx, self.bsc_id)
def make_reply_clone_hook(self, r_pdu):
"""
Set handles when cloning, including _id -> _handle translation.
"""
+
if r_pdu.self_handle is None:
r_pdu.self_handle = self.self_handle
for tag, elt in self.handles:
@@ -97,6 +100,7 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
"""
Find an object based on its handle.
"""
+
return cls.sql_fetch_where1(gctx, cls.element_name + "_handle = %s AND self_id = %s", (handle, self_id))
def serve_fetch_one_maybe(self):
@@ -104,6 +108,7 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
Find the object on which a get, set, or destroy method should
operate, or which would conflict with a create method.
"""
+
where = "%s.%s_handle = %%s AND %s.self_id = self.self_id AND self.self_handle = %%s" % ((self.element_name,) * 3)
args = (getattr(self, self.element_name + "_handle"), self.self_handle)
return self.sql_fetch_where1(self.gctx, where, args, "self")
@@ -112,6 +117,7 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
"""
Find the objects on which a list method should operate.
"""
+
where = "%s.self_id = self.self_id and self.self_handle = %%s" % self.element_name
return self.sql_fetch_where(self.gctx, where, (self.self_handle,), "self")
@@ -124,6 +130,7 @@ class data_elt(rpki.xml_utils.data_elt, rpki.sql.sql_persistent, left_right_name
operations, self is the pre-existing object from SQL and q_pdu is
the set request received from the the IRBE.
"""
+
for tag, elt in self.handles:
id_name = tag + "_id"
if getattr(self, id_name, None) is None:
@@ -171,6 +178,7 @@ class self_elt(data_elt):
"""
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
@@ -178,6 +186,7 @@ class self_elt(data_elt):
"""
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
@@ -185,6 +194,7 @@ class self_elt(data_elt):
"""
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
@@ -192,6 +202,7 @@ class self_elt(data_elt):
"""
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
@@ -199,6 +210,7 @@ class self_elt(data_elt):
"""
Fetch all ROA objects that link to this self object.
"""
+
return rpki.rpkid.roa_obj.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
@property
@@ -206,6 +218,7 @@ class self_elt(data_elt):
"""
Fetch all Ghostbuster record objects that link to this self object.
"""
+
return rpki.rpkid.ghostbuster_obj.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
@property
@@ -213,6 +226,7 @@ class self_elt(data_elt):
"""
Fetch all EE certificate objects that link to this self object.
"""
+
return rpki.rpkid.ee_cert_obj.sql_fetch_where(self.gctx, "self_id = %s", (self.self_id,))
@@ -220,6 +234,7 @@ class self_elt(data_elt):
"""
Extra server actions for self_elt.
"""
+
actions = []
if q_pdu.rekey:
actions.append(self.serve_rekey)
@@ -243,6 +258,7 @@ class self_elt(data_elt):
"""
Handle a left-right rekey action for this self.
"""
+
def loop(iterator, parent):
parent.serve_rekey(iterator, eb)
rpki.async.iterator(self.parents, loop, cb)
@@ -251,6 +267,7 @@ class self_elt(data_elt):
"""
Handle a left-right revoke action for this self.
"""
+
def loop(iterator, parent):
parent.serve_revoke(iterator, eb)
rpki.async.iterator(self.parents, loop, cb)
@@ -259,6 +276,7 @@ class self_elt(data_elt):
"""
Handle a left-right reissue action for this self.
"""
+
def loop(iterator, parent):
parent.serve_reissue(iterator, eb)
rpki.async.iterator(self.parents, loop, cb)
@@ -267,6 +285,7 @@ class self_elt(data_elt):
"""
Handle a left-right revoke_forgotten action for this self.
"""
+
def loop(iterator, parent):
parent.serve_revoke_forgotten(iterator, eb)
rpki.async.iterator(self.parents, loop, cb)
@@ -275,6 +294,7 @@ class self_elt(data_elt):
"""
Handle a left-right clear_replay_protection action for this self.
"""
+
def loop(iterator, obj):
obj.serve_clear_replay_protection(iterator, eb)
rpki.async.iterator(self.parents + self.children + self.repositories, loop, cb)
@@ -283,6 +303,7 @@ class self_elt(data_elt):
"""
Extra cleanup actions when destroying a self_elt.
"""
+
def loop(iterator, parent):
parent.delete(iterator)
rpki.async.iterator(self.parents, loop, cb)
@@ -291,45 +312,44 @@ class self_elt(data_elt):
def serve_publish_world_now(self, cb, eb):
"""
Handle a left-right publish_world_now action for this self.
-
- The publication stuff needs refactoring, right now publication is
- interleaved with local operations in a way that forces far too
- many bounces through the task system for any complex update. The
- whole thing ought to be rewritten to queue up outgoing publication
- PDUs and only send them when we're all done or when we need to
- force publication at a particular point in a multi-phase operation.
-
- Once that reorganization has been done, this method should be
- rewritten to reuse the low-level publish() methods that each
- object will have...but we're not there yet. So, for now, we just
- do this via brute force. Think of it as a trial version to see
- whether we've identified everything that needs to be republished
- for this operation.
"""
+ publisher = rpki.rpkid.publication_queue()
+
def loop(iterator, parent):
- q_msg = rpki.publication.msg.query()
+ repo = parent.repository
for ca in parent.cas:
ca_detail = ca.active_ca_detail
if ca_detail is not None:
- 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)
- q_msg.extend(rpki.publication.ghostbuster_elt.make_publish(
- g.uri, g.ghostbuster) for g in ca_detail.ghostbusters)
- parent.repository.call_pubd(iterator, eb, q_msg)
+ publisher.queue(
+ uri = ca_detail.crl_uri, new_obj = ca_detail.latest_crl, repository = repo)
+ publisher.queue(
+ uri = ca_detail.manifest_uri, new_obj = ca_detail.latest_manifest, repository = repo)
+ for c in ca_detail.child_certs:
+ publisher.queue(
+ uri = c.uri, new_obj = c.cert, repository = repo)
+ for r in ca_detail.roas:
+ if r.roa is not None:
+ publisher.queue(
+ uri = r.uri, new_obj = r.roa, repository = repo)
+ for g in ca_detail.ghostbusters:
+ publisher.queue(
+ uri = g.uri, new_obj = g.ghostbuster, repository = repo)
+ for c in ca_detail.ee_certificates:
+ publisher.queue(
+ uri = c.uri, new_obj = c.cert, repository = repo)
+ iterator()
- rpki.async.iterator(self.parents, loop, cb)
+ def done():
+ publisher.call_pubd(cb, eb)
+
+ rpki.async.iterator(self.parents, loop, done)
def serve_run_now(self, cb, eb):
"""
Handle a left-right run_now action for this self.
"""
+
logger.debug("Forced immediate run of periodic actions for self %s[%d]",
self.self_handle, self.self_id)
completion = rpki.rpkid_tasks.CompletionHandler(cb)
@@ -342,6 +362,7 @@ class self_elt(data_elt):
Find the self object upon which a get, set, or destroy action
should operate, or which would conflict with a create method.
"""
+
return self.serve_fetch_handle(self.gctx, None, self.self_handle)
@classmethod
@@ -349,6 +370,7 @@ class self_elt(data_elt):
"""
Find a self object based on its self_handle.
"""
+
return cls.sql_fetch_where1(gctx, "self_handle = %s", (self_handle,))
def serve_fetch_all(self):
@@ -357,6 +379,7 @@ class self_elt(data_elt):
This is different from the list action for all other objects,
where list only works within a given self_id context.
"""
+
return self.sql_fetch_all(self.gctx)
def schedule_cron_tasks(self, completion):
@@ -428,6 +451,7 @@ class bsc_elt(data_elt):
"""
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
@@ -435,6 +459,7 @@ class bsc_elt(data_elt):
"""
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
@@ -442,6 +467,7 @@ class bsc_elt(data_elt):
"""
Fetch all child objects that link to this BSC object.
"""
+
return child_elt.sql_fetch_where(self.gctx, "bsc_id = %s", (self.bsc_id,))
def serve_pre_save_hook(self, q_pdu, r_pdu, cb, eb):
@@ -449,6 +475,7 @@ class bsc_elt(data_elt):
Extra server actions for bsc_elt -- handle key generation. For
now this only allows RSA with SHA-256.
"""
+
if q_pdu.generate_keypair:
assert q_pdu.key_type in (None, "rsa") and q_pdu.hash_alg in (None, "sha256")
self.private_key_id = rpki.x509.RSA.generate(keylength = q_pdu.key_length or 2048)
@@ -492,12 +519,14 @@ class repository_elt(data_elt):
"""
Fetch all parent objects that link to this repository object.
"""
+
return parent_elt.sql_fetch_where(self.gctx, "repository_id = %s", (self.repository_id,))
def serve_post_save_hook(self, q_pdu, r_pdu, cb, eb):
"""
Extra server actions for repository_elt.
"""
+
actions = []
if q_pdu.clear_replay_protection:
actions.append(self.serve_clear_replay_protection)
@@ -509,6 +538,7 @@ class repository_elt(data_elt):
"""
Handle a left-right clear_replay_protection action for this repository.
"""
+
self.last_cms_timestamp = None
self.sql_mark_dirty()
cb()
@@ -518,6 +548,7 @@ class repository_elt(data_elt):
"""
Default handler for publication response PDUs.
"""
+
pdu.raise_if_error()
def call_pubd(self, callback, errback, q_msg, handlers = None):
@@ -544,7 +575,7 @@ class repository_elt(data_elt):
handlers = {}
for q_pdu in q_msg:
- logger.info("Sending %s %s to pubd", q_pdu.action, q_pdu.uri)
+ logger.info("Sending %r to pubd", q_pdu)
bsc = self.bsc
q_der = rpki.publication.cms_msg().wrap(q_msg, bsc.private_key_id, bsc.signing_cert, bsc.signing_cert_crl)
@@ -624,6 +655,7 @@ class parent_elt(data_elt):
"""
Fetch repository object to which this parent object links.
"""
+
return repository_elt.sql_fetch(self.gctx, self.repository_id)
@property
@@ -631,12 +663,14 @@ class parent_elt(data_elt):
"""
Fetch all CA objects that link to this parent object.
"""
+
return rpki.rpkid.ca_obj.sql_fetch_where(self.gctx, "parent_id = %s", (self.parent_id,))
def serve_post_save_hook(self, q_pdu, r_pdu, cb, eb):
"""
Extra server actions for parent_elt.
"""
+
actions = []
if q_pdu.rekey:
actions.append(self.serve_rekey)
@@ -656,6 +690,7 @@ class parent_elt(data_elt):
"""
Handle a left-right rekey action for this parent.
"""
+
def loop(iterator, ca):
ca.rekey(iterator, eb)
rpki.async.iterator(self.cas, loop, cb)
@@ -664,6 +699,7 @@ class parent_elt(data_elt):
"""
Handle a left-right revoke action for this parent.
"""
+
def loop(iterator, ca):
ca.revoke(cb = iterator, eb = eb)
rpki.async.iterator(self.cas, loop, cb)
@@ -672,6 +708,7 @@ class parent_elt(data_elt):
"""
Handle a left-right reissue action for this parent.
"""
+
def loop(iterator, ca):
ca.reissue(cb = iterator, eb = eb)
rpki.async.iterator(self.cas, loop, cb)
@@ -680,6 +717,7 @@ class parent_elt(data_elt):
"""
Handle a left-right clear_replay_protection action for this parent.
"""
+
self.last_cms_timestamp = None
self.sql_mark_dirty()
cb()
@@ -860,6 +898,7 @@ class child_elt(data_elt):
"""
Fetch all child_cert objects that link to this child object.
"""
+
return rpki.rpkid.child_cert_obj.fetch(self.gctx, self, ca_detail, ski, unique)
@property
@@ -867,6 +906,7 @@ class child_elt(data_elt):
"""
Fetch all child_cert objects that link to this child object.
"""
+
return self.fetch_child_certs()
@property
@@ -874,12 +914,14 @@ class child_elt(data_elt):
"""
Fetch all parent objects that link to self object to which this child object links.
"""
+
return parent_elt.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 child_elt.
"""
+
actions = []
if q_pdu.reissue:
actions.append(self.serve_reissue)
@@ -893,6 +935,7 @@ class child_elt(data_elt):
"""
Handle a left-right reissue action for this child.
"""
+
publisher = rpki.rpkid.publication_queue()
for child_cert in self.child_certs:
child_cert.reissue(child_cert.ca_detail, publisher, force = True)
@@ -902,6 +945,7 @@ class child_elt(data_elt):
"""
Handle a left-right clear_replay_protection action for this child.
"""
+
self.last_cms_timestamp = None
self.sql_mark_dirty()
cb()
@@ -910,6 +954,7 @@ class child_elt(data_elt):
"""
Fetch the CA corresponding to an up-down class_name.
"""
+
if not class_name.isdigit():
raise rpki.exceptions.BadClassNameSyntax("Bad class name %s" % class_name)
ca = rpki.rpkid.ca_obj.sql_fetch(self.gctx, long(class_name))
@@ -926,6 +971,7 @@ class child_elt(data_elt):
"""
Extra server actions when destroying a child_elt.
"""
+
publisher = rpki.rpkid.publication_queue()
for child_cert in self.child_certs:
child_cert.revoke(publisher = publisher,
@@ -989,6 +1035,7 @@ class list_resources_elt(rpki.xml_utils.base_elt, left_right_namespace):
Handle <list_resources/> element. This requires special handling
due to the data types of some of the attributes.
"""
+
assert name == "list_resources", "Unexpected name %s, stack %s" % (name, stack)
self.read_attrs(attrs)
if isinstance(self.valid_until, str):
@@ -1005,6 +1052,7 @@ class list_resources_elt(rpki.xml_utils.base_elt, left_right_namespace):
Generate <list_resources/> element. This requires special
handling due to the data types of some of the attributes.
"""
+
elt = self.make_elt()
if isinstance(self.valid_until, int):
elt.set("valid_until", self.valid_until.toXMLtime())
@@ -1023,6 +1071,7 @@ class list_roa_requests_elt(rpki.xml_utils.base_elt, left_right_namespace):
Handle <list_roa_requests/> element. This requires special handling
due to the data types of some of the attributes.
"""
+
assert name == "list_roa_requests", "Unexpected name %s, stack %s" % (name, stack)
self.read_attrs(attrs)
if self.ipv4 is not None:
@@ -1068,6 +1117,7 @@ class list_ee_certificate_requests_elt(rpki.xml_utils.base_elt, left_right_names
Handle <list_ee_certificate_requests/> element. This requires special
handling due to the data types of some of the attributes.
"""
+
if name not in self.elements:
assert name == self.element_name, "Unexpected name %s, stack %s" % (name, stack)
self.read_attrs(attrs)
@@ -1086,6 +1136,7 @@ class list_ee_certificate_requests_elt(rpki.xml_utils.base_elt, left_right_names
"""
Handle <pkcs10/> sub-element.
"""
+
assert len(self.elements) == 1
if name == self.elements[0]:
self.pkcs10 = rpki.x509.PKCS10(Base64 = text)
@@ -1098,6 +1149,7 @@ class list_ee_certificate_requests_elt(rpki.xml_utils.base_elt, left_right_names
Generate <list_ee_certificate_requests/> element. This requires special
handling due to the data types of some of the attributes.
"""
+
if isinstance(self.eku, (tuple, list)):
self.eku = ",".join(self.eku)
elt = self.make_elt()
@@ -1128,6 +1180,7 @@ 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:
ca_detail = ca.active_ca_detail
@@ -1148,6 +1201,7 @@ class list_published_objects_elt(rpki.xml_utils.text_elt, left_right_namespace):
"""
Generate one reply PDU.
"""
+
r_pdu = self.make_pdu(tag = self.tag, self_handle = self.self_handle,
uri = uri, child_handle = child_handle)
r_pdu.obj = obj.get_Base64()
@@ -1172,6 +1226,7 @@ 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:
ca_detail = ca.active_ca_detail
@@ -1183,6 +1238,7 @@ class list_received_resources_elt(rpki.xml_utils.base_elt, left_right_namespace)
"""
Generate one reply PDU.
"""
+
resources = cert.get_3779resources()
return self.make_pdu(
tag = self.tag,
@@ -1216,6 +1272,7 @@ class report_error_elt(rpki.xml_utils.text_elt, left_right_namespace):
"""
Generate a <report_error/> element from an exception.
"""
+
self = cls()
self.self_handle = self_handle
self.tag = tag