aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/rpki/left_right.py19
-rw-r--r--scripts/rpki/log.py19
-rw-r--r--scripts/rpki/sql.py45
-rw-r--r--scripts/rpki/x509.py4
-rwxr-xr-xscripts/rpkid.py4
-rw-r--r--scripts/testbed.1.yaml6
-rw-r--r--scripts/testbed.py28
-rw-r--r--scripts/testpoke.py2
8 files changed, 74 insertions, 53 deletions
diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py
index a8813927..b512d94e 100644
--- a/scripts/rpki/left_right.py
+++ b/scripts/rpki/left_right.py
@@ -264,33 +264,38 @@ class self_elt(data_elt):
def serve_pre_save_hook(self, gctx, q_pdu, r_pdu):
"""Extra server actions for self_elt -- handle extension preferences."""
+ rpki.log.trace()
if self is not q_pdu:
if q_pdu.clear_extension_preferences:
self.prefs = []
- self.prefs.extend(pdu.prefs)
+ self.prefs.extend(q_pdu.prefs)
def serve_post_save_hook(self, gctx, q_pdu, r_pdu):
"""Extra server actions for self_elt."""
- if self.rekey:
+ rpki.log.trace()
+ if q_pdu.rekey:
self.serve_rekey(gctx)
- if self.reissue:
+ if q_pdu.reissue:
self.serve_reissue(gctx)
- if self.revoke:
+ if q_pdu.revoke:
self.serve_revoke(gctx)
self.unimplemented_control("run_now", "publish_world_now")
def serve_rekey(self, gctx):
"""Handle a left-right rekey action for this self."""
+ rpki.log.trace()
for parent in self.parents(gctx):
parent.serve_rekey(gctx)
def serve_revoke(self, gctx):
"""Handle a left-right revoke action for this self."""
+ rpki.log.trace()
for parent in self.parents(gctx):
parent.serve_revoke(gctx)
def serve_reissue(self, gctx):
"""Handle a left-right reissue action for this self."""
+ rpki.log.trace()
for parent in self.parents(gctx):
parent.serve_reissue(gctx)
@@ -537,11 +542,11 @@ class parent_elt(data_elt):
def serve_post_save_hook(self, gctx, q_pdu, r_pdu):
"""Extra server actions for parent_elt."""
- if self.rekey:
+ if q_pdu.rekey:
self.serve_rekey(gctx)
- if self.reissue:
+ if q_pdu.reissue:
self.serve_reissue(gctx)
- if self.revoke:
+ if q_pdu.revoke:
self.serve_revoke(gctx)
def serve_rekey(self, gctx):
diff --git a/scripts/rpki/log.py b/scripts/rpki/log.py
index aeb0e0d2..1f85f667 100644
--- a/scripts/rpki/log.py
+++ b/scripts/rpki/log.py
@@ -21,14 +21,17 @@ import syslog, traceback
enable_trace = False
-def init(ident = "rpki", flags = syslog.LOG_PID | syslog.LOG_PERROR, facility = syslog.LOG_DAEMON, trace = False):
+def init(ident = "rpki", flags = syslog.LOG_PID | syslog.LOG_PERROR, facility = syslog.LOG_DAEMON):
"""Initialize logging system."""
+ return syslog.openlog(ident, flags, facility)
+
+def set_trace(trace):
+ """Enable or disable call tracing."""
+
global enable_trace
enable_trace = trace
- return syslog.openlog(ident, flags, facility)
-
class logger(object):
"""Closure for logging."""
@@ -38,11 +41,11 @@ class logger(object):
def __call__(self, message):
return syslog.syslog(self.priority, message)
-error = logger(syslog.LOG_ERR)
-warning = logger(syslog.LOG_WARNING)
-notice = logger(syslog.LOG_NOTICE)
-info = logger(syslog.LOG_INFO)
-debug = logger(syslog.LOG_DEBUG)
+error = logger(syslog.LOG_ERR)
+warn = logger(syslog.LOG_WARNING)
+note = logger(syslog.LOG_NOTICE)
+info = logger(syslog.LOG_INFO)
+debug = logger(syslog.LOG_DEBUG)
def trace():
"""Execution trace -- where are we now, and whence came we here?"""
diff --git a/scripts/rpki/sql.py b/scripts/rpki/sql.py
index de18e1f1..92b4c48b 100644
--- a/scripts/rpki/sql.py
+++ b/scripts/rpki/sql.py
@@ -14,7 +14,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-import MySQLdb, time, traceback
+import MySQLdb, time
import rpki.x509, rpki.resource_set, rpki.sundial
def connect(cfg):
@@ -284,7 +284,7 @@ class ca_obj(sql_persistant):
rc_resources = rc.to_resource_bag()
cert_map = dict((c.cert.get_SKI(), c) for c in rc.certs)
- for ca_detail in ca_detail_obj.sql_fetch_where(gctx, "ca_id = %s AND latest_ca_cert IS NOT NULL", (self.ca_id,)):
+ for ca_detail in ca_detail_obj.sql_fetch_where(gctx, "ca_id = %s AND latest_ca_cert IS NOT NULL AND state != 'revoked'", (self.ca_id,)):
ski = ca_detail.latest_ca_cert.get_SKI()
if ca_detail.state in ("pending", "active"):
current_resources = ca_detail.latest_ca_cert.get_3779resources()
@@ -361,12 +361,6 @@ class ca_obj(sql_persistant):
def rekey(self, gctx):
"""Initiate a rekey operation for this ca.
- Noone who was at the meeting in Prague 2007 quite remembers why we
- used this name for this operation, but discussion months later
- concluded that it corresponds to the rollover operations in
- Geoff's "Common Management Tasks" document, so that's what this
- code does, with minor variations.
-
Tasks:
- Generate a new keypair.
@@ -376,27 +370,10 @@ class ca_obj(sql_persistant):
- Mark result as our active ca_detail.
- Reissue all child certs issued by this ca using the new ca_detail.
-
- - Schedule old ca_detail for removal. Geoff specifies a
- timer-based method, opinions vary on whether this is ok or we
- should instead just mark the old ca_detail as deprecated and
- leave it that way until we receive an explicit trigger from the
- IRBE.
-
- - Request revocation of old keypair by parent.
-
- - Revoke all certs (children, internal use certs like manifest,
- whatever) issued by the old keypair.
-
- - Generate a final CRL, signed with the old keypair, listing all
- the revoked certs, with a next CRL time after the last cert or
- CRL signed by the old keypair will have expired.
-
- - Destroy old keypair.
-
- - Leave final CRL in place until its next CRL time has passed.
"""
+ rpki.log.trace()
+
parent = self.parent(gctx)
old_detail = self.fetch_active(gctx)
new_detail = ca_detail_obj.create(gctx, self)
@@ -414,6 +391,8 @@ class ca_obj(sql_persistant):
def revoke(self, gctx):
"""Revoke deprecated ca_detail objects associated with this ca."""
+ rpki.log.trace()
+
for ca_detail in self.fetch_deprecated(gctx):
ca_detail.revoke(gctx)
@@ -516,6 +495,10 @@ class ca_detail_obj(sql_persistant):
if r_msg.payload.ski != self.latest_ca_cert.gSKI():
raise rpki.exceptions.SKIMismatch
+ ca = self.ca(gctx)
+ parent = ca.parent(gctx)
+ crl_interval = rpki.sundial.timedelta(seconds = parent.self(gctx).crl_interval)
+
nextUpdate = rpki.sundial.datetime.utcnow()
if self.latest_manifest is not None:
@@ -524,14 +507,14 @@ class ca_detail_obj(sql_persistant):
if self.latest_crl is not None:
nextUpdate = nextUpdate.later(self.latest_crl.getNextUpdate())
- for child_cert in self.chidl_certs(gctx):
+ for child_cert in self.child_certs(gctx):
nextUpdate = nextUpdate.later(child_cert.cert.getNotAfter())
child_cert.revoke()
- nextUpdate += rpki.sundial.timedelta(seconds = parent.self(gctx).crl_interval)
+ nextUpdate += crl_interval
- generate_crl(gctx, nextUpdate)
- generate_manifest(gctx, nextUpdate)
+ self.generate_crl(gctx, nextUpdate)
+ self.generate_manifest(gctx, nextUpdate)
self.private_key_id = None
self.manifest_private_key_id = None
diff --git a/scripts/rpki/x509.py b/scripts/rpki/x509.py
index 4d902351..c029e5f3 100644
--- a/scripts/rpki/x509.py
+++ b/scripts/rpki/x509.py
@@ -610,11 +610,11 @@ class SignedManifest(DER_object):
def getThisUpdate(self):
"""Get thisUpdate value from this manifest."""
- return rpki.sundial.datetime.fromGeneralizedTime(self.get_content())
+ return rpki.sundial.datetime.fromGeneralizedTime(self.get_content().thisUpdate.get())
def getNextUpdate(self):
"""Get nextUpdate value from this manifest."""
- return rpki.sundial.datetime.fromGeneralizedTime(self.get_content())
+ return rpki.sundial.datetime.fromGeneralizedTime(self.get_content().nextUpdate.get())
def verify(self, ta):
"""Verify this manifest."""
diff --git a/scripts/rpkid.py b/scripts/rpkid.py
index bf114c6e..5779753b 100755
--- a/scripts/rpkid.py
+++ b/scripts/rpkid.py
@@ -40,8 +40,8 @@ def left_right_handler(query, path):
rpki.sql.sql_sweep(gctx)
return 200, reply
except lxml.etree.DocumentInvalid:
- rpki.log.warning("Received reply document does not pass schema check: " + lxml.etree.tostring(r_elt, pretty_print = True))
- rpki.log.warning(traceback.format_exc())
+ rpki.log.warn("Received reply document does not pass schema check: " + lxml.etree.tostring(r_elt, pretty_print = True))
+ rpki.log.warn(traceback.format_exc())
return 500, "Schema violation"
except Exception, data:
rpki.log.error(traceback.format_exc())
diff --git a/scripts/testbed.1.yaml b/scripts/testbed.1.yaml
index 5d9efeae..acee42e2 100644
--- a/scripts/testbed.1.yaml
+++ b/scripts/testbed.1.yaml
@@ -24,6 +24,12 @@ kids:
ipv4: 192.0.2.1-192.0.2.33
asn: 64533
---
+- name: R0
+ rekey:
+---
+- name: R0
+ revoke:
+---
- name: Alice
valid_add: 10
---
diff --git a/scripts/testbed.py b/scripts/testbed.py
index 5dd3b4ad..a482c9b3 100644
--- a/scripts/testbed.py
+++ b/scripts/testbed.py
@@ -33,7 +33,7 @@ config_file contains settings for various implementation-specific
things that don't belong in yaml_script.
"""
-import os, yaml, MySQLdb, subprocess, signal, time, datetime, re, getopt, sys
+import os, yaml, MySQLdb, subprocess, signal, time, datetime, re, getopt, sys, lxml
import rpki.resource_set, rpki.sundial, rpki.x509, rpki.https, rpki.log, rpki.left_right, rpki.config
os.environ["TZ"] = "UTC"
@@ -264,7 +264,7 @@ def main():
rpki.log.info("Killing %s" % n)
os.kill(p.pid, signal.SIGTERM)
except Exception, data:
- rpki.log.warning("Couldn't clean up daemons (%s), continuing" % data)
+ rpki.log.warn("Couldn't clean up daemons (%s), continuing" % data)
class timedelta(datetime.timedelta):
"""Timedelta with text parsing. This accepts two input formats:
@@ -404,11 +404,33 @@ class allocation(object):
def apply_sub_as(self, text): self.base.as = self.base.as.difference(rpki.resource_set.resource_set_as(text))
def apply_sub_v4(self, text): self.base.v4 = self.base.v4.difference(rpki.resource_set.resource_set_ipv4(text))
def apply_sub_v6(self, text): self.base.v6 = self.base.v6.difference(rpki.resource_set.resource_set_ipv6(text))
+
def apply_valid_until(self, stamp): self.base.valid_until = stamp
def apply_valid_for(self, text): self.base.valid_until = datetime.datetime.utcnow() + timedelta.parse(text)
def apply_valid_add(self, text): self.base.valid_until += timedelta.parse(text)
def apply_valid_sub(self, text): self.base.valid_until -= timedelta.parse(text)
+ def apply_rekey(self, target):
+ 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)
+ self.call_rpkid(rpki.left_right.self_elt.make_pdu(action = "set", self_id = self.self_id, rekey = "yes"))
+ else:
+ rpki.log.info("Rekeying <parent/> %s %s" % (self.name, target))
+ self.call_rpkid(rpki.left_right.parent_elt.make_pdu(action = "set", self_id = self.self_id, parent_id = target, rekey = "yes"))
+
+ def apply_revoke(self, target):
+ 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"))
+ elif target is None:
+ rpki.log.info("Revoking <self/> %s" % self.name)
+ self.call_rpkid(rpki.left_right.self_elt.make_pdu(action = "set", self_id = self.self_id, revoke = "yes"))
+ else:
+ rpki.log.info("Revoking <parent/> %s %s" % (self.name, target))
+ self.call_rpkid(rpki.left_right.parent_elt.make_pdu(action = "set", self_id = self.self_id, parent_id = target, revoke = "yes"))
+
def __str__(self):
s = self.name + "\n"
if self.resources.as: s += " ASN: %s\n" % self.resources.as
@@ -516,6 +538,7 @@ class allocation(object):
pdu.type = "query"
elt = rpki.left_right.msg((pdu,)).toXML()
rpki.relaxng.left_right.assertValid(elt)
+ rpki.log.debug(lxml.etree.tostring(elt, pretty_print = True, encoding = "us-ascii"))
cms = rpki.cms.xml_sign(
elt = elt,
key = testbed_key,
@@ -530,6 +553,7 @@ class allocation(object):
msg = cms)
elt = rpki.cms.xml_verify(cms = cms, ta = self.rpkid_ta)
rpki.relaxng.left_right.assertValid(elt)
+ rpki.log.debug(lxml.etree.tostring(elt, pretty_print = True, encoding = "us-ascii"))
pdu = rpki.left_right.sax_handler.saxify(elt)[0]
assert pdu.type == "reply" and not isinstance(pdu, rpki.left_right.report_error_elt)
return pdu
diff --git a/scripts/testpoke.py b/scripts/testpoke.py
index 40fce102..3d23751b 100644
--- a/scripts/testpoke.py
+++ b/scripts/testpoke.py
@@ -26,7 +26,7 @@ Usage: python testpoke.py [ { -y | --yaml } configfile ]
Default configuration file is testpoke.yaml, override with --yaml option.
"""
-import traceback, os, time, getopt, sys, lxml, yaml
+import os, time, getopt, sys, lxml, yaml
import rpki.resource_set, rpki.up_down, rpki.left_right, rpki.x509
import rpki.https, rpki.config, rpki.cms, rpki.exceptions
import rpki.relaxng, rpki.oids