diff options
author | Rob Austein <sra@hactrn.net> | 2015-10-12 02:29:26 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-10-12 02:29:26 +0000 |
commit | 0714a72bf29150d269e0dc45c2a868459dc5d023 (patch) | |
tree | ee45616b84ee7d7efe8718b3bfafdb795c63cc40 /rpki/rpkidb/models.py | |
parent | c67ce5844729e3d2a96b020ed18c953e29d44f75 (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.py | 174 |
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") |