diff options
author | Rob Austein <sra@hactrn.net> | 2015-10-11 21:01:18 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-10-11 21:01:18 +0000 |
commit | c67ce5844729e3d2a96b020ed18c953e29d44f75 (patch) | |
tree | 714a2ec68359d552bf1c80d9dfc9f6cf5899a5fe /rpki | |
parent | 79bf6b0c42fd6e19cf215cc44137650b976e070e (diff) |
Checkpoint updated XML code.
svn path=/branches/tk705/; revision=6112
Diffstat (limited to 'rpki')
-rw-r--r-- | rpki/rpkid.py | 37 | ||||
-rw-r--r-- | rpki/rpkidb/models.py | 141 |
2 files changed, 124 insertions, 54 deletions
diff --git a/rpki/rpkid.py b/rpki/rpkid.py index ddc04bd0..a5c0ddd7 100644 --- a/rpki/rpkid.py +++ b/rpki/rpkid.py @@ -387,7 +387,8 @@ class main(object): type = "reply", version = rpki.left_right.version) self.irbe_cms_timestamp = q_cms.check_replay(self.irbe_cms_timestamp, path) - assert q_msg.tag.startswith(rpki.left_right.xmlns) and all(q_pdu.tag.startswith(rpki.left_right.xmlns) for q_pdu in q_msg) + assert q_msg.tag.startswith(rpki.left_right.xmlns) + assert all(q_pdu.tag.startswith(rpki.left_right.xmlns) for q_pdu in q_msg) if q_msg.get("version") != rpki.left_right.version: raise rpki.exceptions.BadQuery("Unrecognized protocol version") @@ -404,7 +405,6 @@ class main(object): def fail(e): if not isinstance(e, rpki.exceptions.NotFound): logger.exception("Unhandled exception serving left-right PDU %r", q_pdu) - # Compatability kludge if isinstance(q_pdu, rpki.left_right.base_elt): error_self_handle = q_pdu.self_handle @@ -412,23 +412,21 @@ class main(object): else: error_self_handle = q_pdu.get("self_handle") error_tag = q_pdu.get("tag") - r_pdu = SubElement(r_msg, rpki.left_right.tag_report_error, error_code = e.__class__.__name__) r_pdu.text = str(e) if error_tag is not None: r_pdu.set("tag", error_tag) if error_self_handle is not None: r_pdu.set("self_handle", error_self_handle) - self.sql.sweep() - cb(200, body = rpki.left_right.cms_msg().wrap(r_msg, self.rpkid_key, self.rpkid_cert)) try: if q_pdu.tag in self.left_right_trivial_handlers: self.left_right_trivial_handlers[q_pdu.tag](q_pdu, r_msg) iterator() - else: + + elif True: # Old-style handlers q_map = { rpki.left_right.tag_self : rpki.left_right.self_elt, rpki.left_right.tag_bsc : rpki.left_right.bsc_elt, rpki.left_right.tag_parent : rpki.left_right.parent_elt, @@ -437,6 +435,33 @@ class main(object): q_pdu = q_map[q_pdu.tag].fromXML(q_pdu) q_pdu.gctx = self q_pdu.serve_dispatch(r_msg, iterator, fail) + + else: # New-style handlers + + # This will all need to go under an @atomic or equivalent + # with statement, just not quite sure where to put it yet. + + action = q_pdu.get("action") + model = self.left_right_models[q_pdu.tag] + + if action in ("get", "list"): + for obj in model.objects.xml_list(q_pdu): + obj.xml_template.encode(obj, r_msg) + + elif action == "destroy": + model.objects.xml_get_for_delete(q_pdu).delete() + obj.xml_template.acknowledge(obj, q_pdu, r_msg) + + else: + assert action in ("create", "set") + obj = model.objects.xml_get_or_create(q_pdu) + obj.xml_template.decode(obj, q_pdu) + + # Handle special actions here. + + obj.save() + obj.xml_template.acknowledge(obj, q_pdu, r_msg) + except (rpki.async.ExitNow, SystemExit): raise except Exception, e: diff --git a/rpki/rpkidb/models.py b/rpki/rpkidb/models.py index 8963c1ef..5ba743de 100644 --- a/rpki/rpkidb/models.py +++ b/rpki/rpkidb/models.py @@ -56,79 +56,120 @@ class XMLTemplate(object): self.attributes = attributes self.booleans = booleans self.elements = elements - - def encode(self, obj): + + def encode(self, obj, r_msg): """ Encode an ORM object as XML. """ - xml = Element(rpki.left_right.xmlns + self.name, nsmap = rpki.left_right.nsmap) - xml.set(self.name + "_handle", getattr(obj, self.name + "_handle")) - for k in self.handles: - v = getattr(obj, k.xml.name) + r_pdu = SubElement(r_msg, rpki.left_right.xmlns + self.name, nsmap = rpki.left_right.nsmap) + r_pdu.set(self.name + "_handle", getattr(obj, self.name + "_handle")) + if self.name != "self": + r_pdu.set("self_handle", getattr(obj, "self_handle")) + for h in self.handles: + k = h.xml_template.name + v = getattr(obj, k) if v is not None: - xml.set(k.xml.name + "_handle", getattr(v, k.xml.name + "_handle")) + r_pdu.set(k + "_handle", getattr(v, k + "_handle")) for k in self.attributes: v = getattr(obj, k) if v is not None: - xml.set(k, str(v)) + r_pdu.set(k, str(v)) for k in self.booleans: if getattr(obj, k): - xml.set(k, "yes") + r_pdu.set(k, "yes") for k in self.elements: v = getattr(obj, k) if v is not None and not v.empty(): - SubElement(xml, rpki.left_right.xmlns + k).text = v.get_Base64() - return xml + SubElement(r_pdu, rpki.left_right.xmlns + k).text = v.get_Base64() + + def acknowledge(self, obj, q_pdu, r_msg): + """ + Add an acknowledgement PDU in response to a create, set, or + destroy action. - def decode(self, obj, xml): + This includes a bit of special-case code for BSC objects which has + to go somewhere; we could handle it via some kind method of + call-out to the BSC model, but it's not worth building a general + mechanism for one case, so we do it inline and have done. + """ + + assert q_pdu.tag == rpki.left_right.xmlns + self.name + r_pdu = SubElement(r_msg, rpki.left_right.xmlns + self.name, nsmap = rpki.left_right.nsmap) + r_pdu.set(self.name + "_handle", getattr(obj, self.name + "_handle")) + if self.name != "self": + r_pdu.set("self_handle", getattr(obj, "self_handle")) + if self.name == "bsc" and q_pdu.get("action") != "destroy" and obj.pkcs11_request is not None: + assert not obj.pkcs11_request.empty() + SubElement(r_pdu, rpki.left_right.xmlns + "pkcs11_request").text = obj.pkcs11_request.get_Base64() + + def decode(self, obj, q_pdu): """ Decode XML into an ORM object. """ - assert xml.tag == rpki.left_right.xmlns + self.name - setattr(obj, self.name + "_handle", xml.get(self.name + "_handle")) - for k in self.handles: - v = xml.get(k.xml.name + "_handle") + assert q_pdu.tag == rpki.left_right.xmlns + self.name + for h in self.handles: + k = h.xml_template.name + v = q_pdu.get(k + "_handle") if v is not None: - d = { k.xml.name + "_handle" : v } - if k.xml.name != "self": - d.update(self = obj.self) - setattr(obj, k.xml.name, k.objects.get(**d)) + setattr(obj, k, h.objects.get(**{k + "_handle" : v, "self" : obj.self})) for k in self.attributes: - v = xml.get(k) + v = q_pdu.get(k) if v is not None: v.encode("ascii") if v.isdigit(): v = long(v) setattr(obj, k, v) for k in self.booleans: - v = xml.get(k) + v = q_pdu.get(k) if v is not None: setattr(obj, k, v == "yes") for k in self.elements: - v = xml.findtext(rpki.left_right.xmlns + k) + v = q_pdu.findtext(rpki.left_right.xmlns + k) if v and v.strip(): setattr(obj, k, self.element_type[k](Base64 = v)) class XMLManager(models.Manager): """ - Add a .xml_find() method which looks up the object corresponding to - the handles in an XML element. + Add a few methods which locate or create an object or objects + corresponding to the handles in an XML element, as appropriate. This assumes that models which use it have an "xml" class attribute holding an XMLTemplate object (above). """ - def xml_find(self, xml): - name = self.model.xml.name - assert xml.tag == rpki.left_right.xmlns + name + def xml_get_or_create(self, xml): + name = self.model.xml_template.name + action = xml.get("action") + assert xml.tag == rpki.left_right.xmlns + name and action in ("create", "set") d = { name + "_handle" : xml.get(name + "_handle") } + if name != "self" and action == "create": + d["self"] = Self.objects.get(self_handle = xml.get("self_handle")) + elif name != "self": + d["self__self_handle"] = xml.get("self_handle") + return self.model(**d) if action == "create" else self.get(**d) + + def xml_list(self, xml): + name = self.model.xml_template.name + action = xml.get("action") + assert xml.tag == rpki.left_right.xmlns + name and action in ("get", "list") + d = {} + if action == "get": + d[name + "_handle"] = xml.get(name + "_handle") if name != "self": - d.update(self__self_handle = xml.get("self_handle")) - return self.get(**d) + d["self__self_handle"] = xml.get("self_handle") + return self.filter(**d) if d else self.all() + def xml_get_for_delete(self, xml): + name = self.model.xml_template.name + action = xml.get("action") + assert xml.tag == rpki.left_right.xmlns + name and action == "destroy" + d = { name + "_handle" : xml.get(name + "_handle") } + if name != "self": + d["self__self_handle"] = xml.get("self_handle") + return self.get(**d) # Models @@ -141,10 +182,11 @@ class Self(models.Model): bpki_glue = CertificateField(null = True) objects = XMLManager() - xml = XMLTemplate(name = "self", - attributes = ("crl_interval", "regen_margin"), - booleans = ("use_hsm",), - elements = ("bpki_cert", "bpki_glue")) + xml_template = XMLTemplate( + name = "self", + attributes = ("crl_interval", "regen_margin"), + booleans = ("use_hsm",), + elements = ("bpki_cert", "bpki_glue")) class BSC(models.Model): bsc_handle = models.SlugField(max_length = 255) @@ -159,9 +201,9 @@ class BSC(models.Model): class Meta: unique_together = ("self", "bsc_handle") - xml = XMLTemplate(name = "bsc", - handles = (Self,), - elements = ("signing_cert", "signing_cert_crl", "pkcs10_request")) + xml_template = XMLTemplate( + name = "bsc", + elements = ("signing_cert", "signing_cert_crl", "pkcs10_request")) class Repository(models.Model): repository_handle = models.SlugField(max_length = 255) @@ -176,10 +218,11 @@ class Repository(models.Model): class Meta: unique_together = ("self", "repository_handle") - xml = XMLTemplate(name = "repository", - handles = (Self, BSC), - attributes = ("peer_contact_uri",), - elements = ("bpki_cert", "bpki_glue")) + xml_template = XMLTemplate( + name = "repository", + handles = (BSC,), + attributes = ("peer_contact_uri",), + elements = ("bpki_cert", "bpki_glue")) class Parent(models.Model): @@ -199,10 +242,11 @@ class Parent(models.Model): class Meta: unique_together = ("self", "parent_handle") - xml = XMLTemplate(name = "parent", - handles = (Self, BSC, Repository), - attributes = ("peer_contact_uri", "sia_base", "sender_name", "recipient_name"), - elements = ("bpki_cms_cert", "bpki_cms_glue")) + xml_template = XMLTemplate( + name = "parent", + handles = (BSC, Repository), + attributes = ("peer_contact_uri", "sia_base", "sender_name", "recipient_name"), + elements = ("bpki_cms_cert", "bpki_cms_glue")) class CA(models.Model): last_crl_sn = models.BigIntegerField() @@ -241,9 +285,10 @@ class Child(models.Model): class Meta: unique_together = ("self", "child_handle") - xml = XMLTemplate(name = "child", - handles = (Self, BSC), - elements = ("bpki_cert", "bpki_glue")) + xml_template = XMLTemplate( + name = "child", + handles = (BSC,), + elements = ("bpki_cert", "bpki_glue")) class ChildCert(models.Model): cert = CertificateField() |