aboutsummaryrefslogtreecommitdiff
path: root/rpki/rpkidb/models.py
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-10-12 02:29:26 +0000
committerRob Austein <sra@hactrn.net>2015-10-12 02:29:26 +0000
commit0714a72bf29150d269e0dc45c2a868459dc5d023 (patch)
treeee45616b84ee7d7efe8718b3bfafdb795c63cc40 /rpki/rpkidb/models.py
parentc67ce5844729e3d2a96b020ed18c953e29d44f75 (diff)
Checkpoint while porting old create/set actions to ORM models.
svn path=/branches/tk705/; revision=6113
Diffstat (limited to 'rpki/rpkidb/models.py')
-rw-r--r--rpki/rpkidb/models.py174
1 files changed, 151 insertions, 23 deletions
diff --git a/rpki/rpkidb/models.py b/rpki/rpkidb/models.py
index 5ba743de..154d759b 100644
--- a/rpki/rpkidb/models.py
+++ b/rpki/rpkidb/models.py
@@ -50,12 +50,13 @@ class XMLTemplate(object):
signing_cert = rpki.x509.X509,
signing_cert_crl = rpki.x509.CRL)
- def __init__(self, name, attributes = (), booleans = (), elements = (), handles = ()):
+ def __init__(self, name, attributes = (), booleans = (), elements = (), readonly = (), handles = ()):
self.name = name
self.handles = handles
self.attributes = attributes
self.booleans = booleans
self.elements = elements
+ self.readonly = readonly
def encode(self, obj, r_msg):
"""
@@ -78,7 +79,7 @@ class XMLTemplate(object):
for k in self.booleans:
if getattr(obj, k):
r_pdu.set(k, "yes")
- for k in self.elements:
+ for k in self.elements + self.readonly:
v = getattr(obj, k)
if v is not None and not v.empty():
SubElement(r_pdu, rpki.left_right.xmlns + k).text = v.get_Base64()
@@ -188,6 +189,104 @@ class Self(models.Model):
booleans = ("use_hsm",),
elements = ("bpki_cert", "bpki_glue"))
+ def xml_pre_delete_hook(self):
+ raise NotImplementedError
+
+ def xml_pre_save_hook(self, q_pdu):
+ pass
+
+ def xml_post_save_hook(self, q_pdu, cb, eb):
+ actions = []
+ rekey = q_pdu.get("rekey")
+ revoke = q_pdu.get("revoke")
+ reissue = q_pdu.get("reissue")
+ revoke_forgotten = q_pdu.get("revoke_forgotten")
+ publish_world_now = q_pdu.get("publish_world_now")
+ run_now = q_pdu.get("run_now")
+ clear_replay_protection = q_pdu.get("clear_replay_protection")
+ if rekey or revoke or reissue or revoke_forgotten or clear_replay_protection:
+ for parent in self.parents.all():
+ if rekey:
+ actions.append(parent.serve_rekey)
+ if revoke:
+ actions.append(parent.serve_revoke)
+ if reissue:
+ actions.append(parent.serve_reissue)
+ if revoke_forgotten:
+ actions.append(parent.serve_revoke_forgotten)
+ if clear_replay_protection:
+ actions.append(parent.serve_clear_replay_protection)
+ if clear_replay_protection:
+ for child in self.children.all():
+ actions.append(child.serve_clear_replay_protection)
+ for repository in self.repositories.all():
+ actions.append(repository.serve_clear_replay_protection)
+ if publish_world_now:
+ actions.append(self.serve_publish_world_now)
+ if run_now:
+ actions.append(self.serve_run_now)
+ def loop(iterator, action):
+ action(iterator, eb)
+ rpki.async.iterator(actions, loop, cb)
+
+ def serve_publish_world_now(self, cb, eb):
+ publisher = rpki.rpkid.publication_queue()
+ repositories = set()
+ objects = dict()
+
+ def loop(iterator, parent):
+ repository = parent.repository
+ if repository.peer_contact_uri in repositories:
+ return iterator()
+ repositories.add(repository.peer_contact_uri)
+ q_msg = Element(rpki.publication.tag_msg, nsmap = rpki.publication.nsmap,
+ type = "query", version = rpki.publication.version)
+ SubElement(q_msg, rpki.publication.tag_list, tag = "list")
+ def list_handler(r_pdu):
+ rpki.publication.raise_if_error(r_pdu)
+ assert r_pdu.tag == rpki.publication.tag_list
+ assert r_pdu.get("uri") not in objects
+ objects[r_pdu.get("uri")] = (r_pdu.get("hash"), repository)
+ repository.call_pubd(iterator, eb, q_msg, length_check = False, handlers = dict(list = list_handler))
+
+ def reconcile(uri, obj, repository):
+ h, r = objects.pop(uri, (None, None))
+ if h is not None:
+ assert r == repository
+ publisher.queue(uri = uri, new_obj = obj, old_hash = h, repository = repository)
+
+ def done():
+ for parent in self.parents.all():
+ repository = parent.repository
+ for ca in parent.cas.all():
+ ca_detail = ca.active_ca_detail
+ if ca_detail is not None:
+ reconcile(uri = ca_detail.crl_uri, obj = ca_detail.latest_crl, repository = repository)
+ reconcile(uri = ca_detail.manifest_uri, obj = ca_detail.latest_manifest, repository = repository)
+ for c in ca_detail.child_certs.all():
+ reconcile(uri = c.uri, obj = c.cert, repository = repository)
+ for r in ca_detail.roas.all():
+ if r.roa is not None:
+ reconcile(uri = r.uri, obj = r.roa, repository = repository)
+ for g in ca_detail.ghostbusters.all():
+ reconcile(uri = g.uri, obj = g.ghostbuster, repository = repository)
+ for c in ca_detail.ee_certificates.all():
+ reconcile(uri = c.uri, obj = c.cert, repository = repository)
+ for u in objects:
+ h, r = objects[h]
+ publisher.queue(uri = u, old_hash = h, repository = r)
+ publisher.call_pubd(cb, eb)
+
+ rpki.async.iterator(self.parents.all(), loop, done)
+
+ def serve_run_now(self, cb, eb):
+ logger.debug("Forced immediate run of periodic actions for self %s[%d]", self.self_handle, self.self_id)
+ completion = rpki.rpkid_tasks.CompletionHandler(cb)
+ self.schedule_cron_tasks(completion)
+ assert completion.count > 0
+ self.gctx.task_run()
+
+
class BSC(models.Model):
bsc_handle = models.SlugField(max_length = 255)
private_key_id = KeyField()
@@ -195,7 +294,7 @@ class BSC(models.Model):
hash_alg = EnumField(choices = ("sha256",))
signing_cert = CertificateField(null = True)
signing_cert_crl = CRLField(null = True)
- self = models.ForeignKey(Self)
+ self = models.ForeignKey(Self, related_name = "bscs")
objects = XMLManager()
class Meta:
@@ -203,7 +302,22 @@ class BSC(models.Model):
xml_template = XMLTemplate(
name = "bsc",
- elements = ("signing_cert", "signing_cert_crl", "pkcs10_request"))
+ elements = ("signing_cert", "signing_cert_crl"),
+ readonly = ("pkcs10_request",))
+
+ def xml_pre_delete_hook(self):
+ pass
+
+ def xml_pre_save_hook(self, q_pdu):
+ # Handle key generation, only supports RSA with SHA-256 for now.
+ if q_pdu.get("generate_keypair"):
+ assert q_pdu.get("key_type") in (None, "rsa") and q_pdu.get("hash_alg") in (None, "sha256")
+ self.private_key_id = rpki.x509.RSA.generate(keylength = int(q_pdu.get("key_length", 2048)))
+ self.pkcs10_request = rpki.x509.PKCS10.create(keypair = self.private_key_id)
+
+ def xml_post_save_hook(self, q_pdu):
+ pass
+
class Repository(models.Model):
repository_handle = models.SlugField(max_length = 255)
@@ -211,8 +325,8 @@ class Repository(models.Model):
bpki_cert = CertificateField(null = True)
bpki_glue = CertificateField(null = True)
last_cms_timestamp = SundialField(null = True)
- bsc = models.ForeignKey(BSC)
- self = models.ForeignKey(Self)
+ bsc = models.ForeignKey(BSC, related_name = "repositories")
+ self = models.ForeignKey(Self, related_name = "repositories")
objects = XMLManager()
class Meta:
@@ -224,6 +338,10 @@ class Repository(models.Model):
attributes = ("peer_contact_uri",),
elements = ("bpki_cert", "bpki_glue"))
+ def xml_pre_delete_hook(self): raise NotImplementedError
+ def xml_pre_save_hook(self, q_pdu): raise NotImplementedError
+ def xml_post_save_hook(self, q_pdu): raise NotImplementedError
+
class Parent(models.Model):
parent_handle = models.SlugField(max_length = 255)
@@ -234,9 +352,9 @@ class Parent(models.Model):
sender_name = models.TextField(null = True)
recipient_name = models.TextField(null = True)
last_cms_timestamp = SundialField(null = True)
- self = models.ForeignKey(Self)
- bsc = models.ForeignKey(BSC)
- repository = models.ForeignKey(Repository)
+ self = models.ForeignKey(Self, related_name = "parents")
+ bsc = models.ForeignKey(BSC, related_name = "parents")
+ repository = models.ForeignKey(Repository, related_name = "parents")
objects = XMLManager()
class Meta:
@@ -248,6 +366,11 @@ class Parent(models.Model):
attributes = ("peer_contact_uri", "sia_base", "sender_name", "recipient_name"),
elements = ("bpki_cms_cert", "bpki_cms_glue"))
+ def xml_pre_delete_hook(self): raise NotImplementedError
+ def xml_pre_save_hook(self, q_pdu): raise NotImplementedError
+ def xml_post_save_hook(self, q_pdu): raise NotImplementedError
+
+
class CA(models.Model):
last_crl_sn = models.BigIntegerField()
last_manifest_sn = models.BigIntegerField()
@@ -256,7 +379,7 @@ class CA(models.Model):
last_issued_sn = models.BigIntegerField()
sia_uri = models.TextField(null = True)
parent_resource_class = models.TextField(null = True)
- parent = models.ForeignKey(Parent)
+ parent = models.ForeignKey(Parent, related_name = "cas")
class CADetail(models.Model):
public_key = KeyField(null = True)
@@ -271,15 +394,15 @@ class CADetail(models.Model):
manifest_published = SundialField(null = True)
state = EnumField(choices = ("pending", "active", "deprecated", "revoked"))
ca_cert_uri = models.TextField(null = True)
- ca = models.ForeignKey(CA)
+ ca = models.ForeignKey(CA, related_name = "ca_details")
class Child(models.Model):
child_handle = models.SlugField(max_length = 255)
bpki_cert = CertificateField(null = True)
bpki_glue = CertificateField(null = True)
last_cms_timestamp = SundialField(null = True)
- self = models.ForeignKey(Self)
- bsc = models.ForeignKey(BSC)
+ self = models.ForeignKey(Self, related_name = "children")
+ bsc = models.ForeignKey(BSC, related_name = "children")
objects = XMLManager()
class Meta:
@@ -290,45 +413,50 @@ class Child(models.Model):
handles = (BSC,),
elements = ("bpki_cert", "bpki_glue"))
+ def xml_pre_delete_hook(self): raise NotImplementedError
+ def xml_pre_save_hook(self, q_pdu): raise NotImplementedError
+ def xml_post_save_hook(self, q_pdu): raise NotImplementedError
+
+
class ChildCert(models.Model):
cert = CertificateField()
published = SundialField(null = True)
ski = BlobField()
- child = models.ForeignKey(Child)
- ca_detail = models.ForeignKey(CADetail)
+ child = models.ForeignKey(Child, related_name = "child_certs")
+ ca_detail = models.ForeignKey(CADetail, related_name = "child_certs")
class EECert(models.Model):
ski = BlobField()
cert = CertificateField()
published = SundialField(null = True)
- self = models.ForeignKey(Self)
- ca_detail = models.ForeignKey(CADetail)
+ self = models.ForeignKey(Self, related_name = "ee_certs")
+ ca_detail = models.ForeignKey(CADetail, related_name = "ee_certs")
class Ghostbuster(models.Model):
vcard = models.TextField()
cert = CertificateField()
ghostbuster = GhostbusterField()
published = SundialField(null = True)
- self = models.ForeignKey(Self)
- ca_detail = models.ForeignKey(CADetail)
+ self = models.ForeignKey(Self, related_name = "ghostbusters")
+ ca_detail = models.ForeignKey(CADetail, related_name = "ghostbusters")
class RevokedCert(models.Model):
serial = models.BigIntegerField()
revoked = SundialField()
expires = SundialField()
- ca_detail = models.ForeignKey(CADetail)
+ ca_detail = models.ForeignKey(CADetail, related_name = "revoked_certs")
class ROA(models.Model):
asn = models.BigIntegerField()
cert = CertificateField()
roa = ROAField()
published = SundialField(null = True)
- self = models.ForeignKey(Self)
- ca_detail = models.ForeignKey(CADetail)
+ self = models.ForeignKey(Self, related_name = "roas")
+ ca_detail = models.ForeignKey(CADetail, related_name = "roas")
class ROAPrefix(models.Model):
prefix = models.CharField(max_length = 40)
prefixlen = models.SmallIntegerField()
max_prefixlen = models.SmallIntegerField()
version = models.SmallIntegerField()
- roa = models.ForeignKey(ROA)
+ roa = models.ForeignKey(ROA, related_name = "roa_prefixes")