diff options
Diffstat (limited to 'rpkid/rpki/gui/cacheview/models.py')
-rw-r--r-- | rpkid/rpki/gui/cacheview/models.py | 203 |
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 |