aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/gui/cacheview/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki/gui/cacheview/models.py')
-rw-r--r--rpkid/rpki/gui/cacheview/models.py203
1 files changed, 94 insertions, 109 deletions
diff --git a/rpkid/rpki/gui/cacheview/models.py b/rpkid/rpki/gui/cacheview/models.py
index 077a28ff..4be45b5c 100644
--- a/rpkid/rpki/gui/cacheview/models.py
+++ b/rpkid/rpki/gui/cacheview/models.py
@@ -1,106 +1,87 @@
-"""
-Copyright (C) 2011 SPARTA, Inc. dba Cobham Analytic Solutions
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-"""
+# Copyright (C) 2011 SPARTA, Inc. dba Cobham Analytic Solutions
+# Copyright (C) 2012 SPARTA, Inc. a Parsons Company
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND SPARTA DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL SPARTA BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+__version__ = '$Id$'
from datetime import datetime
import time
from django.db import models
-from rpki.resource_set import resource_range_ipv4, resource_range_ipv6
-from rpki.exceptions import MustBePrefix
+import rpki.ipaddrs
+import rpki.resource_set
+import rpki.gui.models
+
class TelephoneField(models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 255
models.CharField.__init__(self, *args, **kwargs)
-class AddressRange(models.Model):
- family = models.IntegerField()
- min = models.IPAddressField(db_index=True)
- max = models.IPAddressField(db_index=True)
-
- class Meta:
- ordering = ('family', 'min', 'max')
- unique_together = ('family', 'min', 'max')
+class AddressRange(rpki.gui.models.PrefixV4):
@models.permalink
def get_absolute_url(self):
return ('rpki.gui.cacheview.views.addressrange_detail', [str(self.pk)])
- def __unicode__(self):
- if self.min == self.max:
- return u'%s' % self.min
-
- if self.family == 4:
- r = resource_range_ipv4.from_strings(self.min, self.max)
- elif self.family == 6:
- r = resource_range_ipv6.from_strings(self.min, self.max)
-
- try:
- prefixlen = r.prefixlen()
- except MustBePrefix:
- return u'%s-%s' % (self.min, self.max)
- return u'%s/%d' % (self.min, prefixlen)
-class ASRange(models.Model):
- min = models.PositiveIntegerField(db_index=True)
- max = models.PositiveIntegerField(db_index=True)
-
- class Meta:
- ordering = ('min', 'max')
- #unique_together = ('min', 'max')
+class AddressRangeV6(rpki.gui.models.PrefixV6):
+ @models.permalink
+ def get_absolute_url(self):
+ return ('rpki.gui.cacheview.views.addressrange_detail_v6',
+ [str(self.pk)])
- def __unicode__(self):
- if self.min == self.max:
- return u'AS%d' % self.min
- else:
- return u'AS%s-%s' % (self.min, self.max)
+class ASRange(rpki.gui.models.ASN):
@models.permalink
def get_absolute_url(self):
return ('rpki.gui.cacheview.views.asrange_detail', [str(self.pk)])
kinds = list(enumerate(('good', 'warn', 'bad')))
-kinds_dict = dict((v,k) for k,v in kinds)
+kinds_dict = dict((v, k) for k, v in kinds)
+
class ValidationLabel(models.Model):
"""
Represents a specific error condition defined in the rcynic XML
output file.
"""
- label = models.CharField(max_length=30, db_index=True, unique=True)
+ label = models.CharField(max_length=79, db_index=True, unique=True)
status = models.CharField(max_length=255)
kind = models.PositiveSmallIntegerField(choices=kinds)
def __unicode__(self):
return self.label
- class Meta:
- verbose_name_plural = 'ValidationLabels'
+
+class RepositoryObject(models.Model):
+ """
+ Represents a globally unique RPKI repository object, specified by its URI.
+ """
+ uri = models.URLField(unique=True, db_index=True)
generations = list(enumerate(('current', 'backup')))
generations_dict = dict((val, key) for (key, val) in generations)
+
class ValidationStatus(models.Model):
- timestamp = models.DateTimeField()
+ timestamp = models.DateTimeField()
generation = models.PositiveSmallIntegerField(choices=generations, null=True)
- status = models.ForeignKey('ValidationLabel')
+ status = models.ForeignKey(ValidationLabel)
+ repo = models.ForeignKey(RepositoryObject, related_name='statuses')
- class Meta:
- abstract = True
class SignedObject(models.Model):
"""
@@ -108,24 +89,20 @@ class SignedObject(models.Model):
The signing certificate is ommitted here in order to give a proper
value for the 'related_name' attribute.
"""
- # attributes from rcynic's output XML file
- uri = models.URLField(unique=True, db_index=True)
+ repo = models.ForeignKey(RepositoryObject, related_name='cert', unique=True)
# on-disk file modification time
- mtime = models.PositiveIntegerField(default=0)
+ mtime = models.PositiveIntegerField(default=0)
# SubjectName
- name = models.CharField(max_length=255)
+ name = models.CharField(max_length=255)
# value from the SKI extension
- keyid = models.CharField(max_length=50, db_index=True)
+ keyid = models.CharField(max_length=60, db_index=True)
# validity period from EE cert which signed object
not_before = models.DateTimeField()
- not_after = models.DateTimeField()
-
- class Meta:
- abstract = True
+ not_after = models.DateTimeField()
def mtime_as_datetime(self):
"""
@@ -133,13 +110,6 @@ class SignedObject(models.Model):
"""
return datetime.utcfromtimestamp(self.mtime + time.timezone)
- def is_valid(self):
- """
- Returns a boolean value indicating whether this object has passed
- validation checks.
- """
- return bool(self.statuses.filter(status=ValidationLabel.objects.get(label="object_accepted")))
-
def status_id(self):
"""
Returns a HTML class selector for the current object based on its validation status.
@@ -149,70 +119,90 @@ class SignedObject(models.Model):
for x in reversed(kinds):
if self.statuses.filter(generation=generations_dict['current'], status__kind=x[0]):
return x[1]
- return None # should not happen
+ return None # should not happen
def __unicode__(self):
return u'%s' % self.name
+
class Cert(SignedObject):
"""
Object representing a resource certificate.
"""
addresses = models.ManyToManyField(AddressRange, related_name='certs')
- asns = models.ManyToManyField(ASRange, related_name='certs')
- issuer = models.ForeignKey('Cert', related_name='children', null=True, blank=True)
- sia = models.CharField(max_length=255)
+ addresses_v6 = models.ManyToManyField(AddressRangeV6, related_name='certs')
+ asns = models.ManyToManyField(ASRange, related_name='certs')
+ issuer = models.ForeignKey('self', related_name='children', null=True)
+ sia = models.CharField(max_length=255)
@models.permalink
def get_absolute_url(self):
return ('rpki.gui.cacheview.views.cert_detail', [str(self.pk)])
-class ValidationStatus_Cert(ValidationStatus):
- cert = models.ForeignKey('Cert', related_name='statuses')
class ROAPrefix(models.Model):
- family = models.PositiveIntegerField()
- prefix = models.IPAddressField()
- bits = models.PositiveIntegerField()
- max_length = models.PositiveIntegerField()
+ "Abstract base class for ROA mixin."
+
+ max_length = models.PositiveSmallIntegerField()
class Meta:
- ordering = ['family', 'prefix', 'bits', 'max_length']
+ abstract = True
+
+ def as_roa_prefix(self):
+ "Return value as a rpki.resource_set.roa_prefix_ip object."
+ rng = self.as_resource_range()
+ return self.roa_cls(rng.prefix_min, rng.prefixlen(), self.max_length)
def __unicode__(self):
- if self.bits == self.max_length:
- return u'%s/%d' % (self.prefix, self.bits)
- else:
- return u'%s/%d-%d' % (self.prefix, self.bits, self.max_length)
+ p = self.as_resource_range()
+ if p.prefixlen() == self.max_length:
+ return str(p)
+ return '%s-%s' % (str(p), self.max_length)
+
+
+# ROAPrefix is declared first, so subclass picks up __unicode__ from it.
+class ROAPrefixV4(ROAPrefix, rpki.gui.models.PrefixV4):
+ "One v4 prefix in a ROA."
+
+ roa_cls = rpki.resource_set.roa_prefix_ipv4
+
+ class Meta:
+ ordering = ('prefix_min',)
+
+
+# ROAPrefix is declared first, so subclass picks up __unicode__ from it.
+class ROAPrefixV6(ROAPrefix, rpki.gui.models.PrefixV6):
+ "One v6 prefix in a ROA."
+
+ roa_cls = rpki.resource_set.roa_prefix_ipv6
+
+ class Meta:
+ ordering = ('prefix_min',)
+
class ROA(SignedObject):
- asid = models.PositiveIntegerField()
- prefixes = models.ManyToManyField(ROAPrefix, related_name='roas')
- issuer = models.ForeignKey('Cert', related_name='roas')
+ asid = models.PositiveIntegerField()
+ prefixes = models.ManyToManyField(ROAPrefixV4, related_name='roas')
+ prefixes_v6 = models.ManyToManyField(ROAPrefixV6, related_name='roas')
+ issuer = models.ForeignKey('Cert', related_name='roas')
@models.permalink
def get_absolute_url(self):
return ('rpki.gui.cacheview.views.roa_detail', [str(self.pk)])
class Meta:
- ordering = ['asid']
+ ordering = ('asid',)
def __unicode__(self):
return u'ROA for AS%d' % self.asid
- @models.permalink
- def get_absolute_url(self):
- return ('rpki.gui.cacheview.views.roa_detail', [str(self.pk)])
-
-class ValidationStatus_ROA(ValidationStatus):
- roa = models.ForeignKey('ROA', related_name='statuses')
class Ghostbuster(SignedObject):
- full_name = models.CharField(max_length=40)
+ full_name = models.CharField(max_length=40)
email_address = models.EmailField(blank=True, null=True)
- organization = models.CharField(blank=True, null=True, max_length=255)
- telephone = TelephoneField(blank=True, null=True)
- issuer = models.ForeignKey('Cert', related_name='ghostbusters')
+ organization = models.CharField(blank=True, null=True, max_length=255)
+ telephone = TelephoneField(blank=True, null=True)
+ issuer = models.ForeignKey('Cert', related_name='ghostbusters')
@models.permalink
def get_absolute_url(self):
@@ -226,8 +216,3 @@ class Ghostbuster(SignedObject):
if self.email_address:
return self.email_address
return self.telephone
-
-class ValidationStatus_Ghostbuster(ValidationStatus):
- gbr = models.ForeignKey('Ghostbuster', related_name='statuses')
-
-# vim:sw=4 ts=8 expandtab