aboutsummaryrefslogtreecommitdiff
path: root/rpki/pubdb
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
committerRob Austein <sra@hactrn.net>2015-10-26 06:29:00 +0000
commitb46deb1417dc3596e9ac9fe2fe8cc0b7f42457e7 (patch)
treeca0dc0276d1adc168bc3337ce0564c4ec4957c1b /rpki/pubdb
parent397beaf6d9900dc3b3cb612c89ebf1d57b1d16f6 (diff)
"Any programmer who fails to comply with the standard naming, formatting,
or commenting conventions should be shot. If it so happens that it is inconvenient to shoot him, then he is to be politely requested to recode his program in adherence to the above standard." -- Michael Spier, Digital Equipment Corporation svn path=/branches/tk705/; revision=6152
Diffstat (limited to 'rpki/pubdb')
-rw-r--r--rpki/pubdb/models.py476
1 files changed, 238 insertions, 238 deletions
diff --git a/rpki/pubdb/models.py b/rpki/pubdb/models.py
index 2b6d67e4..46dcf493 100644
--- a/rpki/pubdb/models.py
+++ b/rpki/pubdb/models.py
@@ -48,266 +48,266 @@ rrdp_tag_withdraw = rrdp_xmlns + "withdraw"
# sure quite where to put it at the moment.
def DERSubElement(elt, name, der, attrib = None, **kwargs):
- """
- Convenience wrapper around SubElement for use with Base64 text.
- """
+ """
+ Convenience wrapper around SubElement for use with Base64 text.
+ """
- se = SubElement(elt, name, attrib, **kwargs)
- se.text = rpki.x509.base64_with_linebreaks(der)
- se.tail = "\n"
- return se
+ se = SubElement(elt, name, attrib, **kwargs)
+ se.text = rpki.x509.base64_with_linebreaks(der)
+ se.tail = "\n"
+ return se
class Client(models.Model):
- client_handle = models.CharField(unique = True, max_length = 255)
- base_uri = models.TextField()
- bpki_cert = CertificateField()
- bpki_glue = CertificateField(null = True)
- last_cms_timestamp = SundialField(blank = True, null = True)
+ client_handle = models.CharField(unique = True, max_length = 255)
+ base_uri = models.TextField()
+ bpki_cert = CertificateField()
+ bpki_glue = CertificateField(null = True)
+ last_cms_timestamp = SundialField(blank = True, null = True)
- def check_allowed_uri(self, uri):
- """
- Make sure that a target URI is within this client's allowed URI space.
- """
+ def check_allowed_uri(self, uri):
+ """
+ Make sure that a target URI is within this client's allowed URI space.
+ """
- if not uri.startswith(self.base_uri):
- raise rpki.exceptions.ForbiddenURI
+ if not uri.startswith(self.base_uri):
+ raise rpki.exceptions.ForbiddenURI
class Session(models.Model):
- uuid = models.CharField(unique = True, max_length=36)
- serial = models.BigIntegerField()
- snapshot = models.TextField(blank = True)
- hash = models.CharField(max_length = 64, blank = True)
-
- ## @var keep_all_rrdp_files
- # Debugging flag to prevent expiration of old RRDP files.
- # This simplifies debugging delta code. Need for this
- # may go away once RRDP is fully integrated into rcynic.
- keep_all_rrdp_files = False
-
- def new_delta(self, expires):
- """
- Construct a new delta associated with this session.
- """
+ uuid = models.CharField(unique = True, max_length=36)
+ serial = models.BigIntegerField()
+ snapshot = models.TextField(blank = True)
+ hash = models.CharField(max_length = 64, blank = True)
+
+ ## @var keep_all_rrdp_files
+ # Debugging flag to prevent expiration of old RRDP files.
+ # This simplifies debugging delta code. Need for this
+ # may go away once RRDP is fully integrated into rcynic.
+ keep_all_rrdp_files = False
+
+ def new_delta(self, expires):
+ """
+ Construct a new delta associated with this session.
+ """
+
+ delta = Delta(session = self,
+ serial = self.serial + 1,
+ expires = expires)
+ delta.elt = Element(rrdp_tag_delta,
+ nsmap = rrdp_nsmap,
+ version = rrdp_version,
+ session_id = self.uuid,
+ serial = str(delta.serial))
+ return delta
+
+
+ def expire_deltas(self):
+ """
+ Delete deltas whose expiration date has passed.
+ """
+
+ self.delta_set.filter(expires__lt = rpki.sundial.now()).delete()
+
+
+ def generate_snapshot(self):
+ """
+ Generate an XML snapshot of this session.
+ """
+
+ xml = Element(rrdp_tag_snapshot, nsmap = rrdp_nsmap,
+ version = rrdp_version,
+ session_id = self.uuid,
+ serial = str(self.serial))
+ xml.text = "\n"
+ for obj in self.publishedobject_set.all():
+ DERSubElement(xml, rrdp_tag_publish,
+ der = obj.der,
+ uri = obj.uri)
+ rpki.relaxng.rrdp.assertValid(xml)
+ self.snapshot = ElementToString(xml, pretty_print = True)
+ self.hash = rpki.x509.sha256(self.snapshot).encode("hex")
+ self.save()
+
+
+ @property
+ def snapshot_fn(self):
+ return "%s/snapshot/%s.xml" % (self.uuid, self.serial)
+
+
+ @property
+ def notification_fn(self):
+ return "notify.xml"
+
+
+ @staticmethod
+ def _write_rrdp_file(fn, text, rrdp_publication_base, overwrite = False):
+ if overwrite or not os.path.exists(os.path.join(rrdp_publication_base, fn)):
+ tn = os.path.join(rrdp_publication_base, fn + ".%s.tmp" % os.getpid())
+ if not os.path.isdir(os.path.dirname(tn)):
+ os.makedirs(os.path.dirname(tn))
+ with open(tn, "w") as f:
+ f.write(text)
+ os.rename(tn, os.path.join(rrdp_publication_base, fn))
+
+
+ @staticmethod
+ def _rrdp_filename_to_uri(fn, rrdp_uri_base):
+ return "%s/%s" % (rrdp_uri_base.rstrip("/"), fn)
+
+
+ def _generate_update_xml(self, rrdp_uri_base):
+ xml = Element(rrdp_tag_notification, nsmap = rrdp_nsmap,
+ version = rrdp_version,
+ session_id = self.uuid,
+ serial = str(self.serial))
+ SubElement(xml, rrdp_tag_snapshot,
+ uri = self._rrdp_filename_to_uri(self.snapshot_fn, rrdp_uri_base),
+ hash = self.hash)
+ for delta in self.delta_set.all():
+ SubElement(xml, rrdp_tag_delta,
+ uri = self._rrdp_filename_to_uri(delta.fn, rrdp_uri_base),
+ hash = delta.hash,
+ serial = str(delta.serial))
+ rpki.relaxng.rrdp.assertValid(xml)
+ return ElementToString(xml, pretty_print = True)
+
+
+ def synchronize_rrdp_files(self, rrdp_publication_base, rrdp_uri_base):
+ """
+ Write current RRDP files to disk, clean up old files and directories.
+ """
+
+ current_filenames = set()
+
+ for delta in self.delta_set.all():
+ self._write_rrdp_file(delta.fn, delta.xml, rrdp_publication_base)
+ current_filenames.add(delta.fn)
+
+ self._write_rrdp_file(self.snapshot_fn, self.snapshot, rrdp_publication_base)
+ current_filenames.add(self.snapshot_fn)
+
+ self._write_rrdp_file(self.notification_fn, self._generate_update_xml(rrdp_uri_base),
+ rrdp_publication_base, overwrite = True)
+ current_filenames.add(self.notification_fn)
+
+ if not self.keep_all_rrdp_files:
+ for root, dirs, files in os.walk(rrdp_publication_base, topdown = False):
+ for fn in files:
+ fn = os.path.join(root, fn)
+ if fn[len(rrdp_publication_base):].lstrip("/") not in current_filenames:
+ os.remove(fn)
+ for dn in dirs:
+ try:
+ os.rmdir(os.path.join(root, dn))
+ except OSError:
+ pass
- delta = Delta(session = self,
- serial = self.serial + 1,
- expires = expires)
- delta.elt = Element(rrdp_tag_delta,
- nsmap = rrdp_nsmap,
- version = rrdp_version,
- session_id = self.uuid,
- serial = str(delta.serial))
- return delta
+class Delta(models.Model):
+ serial = models.BigIntegerField()
+ xml = models.TextField()
+ hash = models.CharField(max_length = 64)
+ expires = SundialField()
+ session = models.ForeignKey(Session)
- def expire_deltas(self):
- """
- Delete deltas whose expiration date has passed.
- """
- self.delta_set.filter(expires__lt = rpki.sundial.now()).delete()
+ @staticmethod
+ def _uri_to_filename(uri, publication_base):
+ if not uri.startswith("rsync://"):
+ raise rpki.exceptions.BadURISyntax(uri)
+ path = uri.split("/")[4:]
+ path.insert(0, publication_base.rstrip("/"))
+ filename = "/".join(path)
+ if "/../" in filename or filename.endswith("/.."):
+ raise rpki.exceptions.BadURISyntax(filename)
+ return filename
- def generate_snapshot(self):
- """
- Generate an XML snapshot of this session.
- """
+ @property
+ def fn(self):
+ return "%s/deltas/%s.xml" % (self.session.uuid, self.serial)
- xml = Element(rrdp_tag_snapshot, nsmap = rrdp_nsmap,
- version = rrdp_version,
- session_id = self.uuid,
- serial = str(self.serial))
- xml.text = "\n"
- for obj in self.publishedobject_set.all():
- DERSubElement(xml, rrdp_tag_publish,
- der = obj.der,
- uri = obj.uri)
- rpki.relaxng.rrdp.assertValid(xml)
- self.snapshot = ElementToString(xml, pretty_print = True)
- self.hash = rpki.x509.sha256(self.snapshot).encode("hex")
- self.save()
-
-
- @property
- def snapshot_fn(self):
- return "%s/snapshot/%s.xml" % (self.uuid, self.serial)
-
-
- @property
- def notification_fn(self):
- return "notify.xml"
-
-
- @staticmethod
- def _write_rrdp_file(fn, text, rrdp_publication_base, overwrite = False):
- if overwrite or not os.path.exists(os.path.join(rrdp_publication_base, fn)):
- tn = os.path.join(rrdp_publication_base, fn + ".%s.tmp" % os.getpid())
- if not os.path.isdir(os.path.dirname(tn)):
- os.makedirs(os.path.dirname(tn))
- with open(tn, "w") as f:
- f.write(text)
- os.rename(tn, os.path.join(rrdp_publication_base, fn))
-
-
- @staticmethod
- def _rrdp_filename_to_uri(fn, rrdp_uri_base):
- return "%s/%s" % (rrdp_uri_base.rstrip("/"), fn)
-
-
- def _generate_update_xml(self, rrdp_uri_base):
- xml = Element(rrdp_tag_notification, nsmap = rrdp_nsmap,
- version = rrdp_version,
- session_id = self.uuid,
- serial = str(self.serial))
- SubElement(xml, rrdp_tag_snapshot,
- uri = self._rrdp_filename_to_uri(self.snapshot_fn, rrdp_uri_base),
- hash = self.hash)
- for delta in self.delta_set.all():
- SubElement(xml, rrdp_tag_delta,
- uri = self._rrdp_filename_to_uri(delta.fn, rrdp_uri_base),
- hash = delta.hash,
- serial = str(delta.serial))
- rpki.relaxng.rrdp.assertValid(xml)
- return ElementToString(xml, pretty_print = True)
-
-
- def synchronize_rrdp_files(self, rrdp_publication_base, rrdp_uri_base):
- """
- Write current RRDP files to disk, clean up old files and directories.
- """
- current_filenames = set()
-
- for delta in self.delta_set.all():
- self._write_rrdp_file(delta.fn, delta.xml, rrdp_publication_base)
- current_filenames.add(delta.fn)
-
- self._write_rrdp_file(self.snapshot_fn, self.snapshot, rrdp_publication_base)
- current_filenames.add(self.snapshot_fn)
-
- self._write_rrdp_file(self.notification_fn, self._generate_update_xml(rrdp_uri_base),
- rrdp_publication_base, overwrite = True)
- current_filenames.add(self.notification_fn)
-
- if not self.keep_all_rrdp_files:
- for root, dirs, files in os.walk(rrdp_publication_base, topdown = False):
- for fn in files:
- fn = os.path.join(root, fn)
- if fn[len(rrdp_publication_base):].lstrip("/") not in current_filenames:
- os.remove(fn)
- for dn in dirs:
- try:
- os.rmdir(os.path.join(root, dn))
- except OSError:
- pass
+ def activate(self):
+ rpki.relaxng.rrdp.assertValid(self.elt)
+ self.xml = ElementToString(self.elt, pretty_print = True)
+ self.hash = rpki.x509.sha256(self.xml).encode("hex")
+ self.save()
+ self.session.serial += 1
+ self.session.save()
-class Delta(models.Model):
- serial = models.BigIntegerField()
- xml = models.TextField()
- hash = models.CharField(max_length = 64)
- expires = SundialField()
- session = models.ForeignKey(Session)
-
-
- @staticmethod
- def _uri_to_filename(uri, publication_base):
- if not uri.startswith("rsync://"):
- raise rpki.exceptions.BadURISyntax(uri)
- path = uri.split("/")[4:]
- path.insert(0, publication_base.rstrip("/"))
- filename = "/".join(path)
- if "/../" in filename or filename.endswith("/.."):
- raise rpki.exceptions.BadURISyntax(filename)
- return filename
-
-
- @property
- def fn(self):
- return "%s/deltas/%s.xml" % (self.session.uuid, self.serial)
-
-
- def activate(self):
- rpki.relaxng.rrdp.assertValid(self.elt)
- self.xml = ElementToString(self.elt, pretty_print = True)
- self.hash = rpki.x509.sha256(self.xml).encode("hex")
- self.save()
- self.session.serial += 1
- self.session.save()
-
-
- def publish(self, client, der, uri, obj_hash):
- try:
- obj = client.publishedobject_set.get(session = self.session, uri = uri)
- if obj.hash == obj_hash:
- obj.delete()
- elif obj_hash is None:
- raise rpki.exceptions.ExistingObjectAtURI("Object already published at %s" % uri)
- else:
- raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash))
- except rpki.pubdb.models.PublishedObject.DoesNotExist:
- pass
- logger.debug("Publishing %s", uri)
- PublishedObject.objects.create(session = self.session, client = client, der = der, uri = uri,
- hash = rpki.x509.sha256(der).encode("hex"))
- se = DERSubElement(self.elt, rrdp_tag_publish, der = der, uri = uri)
- if obj_hash is not None:
- se.set("hash", obj_hash)
- rpki.relaxng.rrdp.assertValid(self.elt)
-
-
- def withdraw(self, client, uri, obj_hash):
- obj = client.publishedobject_set.get(session = self.session, uri = uri)
- if obj.hash != obj_hash:
- raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash))
- logger.debug("Withdrawing %s", uri)
- obj.delete()
- SubElement(self.elt, rrdp_tag_withdraw, uri = uri, hash = obj_hash).tail = "\n"
- rpki.relaxng.rrdp.assertValid(self.elt)
-
-
- def update_rsync_files(self, publication_base):
- from errno import ENOENT
- min_path_len = len(publication_base.rstrip("/"))
- for pdu in self.elt:
- assert pdu.tag in (rrdp_tag_publish, rrdp_tag_withdraw)
- fn = self._uri_to_filename(pdu.get("uri"), publication_base)
- if pdu.tag == rrdp_tag_publish:
- tn = fn + ".tmp"
- dn = os.path.dirname(fn)
- if not os.path.isdir(dn):
- os.makedirs(dn)
- with open(tn, "wb") as f:
- f.write(pdu.text.decode("base64"))
- os.rename(tn, fn)
- else:
+ def publish(self, client, der, uri, obj_hash):
try:
- os.remove(fn)
- except OSError, e:
- if e.errno != ENOENT:
- raise
- dn = os.path.dirname(fn)
- while len(dn) > min_path_len:
- try:
- os.rmdir(dn)
- except OSError:
- break
- else:
- dn = os.path.dirname(dn)
- del self.elt
+ obj = client.publishedobject_set.get(session = self.session, uri = uri)
+ if obj.hash == obj_hash:
+ obj.delete()
+ elif obj_hash is None:
+ raise rpki.exceptions.ExistingObjectAtURI("Object already published at %s" % uri)
+ else:
+ raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash))
+ except rpki.pubdb.models.PublishedObject.DoesNotExist:
+ pass
+ logger.debug("Publishing %s", uri)
+ PublishedObject.objects.create(session = self.session, client = client, der = der, uri = uri,
+ hash = rpki.x509.sha256(der).encode("hex"))
+ se = DERSubElement(self.elt, rrdp_tag_publish, der = der, uri = uri)
+ if obj_hash is not None:
+ se.set("hash", obj_hash)
+ rpki.relaxng.rrdp.assertValid(self.elt)
+
+
+ def withdraw(self, client, uri, obj_hash):
+ obj = client.publishedobject_set.get(session = self.session, uri = uri)
+ if obj.hash != obj_hash:
+ raise rpki.exceptions.DifferentObjectAtURI("Found different object at %s (old %s, new %s)" % (uri, obj.hash, obj_hash))
+ logger.debug("Withdrawing %s", uri)
+ obj.delete()
+ SubElement(self.elt, rrdp_tag_withdraw, uri = uri, hash = obj_hash).tail = "\n"
+ rpki.relaxng.rrdp.assertValid(self.elt)
+
+
+ def update_rsync_files(self, publication_base):
+ from errno import ENOENT
+ min_path_len = len(publication_base.rstrip("/"))
+ for pdu in self.elt:
+ assert pdu.tag in (rrdp_tag_publish, rrdp_tag_withdraw)
+ fn = self._uri_to_filename(pdu.get("uri"), publication_base)
+ if pdu.tag == rrdp_tag_publish:
+ tn = fn + ".tmp"
+ dn = os.path.dirname(fn)
+ if not os.path.isdir(dn):
+ os.makedirs(dn)
+ with open(tn, "wb") as f:
+ f.write(pdu.text.decode("base64"))
+ os.rename(tn, fn)
+ else:
+ try:
+ os.remove(fn)
+ except OSError, e:
+ if e.errno != ENOENT:
+ raise
+ dn = os.path.dirname(fn)
+ while len(dn) > min_path_len:
+ try:
+ os.rmdir(dn)
+ except OSError:
+ break
+ else:
+ dn = os.path.dirname(dn)
+ del self.elt
class PublishedObject(models.Model):
- uri = models.CharField(max_length = 255)
- der = models.BinaryField()
- hash = models.CharField(max_length = 64)
- client = models.ForeignKey(Client)
- session = models.ForeignKey(Session)
-
- class Meta: # pylint: disable=C1001,W0232
- unique_together = (("session", "hash"),
- ("session", "uri"))
+ uri = models.CharField(max_length = 255)
+ der = models.BinaryField()
+ hash = models.CharField(max_length = 64)
+ client = models.ForeignKey(Client)
+ session = models.ForeignKey(Session)
+
+ class Meta: # pylint: disable=C1001,W0232
+ unique_together = (("session", "hash"),
+ ("session", "uri"))