aboutsummaryrefslogtreecommitdiff
path: root/rpki/rpkid.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpki/rpkid.py')
-rw-r--r--rpki/rpkid.py271
1 files changed, 179 insertions, 92 deletions
diff --git a/rpki/rpkid.py b/rpki/rpkid.py
index 13be2fd2..e9a05abb 100644
--- a/rpki/rpkid.py
+++ b/rpki/rpkid.py
@@ -316,6 +316,7 @@ class main(object):
Record that we were still alive when we got here, by resetting
keepalive timer.
"""
+
if force or self.cron_timeout is not None:
self.cron_timeout = rpki.sundial.now() + self.cron_keepalive
@@ -323,6 +324,7 @@ class main(object):
"""
Add a task to the scheduler task queue, unless it's already queued.
"""
+
if task not in self.task_queue:
logger.debug("Adding %r to task queue", task)
self.task_queue.append(task)
@@ -337,6 +339,7 @@ class main(object):
queue (we don't want to run it directly, as that could eventually
blow out our call stack).
"""
+
try:
self.task_current = self.task_queue.pop(0)
except IndexError:
@@ -348,6 +351,7 @@ class main(object):
"""
Run first task on the task queue, unless one is running already.
"""
+
if self.task_current is None:
self.task_next()
@@ -444,6 +448,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch parent object to which this CA object links.
"""
+
return rpki.left_right.parent_elt.sql_fetch(self.gctx, self.parent_id)
@property
@@ -451,6 +456,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch all ca_detail objects that link to this CA object.
"""
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s", (self.ca_id,))
@property
@@ -458,6 +464,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch the pending ca_details for this CA, if any.
"""
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND state = 'pending'", (self.ca_id,))
@property
@@ -465,6 +472,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch the active ca_detail for this CA, if any.
"""
+
return ca_detail_obj.sql_fetch_where1(self.gctx, "ca_id = %s AND state = 'active'", (self.ca_id,))
@property
@@ -472,6 +480,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch deprecated ca_details for this CA, if any.
"""
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND state = 'deprecated'", (self.ca_id,))
@property
@@ -479,6 +488,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch active and deprecated ca_details for this CA, if any.
"""
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND (state = 'active' OR state = 'deprecated')", (self.ca_id,))
@property
@@ -486,6 +496,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Fetch revoked ca_details for this CA, if any.
"""
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND state = 'revoked'", (self.ca_id,))
@property
@@ -494,7 +505,7 @@ class ca_obj(rpki.sql.sql_persistent):
Fetch ca_details which are candidates for consideration when
processing an up-down issue_response PDU.
"""
- #return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND latest_ca_cert IS NOT NULL AND state != 'revoked'", (self.ca_id,))
+
return ca_detail_obj.sql_fetch_where(self.gctx, "ca_id = %s AND state != 'revoked'", (self.ca_id,))
def construct_sia_uri(self, parent, rc):
@@ -540,7 +551,8 @@ class ca_obj(rpki.sql.sql_persistent):
if rc_cert is None:
- logger.warning("SKI %s in resource class %s is in database but missing from list_response to %s from %s, maybe parent certificate went away?",
+ logger.warning("SKI %s in resource class %s is in database but missing from list_response to %s from %s, "
+ "maybe parent certificate went away?",
ca_detail.public_key.gSKI(), rc.class_name, parent.self.self_handle, parent.parent_handle)
publisher = publication_queue()
ca_detail.delete(ca = ca_detail.ca, publisher = publisher)
@@ -675,6 +687,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Allocate a certificate serial number.
"""
+
self.last_issued_sn += 1
self.sql_mark_dirty()
return self.last_issued_sn
@@ -683,6 +696,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Allocate a manifest serial number.
"""
+
self.last_manifest_sn += 1
self.sql_mark_dirty()
return self.last_manifest_sn
@@ -691,6 +705,7 @@ class ca_obj(rpki.sql.sql_persistent):
"""
Allocate a CRL serial number.
"""
+
self.last_crl_sn += 1
self.sql_mark_dirty()
return self.last_crl_sn
@@ -781,6 +796,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Extra assertions for SQL decode of a ca_detail_obj.
"""
+
rpki.sql.sql_persistent.sql_decode(self, vals)
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()
@@ -791,12 +807,14 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Fetch CA object to which this ca_detail links.
"""
+
return ca_obj.sql_fetch(self.gctx, self.ca_id)
def fetch_child_certs(self, child = None, ski = None, unique = False, unpublished = None):
"""
Fetch all child_cert objects that link to this ca_detail.
"""
+
return rpki.rpkid.child_cert_obj.fetch(self.gctx, child, self, ski, unique, unpublished)
@property
@@ -804,6 +822,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Fetch all child_cert objects that link to this ca_detail.
"""
+
return self.fetch_child_certs()
def unpublished_child_certs(self, when):
@@ -811,6 +830,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
Fetch all unpublished child_cert objects linked to this ca_detail
with attempted publication dates older than when.
"""
+
return self.fetch_child_certs(unpublished = when)
@property
@@ -818,6 +838,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
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
@@ -825,6 +846,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Fetch all ROA objects that link to this ca_detail.
"""
+
return rpki.rpkid.roa_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,))
def unpublished_roas(self, when):
@@ -832,6 +854,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
Fetch all unpublished ROA objects linked to this ca_detail with
attempted publication dates older than when.
"""
+
return rpki.rpkid.roa_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s AND published IS NOT NULL and published < %s", (self.ca_detail_id, when))
@property
@@ -839,27 +862,39 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Fetch all Ghostbuster objects that link to this ca_detail.
"""
+
return rpki.rpkid.ghostbuster_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,))
+ def unpublished_ghostbusters(self, when):
+ """
+ Fetch all unpublished Ghostbusters objects linked to this
+ ca_detail with attempted publication dates older than when.
+ """
+
+ return rpki.rpkid.ghostbuster_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s AND published IS NOT NULL and published < %s", (self.ca_detail_id, when))
+
@property
def ee_certificates(self):
"""
Fetch all EE certificate objects that link to this ca_detail.
"""
+
return rpki.rpkid.ee_cert_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s", (self.ca_detail_id,))
- def unpublished_ghostbusters(self, when):
+ def unpublished_ee_certificates(self, when):
"""
- Fetch all unpublished Ghostbusters objects linked to this
+ Fetch all unpublished EE certificate objects linked to this
ca_detail with attempted publication dates older than when.
"""
- return rpki.rpkid.ghostbuster_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s AND published IS NOT NULL and published < %s", (self.ca_detail_id, when))
+
+ return rpki.rpkid.ee_cert_obj.sql_fetch_where(self.gctx, "ca_detail_id = %s AND published IS NOT NULL and published < %s", (self.ca_detail_id, when))
@property
def crl_uri(self):
"""
Return publication URI for this ca_detail's CRL.
"""
+
return self.ca.sia_uri + self.crl_uri_tail
@property
@@ -867,6 +902,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Return tail (filename portion) of publication URI for this ca_detail's CRL.
"""
+
return self.public_key.gSKI() + ".crl"
@property
@@ -874,12 +910,14 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Return publication URI for this ca_detail's manifest.
"""
+
return self.ca.sia_uri + self.public_key.gSKI() + ".mft"
def has_expired(self):
"""
Return whether this ca_detail's certificate has expired.
"""
+
return self.latest_ca_cert.getNotAfter() <= rpki.sundial.now()
def covers(self, target):
@@ -931,11 +969,10 @@ class ca_detail_obj(rpki.sql.sql_persistent):
repository = ca.parent.repository
handler = False if allow_failure else None
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 = handler)
+ publisher.queue(uri = child_cert.uri,
+ old_obj = child_cert.cert,
+ repository = repository,
+ handler = handler)
child_cert.sql_mark_deleted()
for roa in self.roas:
roa.revoke(publisher = publisher, allow_failure = allow_failure, fast = True)
@@ -946,21 +983,19 @@ class ca_detail_obj(rpki.sql.sql_persistent):
except AttributeError:
latest_manifest = None
if latest_manifest is not None:
- publisher.withdraw(cls = rpki.publication.manifest_elt,
- uri = self.manifest_uri,
- obj = self.latest_manifest,
- repository = repository,
- handler = handler)
+ publisher.queue(uri = self.manifest_uri,
+ old_obj = self.latest_manifest,
+ repository = repository,
+ handler = handler)
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,
- obj = self.latest_crl,
- repository = repository,
- handler = handler)
+ publisher.queue(uri = self.crl_uri,
+ old_obj = self.latest_crl,
+ repository = repository,
+ handler = handler)
self.gctx.sql.sweep()
for cert in self.revoked_certs: # + self.child_certs
logger.debug("Deleting %r", cert)
@@ -1170,6 +1205,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
notAfter = resources.valid_until)
if child_cert is None:
+ old_cert = None
child_cert = rpki.rpkid.child_cert_obj(
gctx = child.gctx,
child_id = child.child_id,
@@ -1177,6 +1213,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
cert = cert)
logger.debug("Created new child_cert %r", child_cert)
else:
+ old_cert = child_cert.cert
child_cert.cert = cert
del child_cert.ca_detail
child_cert.ca_detail_id = self.ca_detail_id
@@ -1185,10 +1222,10 @@ class ca_detail_obj(rpki.sql.sql_persistent):
child_cert.ski = cert.get_SKI()
child_cert.published = rpki.sundial.now()
child_cert.sql_store()
- publisher.publish(
- cls = rpki.publication.certificate_elt,
+ publisher.queue(
uri = child_cert.uri,
- obj = child_cert.cert,
+ old_obj = old_cert,
+ new_obj = child_cert.cert,
repository = ca.parent.repository,
handler = child_cert.published_callback)
self.generate_manifest(publisher = publisher)
@@ -1219,6 +1256,8 @@ class ca_detail_obj(rpki.sql.sql_persistent):
certlist.append((revoked_cert.serial, revoked_cert.revoked))
certlist.sort()
+ old_crl = self.latest_crl
+
self.latest_crl = rpki.x509.CRL.generate(
keypair = self.private_key_id,
issuer = self.latest_ca_cert,
@@ -1229,10 +1268,10 @@ 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,
+ publisher.queue(
uri = self.crl_uri,
- obj = self.latest_crl,
+ old_obj = old_crl,
+ new_obj = self.latest_crl,
repository = parent.repository,
handler = self.crl_published_callback)
@@ -1240,6 +1279,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
"""
Check result of CRL publication.
"""
+
pdu.raise_if_error()
self.crl_published = None
self.sql_mark_dirty()
@@ -1276,6 +1316,7 @@ class ca_detail_obj(rpki.sql.sql_persistent):
objs.extend((e.uri_tail, e.cert) for e in self.ee_certificates)
logger.debug("Building manifest object %s", uri)
+ old_manifest = self.latest_manifest
self.latest_manifest = rpki.x509.SignedManifest.build(
serial = ca.next_manifest_number(),
thisUpdate = now,
@@ -1288,16 +1329,17 @@ 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 = uri,
- obj = self.latest_manifest,
- repository = parent.repository,
- handler = self.manifest_published_callback)
+ publisher.queue(uri = uri,
+ old_obj = old_manifest,
+ new_obj = self.latest_manifest,
+ repository = parent.repository,
+ handler = self.manifest_published_callback)
def manifest_published_callback(self, pdu):
"""
Check result of manifest publication.
"""
+
pdu.raise_if_error()
self.manifest_published = None
self.sql_mark_dirty()
@@ -1359,21 +1401,19 @@ class ca_detail_obj(rpki.sql.sql_persistent):
self.crl_published is not None and \
self.crl_published < stale:
logger.debug("Retrying publication for %s", self.crl_uri)
- publisher.publish(cls = rpki.publication.crl_elt,
- uri = self.crl_uri,
- obj = self.latest_crl,
- repository = repository,
- handler = self.crl_published_callback)
+ publisher.queue(uri = self.crl_uri,
+ new_obj = self.latest_crl,
+ repository = repository,
+ handler = self.crl_published_callback)
if self.latest_manifest is not None and \
self.manifest_published is not None and \
self.manifest_published < stale:
logger.debug("Retrying publication for %s", self.manifest_uri)
- publisher.publish(cls = rpki.publication.manifest_elt,
- uri = self.manifest_uri,
- obj = self.latest_manifest,
- repository = repository,
- handler = self.manifest_published_callback)
+ publisher.queue(uri = self.manifest_uri,
+ new_obj = self.latest_manifest,
+ repository = repository,
+ handler = self.manifest_published_callback)
if not check_all:
return
@@ -1383,31 +1423,37 @@ class ca_detail_obj(rpki.sql.sql_persistent):
for child_cert in self.unpublished_child_certs(stale):
logger.debug("Retrying publication for %s", child_cert)
- publisher.publish(
- cls = rpki.publication.certificate_elt,
+ publisher.queue(
uri = child_cert.uri,
- obj = child_cert.cert,
+ new_obj = child_cert.cert,
repository = repository,
handler = child_cert.published_callback)
for roa in self.unpublished_roas(stale):
logger.debug("Retrying publication for %s", roa)
- publisher.publish(
- cls = rpki.publication.roa_elt,
+ publisher.queue(
uri = roa.uri,
- obj = roa.roa,
+ new_obj = roa.roa,
repository = repository,
handler = roa.published_callback)
for ghostbuster in self.unpublished_ghostbusters(stale):
logger.debug("Retrying publication for %s", ghostbuster)
- publisher.publish(
- cls = rpki.publication.ghostbuster_elt,
+ publisher.queue(
uri = ghostbuster.uri,
- obj = ghostbuster.ghostbuster,
+ new_obj = ghostbuster.ghostbuster,
repository = repository,
handler = ghostbuster.published_callback)
+ for ee_cert in self.unpublished_ee_certificates(stale):
+ logger.debug("Retrying publication for %s", ee_cert)
+ publisher.queue(
+ uri = ee_cert.uri,
+ new_obj = ee_cert.cert,
+ repository = repository,
+ handler = ee_cert.published_callback)
+
+
class child_cert_obj(rpki.sql.sql_persistent):
"""
Certificate that has been issued to a child.
@@ -1434,6 +1480,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Initialize a child_cert_obj.
"""
+
rpki.sql.sql_persistent.__init__(self)
self.gctx = gctx
self.child_id = child_id
@@ -1449,6 +1496,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Fetch child object to which this child_cert object links.
"""
+
return rpki.left_right.child_elt.sql_fetch(self.gctx, self.child_id)
@property
@@ -1457,6 +1505,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Fetch ca_detail object to which this child_cert object links.
"""
+
return ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
@ca_detail.deleter
@@ -1471,6 +1520,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Return the tail (filename) portion of the URI for this child_cert.
"""
+
return self.cert.gSKI() + ".cer"
@property
@@ -1478,6 +1528,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Return the publication URI for this child_cert.
"""
+
return self.ca_detail.ca.sia_uri + self.uri_tail
def revoke(self, publisher, generate_crl_and_manifest = True):
@@ -1489,10 +1540,9 @@ class child_cert_obj(rpki.sql.sql_persistent):
ca = ca_detail.ca
logger.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,
- obj = self.cert,
+ publisher.queue(
+ uri = self.uri,
+ old_obj = self.cert,
repository = ca.parent.repository)
self.gctx.sql.sweep()
self.sql_delete()
@@ -1623,6 +1673,7 @@ class child_cert_obj(rpki.sql.sql_persistent):
"""
Publication callback: check result and mark published.
"""
+
pdu.raise_if_error()
self.published = None
self.sql_mark_dirty()
@@ -1647,6 +1698,7 @@ class revoked_cert_obj(rpki.sql.sql_persistent):
"""
Initialize a revoked_cert_obj.
"""
+
rpki.sql.sql_persistent.__init__(self)
self.gctx = gctx
self.serial = serial
@@ -1662,6 +1714,7 @@ class revoked_cert_obj(rpki.sql.sql_persistent):
"""
Fetch ca_detail object to which this revoked_cert_obj links.
"""
+
return ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
@classmethod
@@ -1669,6 +1722,7 @@ class revoked_cert_obj(rpki.sql.sql_persistent):
"""
Revoke a certificate.
"""
+
return cls(
serial = cert.getSerial(),
expires = cert.getNotAfter(),
@@ -1710,6 +1764,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Fetch ca_detail object to which this roa_obj links.
"""
+
return rpki.rpkid.ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
@ca_detail.deleter
@@ -1723,6 +1778,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Extra SQL fetch actions for roa_obj -- handle prefix lists.
"""
+
for version, datatype, attribute in ((4, rpki.resource_set.roa_prefix_set_ipv4, "ipv4"),
(6, rpki.resource_set.roa_prefix_set_ipv6, "ipv6")):
setattr(self, attribute, datatype.from_sql(
@@ -1737,6 +1793,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Extra SQL insert actions for roa_obj -- handle prefix lists.
"""
+
for version, prefix_set in ((4, self.ipv4), (6, self.ipv6)):
if prefix_set:
self.gctx.sql.executemany(
@@ -1751,6 +1808,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Extra SQL delete actions for roa_obj -- handle prefix lists.
"""
+
self.gctx.sql.execute("DELETE FROM roa_prefix WHERE roa_id = %s", (self.roa_id,))
def __repr__(self):
@@ -1892,10 +1950,9 @@ class roa_obj(rpki.sql.sql_persistent):
self.sql_store()
logger.debug("Generating %r URI %s", self, self.uri)
- publisher.publish(
- cls = rpki.publication.roa_elt,
+ publisher.queue(
uri = self.uri,
- obj = self.roa,
+ new_obj = self.roa,
repository = ca.parent.repository,
handler = self.published_callback)
if not fast:
@@ -1940,9 +1997,10 @@ class roa_obj(rpki.sql.sql_persistent):
logger.debug("Withdrawing %r %s and revoking its EE cert", self, uri)
rpki.rpkid.revoked_cert_obj.revoke(cert = cert, ca_detail = ca_detail)
- publisher.withdraw(cls = rpki.publication.roa_elt, uri = uri, obj = roa,
- repository = ca_detail.ca.parent.repository,
- handler = False if allow_failure else None)
+ publisher.queue(uri = uri,
+ old_obj = roa,
+ repository = ca_detail.ca.parent.repository,
+ handler = False if allow_failure else None)
if not regenerate:
self.sql_mark_deleted()
@@ -1956,6 +2014,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Reissue ROA associated with this roa_obj.
"""
+
if self.ca_detail is None:
self.generate(publisher = publisher, fast = fast)
else:
@@ -1965,6 +2024,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Return publication URI for a public key.
"""
+
return self.ca_detail.ca.sia_uri + key.gSKI() + ".roa"
@property
@@ -1972,6 +2032,7 @@ class roa_obj(rpki.sql.sql_persistent):
"""
Return the publication URI for this roa_obj's ROA.
"""
+
return self.ca_detail.ca.sia_uri + self.uri_tail
@property
@@ -1980,6 +2041,7 @@ class roa_obj(rpki.sql.sql_persistent):
Return the tail (filename portion) of the publication URI for this
roa_obj's ROA.
"""
+
return self.cert.gSKI() + ".roa"
@@ -2022,6 +2084,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Fetch self object to which this ghostbuster_obj links.
"""
+
return rpki.left_right.self_elt.sql_fetch(self.gctx, self.self_id)
@property
@@ -2030,6 +2093,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Fetch ca_detail object to which this ghostbuster_obj links.
"""
+
return rpki.rpkid.ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
def __init__(self, gctx = None, self_id = None, ca_detail_id = None, vcard = None):
@@ -2095,10 +2159,9 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
self.sql_store()
logger.debug("Generating Ghostbuster record %r", self.uri)
- publisher.publish(
- cls = rpki.publication.ghostbuster_elt,
+ publisher.queue(
uri = self.uri,
- obj = self.ghostbuster,
+ new_obj = self.ghostbuster,
repository = ca.parent.repository,
handler = self.published_callback)
if not fast:
@@ -2108,6 +2171,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Check publication result.
"""
+
pdu.raise_if_error()
self.published = None
self.sql_mark_dirty()
@@ -2142,9 +2206,10 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
logger.debug("Withdrawing %r %s and revoking its EE cert", self, uri)
rpki.rpkid.revoked_cert_obj.revoke(cert = cert, ca_detail = ca_detail)
- publisher.withdraw(cls = rpki.publication.ghostbuster_elt, uri = uri, obj = ghostbuster,
- repository = ca_detail.ca.parent.repository,
- handler = False if allow_failure else None)
+ publisher.queue(uri = uri,
+ old_obj = ghostbuster,
+ repository = ca_detail.ca.parent.repository,
+ handler = False if allow_failure else None)
if not regenerate:
self.sql_mark_deleted()
@@ -2158,6 +2223,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Reissue Ghostbuster associated with this ghostbuster_obj.
"""
+
if self.ghostbuster is None:
self.generate(publisher = publisher, fast = fast)
else:
@@ -2167,6 +2233,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Return publication URI for a public key.
"""
+
return self.ca_detail.ca.sia_uri + key.gSKI() + ".gbr"
@property
@@ -2174,6 +2241,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
"""
Return the publication URI for this ghostbuster_obj's ghostbuster.
"""
+
return self.ca_detail.ca.sia_uri + self.uri_tail
@property
@@ -2182,6 +2250,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent):
Return the tail (filename portion) of the publication URI for this
ghostbuster_obj's ghostbuster.
"""
+
return self.cert.gSKI() + ".gbr"
@@ -2219,6 +2288,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
"""
Fetch self object to which this ee_cert_obj links.
"""
+
return rpki.left_right.self_elt.sql_fetch(self.gctx, self.self_id)
@property
@@ -2227,6 +2297,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
"""
Fetch ca_detail object to which this ee_cert_obj links.
"""
+
return rpki.rpkid.ca_detail_obj.sql_fetch(self.gctx, self.ca_detail_id)
@ca_detail.deleter
@@ -2244,6 +2315,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
Although, really, one has to ask why we don't just store g(SKI)
in rpkid.sql instead of ski....
"""
+
return base64.urlsafe_b64encode(self.ski).rstrip("=")
@gski.setter
@@ -2255,6 +2327,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
"""
Return the publication URI for this ee_cert_obj.
"""
+
return self.ca_detail.ca.sia_uri + self.uri_tail
@property
@@ -2263,6 +2336,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
Return the tail (filename portion) of the publication URI for this
ee_cert_obj.
"""
+
return self.cert.gSKI() + ".cer"
@classmethod
@@ -2290,12 +2364,11 @@ class ee_cert_obj(rpki.sql.sql_persistent):
ca_detail_id = ca_detail.ca_detail_id,
cert = cert)
- publisher.publish(
- cls = rpki.publication.certificate_elt,
- uri = self.uri,
- obj = self.cert,
+ publisher.queue(
+ uri = self.uri,
+ new_obj = self.cert,
repository = ca.parent.repository,
- handler = self.published_callback)
+ handler = self.published_callback)
self.sql_store()
@@ -2314,10 +2387,9 @@ class ee_cert_obj(rpki.sql.sql_persistent):
ca = ca_detail.ca
logger.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,
- obj = self.cert,
- repository = ca.parent.repository)
+ publisher.queue(uri = self.uri,
+ old_obj = self.cert,
+ repository = ca.parent.repository)
self.gctx.sql.sweep()
self.sql_delete()
if generate_crl_and_manifest:
@@ -2399,12 +2471,12 @@ class ee_cert_obj(rpki.sql.sql_persistent):
self.sql_mark_dirty()
- publisher.publish(
- cls = rpki.publication.certificate_elt,
- uri = self.uri,
- obj = self.cert,
+ publisher.queue(
+ uri = self.uri,
+ old_obj = old_cert,
+ new_obj = self.cert,
repository = ca_detail.ca.parent.repository,
- handler = self.published_callback)
+ handler = self.published_callback)
if must_revoke:
revoked_cert_obj.revoke(cert = old_cert.cert, ca_detail = old_ca_detail)
@@ -2421,6 +2493,7 @@ class ee_cert_obj(rpki.sql.sql_persistent):
"""
Publication callback: check result and mark published.
"""
+
pdu.raise_if_error()
self.published = None
self.sql_mark_dirty()
@@ -2449,29 +2522,43 @@ class publication_queue(object):
if self.replace:
self.uris = {}
- def _add(self, uri, obj, repository, handler, make_pdu):
+ def queue(self, uri, repository, handler = None, old_obj = None, new_obj = None):
+
+ assert old_obj is not None or new_obj is not None
+ assert old_obj is None or isinstance(old_obj, rpki.x509.uri_dispatch(uri))
+ assert new_obj is None or isinstance(new_obj, rpki.x509.uri_dispatch(uri))
+
+ logger.debug("Queuing publication action: uri %s, old %r, new %r", uri, old_obj, new_obj)
+
rid = id(repository)
if rid not in self.repositories:
self.repositories[rid] = repository
self.msgs[rid] = rpki.publication.msg.query()
+
if self.replace and uri in self.uris:
- logger.debug("Removing publication duplicate <%s %r %r>",
- self.uris[uri].action, self.uris[uri].uri, self.uris[uri].payload)
- self.msgs[rid].remove(self.uris.pop(uri))
- pdu = make_pdu(uri = uri, obj = obj)
+ logger.debug("Removing publication duplicate %r", self.uris[uri])
+ old_pdu = self.uris.pop(uri)
+ self.msgs[rid].remove(old_pdu)
+ hash = old_pdu.hash
+ elif old_obj is None:
+ hash = None
+ else:
+ hash = rpki.x509.sha256(old_obj.get_DER()).encode("hex")
+
+ if new_obj is None:
+ pdu = rpki.publication.withdraw_elt.make_pdu(uri = uri, hash = hash)
+ else:
+ pdu = rpki.publication.publish_elt.make_pdu( uri = uri, hash = hash, der = new_obj.get_DER())
+
if handler is not None:
self.handlers[id(pdu)] = handler
pdu.tag = id(pdu)
+
self.msgs[rid].append(pdu)
+
if self.replace:
self.uris[uri] = pdu
- def publish(self, cls, uri, obj, repository, handler = None):
- return self._add( uri, obj, repository, handler, cls.make_publish)
-
- def withdraw(self, cls, uri, obj, repository, handler = None):
- return self._add( uri, obj, repository, handler, cls.make_withdraw)
-
def call_pubd(self, cb, eb):
def loop(iterator, rid):
logger.debug("Calling pubd[%r]", self.repositories[rid])
@@ -2486,5 +2573,5 @@ class publication_queue(object):
return sum(len(self.msgs[rid]) for rid in self.repositories)
def empty(self):
- assert (not self.msgs) == (self.size == 0)
+ assert (not self.msgs) == (self.size == 0), "Assertion failure: not self.msgs: %r, self.size %r" % (not self.msgs, self.size)
return not self.msgs