diff options
Diffstat (limited to 'rpki/gui/app')
-rw-r--r-- | rpki/gui/app/check_expired.py | 53 | ||||
-rw-r--r-- | rpki/gui/app/forms.py | 194 | ||||
-rw-r--r-- | rpki/gui/app/glue.py | 79 | ||||
-rw-r--r-- | rpki/gui/app/migrations/0001_initial.py | 439 | ||||
-rw-r--r-- | rpki/gui/app/models.py | 9 | ||||
-rwxr-xr-x | rpki/gui/app/range_list.py | 2 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0001_initial.py | 192 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0002_auto__add_field_resourcecert_conf.py (renamed from rpki/gui/app/migrations/0002_auto__add_field_resourcecert_conf.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0003_set_conf_from_parent.py (renamed from rpki/gui/app/migrations/0003_set_conf_from_parent.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0004_auto__chg_field_resourcecert_conf.py (renamed from rpki/gui/app/migrations/0004_auto__chg_field_resourcecert_conf.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0005_auto__chg_field_resourcecert_parent.py (renamed from rpki/gui/app/migrations/0005_auto__chg_field_resourcecert_parent.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0006_add_conf_acl.py (renamed from rpki/gui/app/migrations/0006_add_conf_acl.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0007_default_acls.py (renamed from rpki/gui/app/migrations/0007_default_acls.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/0008_add_alerts.py (renamed from rpki/gui/app/migrations/0008_add_alerts.py) | 0 | ||||
-rw-r--r-- | rpki/gui/app/south_migrations/__init__.py | 0 | ||||
-rw-r--r-- | rpki/gui/app/views.py | 135 |
16 files changed, 647 insertions, 456 deletions
diff --git a/rpki/gui/app/check_expired.py b/rpki/gui/app/check_expired.py index a084af79..65f4315f 100644 --- a/rpki/gui/app/check_expired.py +++ b/rpki/gui/app/check_expired.py @@ -1,4 +1,4 @@ -# Copyright (C) 2012, 2013, 2014 SPARTA, Inc. a Parsons Company +# Copyright (C) 2012, 2013, 2014, 2016 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 @@ -21,13 +21,14 @@ from cStringIO import StringIO import logging import datetime -from rpki.gui.cacheview.models import Cert +from rpki.gui.gui_rpki_cache.models import Cert from rpki.gui.app.models import Conf, ResourceCert, Timestamp, Alert from rpki.gui.app.glue import list_received_resources from rpki.irdb import Zookeeper -from rpki.left_right import report_error_elt, list_published_objects_elt from rpki.x509 import X509 +from rpki.left_right import version, nsmap, tag_msg, tag_list_published_objects +from lxml.etree import Element, SubElement from django.core.mail import send_mail logger = logging.getLogger(__name__) @@ -41,8 +42,8 @@ def check_cert(handle, p, errs): The displayed object name defaults to the class name, but can be overridden using the `object_name` argument. - """ + t = p.certificate.getNotAfter() if t <= expire_time: e = 'expired' if t <= now else 'will expire' @@ -60,8 +61,8 @@ def check_expire(conf, errs): # get certs for `handle' cert_set = ResourceCert.objects.filter(conf=conf) for cert in cert_set: - # look up cert in cacheview db - obj_set = Cert.objects.filter(repo__uri=cert.uri) + # look up cert in gui_rpki_cache db + obj_set = Cert.objects.filter(uri=cert.uri) if not obj_set: # since the <list_received_resources/> output is cached, this can # occur if the cache is out of date as well.. @@ -76,7 +77,7 @@ def check_expire(conf, errs): f = '*' else: f = ' ' - msg.append("%s [%d] uri=%s ski=%s name=%s expires=%s" % (f, n, c.repo.uri, c.keyid, c.name, c.not_after)) + msg.append("%s [%d] uri=%s expires=%s" % (f, n, c.uri, c.not_after)) # find ghostbuster records attached to this cert for gbr in c.ghostbusters.all(): @@ -102,30 +103,26 @@ def check_expire(conf, errs): def check_child_certs(conf, errs): """Fetch the list of published objects from rpkid, and inspect the issued resource certs (uri ending in .cer). - """ + z = Zookeeper(handle=conf.handle) - req = list_published_objects_elt.make_pdu(action="list", - tag="list_published_objects", - self_handle=conf.handle) + req = Element(tag_msg, nsmap=nsmap, type="query", version=version) + SubElement(req, tag_list_published_objects, + tag="list_published_objects", tenant_handle=conf.handle) pdus = z.call_rpkid(req) for pdu in pdus: - if isinstance(pdu, report_error_elt): - logger.error("rpkid reported an error: %s", pdu.error_code) - elif isinstance(pdu, list_published_objects_elt): - if pdu.uri.endswith('.cer'): - cert = X509() - cert.set(Base64=pdu.obj) - t = cert.getNotAfter() - if t <= expire_time: - e = 'expired' if t <= now else 'will expire' - errs.write("%(handle)s's rescert for Child %(child)s %(expire)s on %(date)s uri=%(uri)s subject=%(subject)s\n" % { - 'handle': conf.handle, - 'child': pdu.child_handle, - 'uri': pdu.uri, - 'subject': cert.getSubject(), - 'expire': e, - 'date': t}) + if pdu.get("uri").endswith('.cer'): + cert = X509(Base64=pdu.text) + t = cert.getNotAfter() + if t <= expire_time: + e = 'expired' if t <= now else 'will expire' + errs.write("%(handle)s's rescert for Child %(child)s %(expire)s on %(date)s uri=%(uri)s subject=%(subject)s\n" % { + 'handle': conf.handle, + 'child': pdu.get("child_handle"), + 'uri': pdu.get("uri"), + 'subject': cert.getSubject(), + 'expire': e, + 'date': t}) class NetworkError(Exception): @@ -139,8 +136,8 @@ def notify_expired(expire_days=14, from_email=None): expire_days: the number of days ahead of today to warn from_email: set the From: address for the email - """ + global expire_time # so i don't have to pass it around global now diff --git a/rpki/gui/app/forms.py b/rpki/gui/app/forms.py index a1214297..4a95c8da 100644 --- a/rpki/gui/app/forms.py +++ b/rpki/gui/app/forms.py @@ -170,105 +170,105 @@ def ROARequestFormFactory(conf): """ class Cls(forms.Form): - """Form for entering a ROA request. - - Handles both IPv4 and IPv6.""" - - prefix = forms.CharField( - widget=forms.TextInput(attrs={ - 'autofocus': 'true', 'placeholder': 'Prefix', - 'class': 'span4' - }) - ) - max_prefixlen = forms.CharField( - required=False, - widget=forms.TextInput(attrs={ - 'placeholder': 'Max len', - 'class': 'span1' - }) - ) - asn = forms.IntegerField( - widget=forms.TextInput(attrs={ - 'placeholder': 'ASN', - 'class': 'span1' - }) - ) + """Form for entering a ROA request. + + Handles both IPv4 and IPv6.""" + + prefix = forms.CharField( + widget=forms.TextInput(attrs={ + 'autofocus': 'true', 'placeholder': 'Prefix', + 'class': 'span4' + }) + ) + max_prefixlen = forms.CharField( + required=False, + widget=forms.TextInput(attrs={ + 'placeholder': 'Max len', + 'class': 'span1' + }) + ) + asn = forms.IntegerField( + widget=forms.TextInput(attrs={ + 'placeholder': 'ASN', + 'class': 'span1' + }) + ) protect_children = forms.BooleanField(required=False) - def __init__(self, *args, **kwargs): - kwargs['auto_id'] = False - super(Cls, self).__init__(*args, **kwargs) - self.conf = conf # conf is the arg to ROARequestFormFactory - self.inline = True - self.use_table = False - - def _as_resource_range(self): - """Convert the prefix in the form to a - rpki.resource_set.resource_range_ip object. - - If there is no mask provided, assume the closest classful mask. - - """ - prefix = self.cleaned_data.get('prefix') - if '/' not in prefix: - p = IPAddress(prefix) - - # determine the first nonzero bit starting from the lsb and - # subtract from the address size to find the closest classful - # mask that contains this single address - prefixlen = 0 - while (p != 0) and (p & 1) == 0: - prefixlen = prefixlen + 1 - p = p >> 1 - mask = p.bits - (8 * (prefixlen / 8)) - prefix = prefix + '/' + str(mask) - - return resource_range_ip.parse_str(prefix) - - def clean_asn(self): - value = self.cleaned_data.get('asn') - if value < 0: - raise forms.ValidationError('AS must be a positive value or 0') - return value - - def clean_prefix(self): - try: - r = self._as_resource_range() - except: - raise forms.ValidationError('invalid prefix') - - manager = models.ResourceRangeAddressV4 if r.version == 4 else models.ResourceRangeAddressV6 - if not manager.objects.filter(cert__conf=self.conf, - prefix_min__lte=r.min, - prefix_max__gte=r.max).exists(): - raise forms.ValidationError('prefix is not allocated to you') - return str(r) - - def clean_max_prefixlen(self): - v = self.cleaned_data.get('max_prefixlen') - if v: - if v[0] == '/': - v = v[1:] # allow user to specify /24 - try: - if int(v) < 0: - raise forms.ValidationError('max prefix length must be positive or 0') - except ValueError: - raise forms.ValidationError('invalid integer value') - return v - - def clean(self): - if 'prefix' in self.cleaned_data: - r = self._as_resource_range() - max_prefixlen = self.cleaned_data.get('max_prefixlen') - max_prefixlen = int(max_prefixlen) if max_prefixlen else r.prefixlen() - if max_prefixlen < r.prefixlen(): - raise forms.ValidationError( - 'max prefix length must be greater than or equal to the prefix length') - if max_prefixlen > r.min.bits: - raise forms.ValidationError( - 'max prefix length (%d) is out of range for IP version (%d)' % (max_prefixlen, r.min.bits)) - self.cleaned_data['max_prefixlen'] = str(max_prefixlen) - return self.cleaned_data + def __init__(self, *args, **kwargs): + kwargs['auto_id'] = False + super(Cls, self).__init__(*args, **kwargs) + self.conf = conf # conf is the arg to ROARequestFormFactory + self.inline = True + self.use_table = False + + def _as_resource_range(self): + """Convert the prefix in the form to a + rpki.resource_set.resource_range_ip object. + + If there is no mask provided, assume the closest classful mask. + + """ + prefix = self.cleaned_data.get('prefix') + if '/' not in prefix: + p = IPAddress(prefix) + + # determine the first nonzero bit starting from the lsb and + # subtract from the address size to find the closest classful + # mask that contains this single address + prefixlen = 0 + while (p != 0) and (p & 1) == 0: + prefixlen = prefixlen + 1 + p = p >> 1 + mask = p.bits - (8 * (prefixlen / 8)) + prefix = prefix + '/' + str(mask) + + return resource_range_ip.parse_str(prefix) + + def clean_asn(self): + value = self.cleaned_data.get('asn') + if value < 0: + raise forms.ValidationError('AS must be a positive value or 0') + return value + + def clean_prefix(self): + try: + r = self._as_resource_range() + except: + raise forms.ValidationError('invalid prefix') + + manager = models.ResourceRangeAddressV4 if r.version == 4 else models.ResourceRangeAddressV6 + if not manager.objects.filter(cert__conf=self.conf, + prefix_min__lte=r.min, + prefix_max__gte=r.max).exists(): + raise forms.ValidationError('prefix is not allocated to you') + return str(r) + + def clean_max_prefixlen(self): + v = self.cleaned_data.get('max_prefixlen') + if v: + if v[0] == '/': + v = v[1:] # allow user to specify /24 + try: + if int(v) < 0: + raise forms.ValidationError('max prefix length must be positive or 0') + except ValueError: + raise forms.ValidationError('invalid integer value') + return v + + def clean(self): + if 'prefix' in self.cleaned_data: + r = self._as_resource_range() + max_prefixlen = self.cleaned_data.get('max_prefixlen') + max_prefixlen = int(max_prefixlen) if max_prefixlen else r.prefixlen() + if max_prefixlen < r.prefixlen(): + raise forms.ValidationError( + 'max prefix length must be greater than or equal to the prefix length') + if max_prefixlen > r.min.bits: + raise forms.ValidationError( + 'max prefix length (%d) is out of range for IP version (%d)' % (max_prefixlen, r.min.bits)) + self.cleaned_data['max_prefixlen'] = str(max_prefixlen) + return self.cleaned_data return Cls diff --git a/rpki/gui/app/glue.py b/rpki/gui/app/glue.py index a2dddb51..c312618f 100644 --- a/rpki/gui/app/glue.py +++ b/rpki/gui/app/glue.py @@ -16,7 +16,6 @@ """ This file contains code that interfaces between the django views implementing the portal gui and the rpki.* modules. - """ from __future__ import with_statement @@ -28,17 +27,19 @@ from datetime import datetime from rpki.resource_set import (resource_set_as, resource_set_ipv4, resource_set_ipv6, resource_range_ipv4, resource_range_ipv6) -from rpki.left_right import list_received_resources_elt, report_error_elt from rpki.irdb.zookeeper import Zookeeper from rpki.gui.app import models from rpki.exceptions import BadIPResource +from rpki.left_right import nsmap, version, tag_msg, tag_list_received_resources +from lxml.etree import Element, SubElement from django.contrib.auth.models import User -from django.db.transaction import commit_on_success +from django.db.transaction import atomic def ghostbuster_to_vcard(gbr): """Convert a GhostbusterRequest object into a vCard object.""" + import vobject vcard = vobject.vCard() @@ -66,19 +67,7 @@ def ghostbuster_to_vcard(gbr): return vcard.serialize() -class LeftRightError(Exception): - """Class for wrapping report_error_elt errors from Zookeeper.call_rpkid(). - - It expects a single argument, which is the associated report_error_elt instance.""" - - def __str__(self): - return 'Error occurred while communicating with rpkid: handle=%s code=%s text=%s' % ( - self.args[0].self_handle, - self.args[0].error_code, - self.args[0].error_text) - - -@commit_on_success +@atomic def list_received_resources(log, conf): """ Query rpkid for this resource handle's received resources. @@ -86,11 +75,12 @@ def list_received_resources(log, conf): The semantics are to clear the entire table and populate with the list of certs received. Other models should not reference the table directly with foreign keys. - """ z = Zookeeper(handle=conf.handle, disable_signal_handlers=True) - pdus = z.call_rpkid(list_received_resources_elt.make_pdu(self_handle=conf.handle)) + req = Element(tag_msg, nsmap=nsmap, type="query", version=version) + SubElement(req, tag_list_received_resources, tenant_handle=conf.handle) + pdus = z.call_rpkid(req) # pdus is sometimes None (see https://trac.rpki.net/ticket/681) if pdus is None: print >>log, 'error: call_rpkid() returned None for handle %s when fetching received resources' % conf.handle @@ -99,34 +89,27 @@ def list_received_resources(log, conf): models.ResourceCert.objects.filter(conf=conf).delete() for pdu in pdus: - if isinstance(pdu, report_error_elt): - # this will cause the db to be rolled back so the above delete() - # won't clobber existing resources - raise LeftRightError(pdu) - elif isinstance(pdu, list_received_resources_elt): - if pdu.parent_handle != conf.handle: - parent = models.Parent.objects.get(issuer=conf, - handle=pdu.parent_handle) - else: - # root cert, self-signed - parent = None - - not_before = datetime.strptime(pdu.notBefore, "%Y-%m-%dT%H:%M:%SZ") - not_after = datetime.strptime(pdu.notAfter, "%Y-%m-%dT%H:%M:%SZ") - - cert = models.ResourceCert.objects.create( - conf=conf, parent=parent, not_before=not_before, - not_after=not_after, uri=pdu.uri) - - for asn in resource_set_as(pdu.asn): - cert.asn_ranges.create(min=asn.min, max=asn.max) - - for rng in resource_set_ipv4(pdu.ipv4): - cert.address_ranges.create(prefix_min=rng.min, - prefix_max=rng.max) - - for rng in resource_set_ipv6(pdu.ipv6): - cert.address_ranges_v6.create(prefix_min=rng.min, - prefix_max=rng.max) + if pdu.get("parent_handle") != conf.handle: + parent = models.Parent.objects.get(issuer=conf, + handle=pdu.get("parent_handle")) else: - print >>log, "error: unexpected pdu from rpkid type=%s" % type(pdu) + # root cert, self-signed + parent = None + + not_before = datetime.strptime(pdu.get("notBefore"), "%Y-%m-%dT%H:%M:%SZ") + not_after = datetime.strptime(pdu.get("notAfter"), "%Y-%m-%dT%H:%M:%SZ") + + cert = models.ResourceCert.objects.create( + conf=conf, parent=parent, not_before=not_before, + not_after=not_after, uri=pdu.get("uri")) + + for asn in resource_set_as(pdu.get("asn")): + cert.asn_ranges.create(min=asn.min, max=asn.max) + + for rng in resource_set_ipv4(pdu.get("ipv4")): + cert.address_ranges.create(prefix_min=rng.min, + prefix_max=rng.max) + + for rng in resource_set_ipv6(pdu.get("ipv6")): + cert.address_ranges_v6.create(prefix_min=rng.min, + prefix_max=rng.max) diff --git a/rpki/gui/app/migrations/0001_initial.py b/rpki/gui/app/migrations/0001_initial.py index 80877901..79d21324 100644 --- a/rpki/gui/app/migrations/0001_initial.py +++ b/rpki/gui/app/migrations/0001_initial.py @@ -1,192 +1,249 @@ # -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding model 'ResourceCert' - db.create_table('app_resourcecert', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='certs', to=orm['irdb.Parent'])), - ('not_before', self.gf('django.db.models.fields.DateTimeField')()), - ('not_after', self.gf('django.db.models.fields.DateTimeField')()), - ('uri', self.gf('django.db.models.fields.CharField')(max_length=255)), - )) - db.send_create_signal('app', ['ResourceCert']) - - # Adding model 'ResourceRangeAddressV4' - db.create_table('app_resourcerangeaddressv4', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('prefix_min', self.gf('rpki.gui.models.IPv4AddressField')(db_index=True)), - ('prefix_max', self.gf('rpki.gui.models.IPv4AddressField')(db_index=True)), - ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='address_ranges', to=orm['app.ResourceCert'])), - )) - db.send_create_signal('app', ['ResourceRangeAddressV4']) - - # Adding model 'ResourceRangeAddressV6' - db.create_table('app_resourcerangeaddressv6', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('prefix_min', self.gf('rpki.gui.models.IPv6AddressField')(db_index=True)), - ('prefix_max', self.gf('rpki.gui.models.IPv6AddressField')(db_index=True)), - ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='address_ranges_v6', to=orm['app.ResourceCert'])), - )) - db.send_create_signal('app', ['ResourceRangeAddressV6']) - - # Adding model 'ResourceRangeAS' - db.create_table('app_resourcerangeas', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('min', self.gf('django.db.models.fields.PositiveIntegerField')()), - ('max', self.gf('django.db.models.fields.PositiveIntegerField')()), - ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='asn_ranges', to=orm['app.ResourceCert'])), - )) - db.send_create_signal('app', ['ResourceRangeAS']) - - # Adding model 'GhostbusterRequest' - db.create_table('app_ghostbusterrequest', ( - ('ghostbusterrequest_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['irdb.GhostbusterRequest'], unique=True, primary_key=True)), - ('full_name', self.gf('django.db.models.fields.CharField')(max_length=40)), - ('family_name', self.gf('django.db.models.fields.CharField')(max_length=20)), - ('given_name', self.gf('django.db.models.fields.CharField')(max_length=20)), - ('additional_name', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True)), - ('honorific_prefix', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), - ('honorific_suffix', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), - ('email_address', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True)), - ('organization', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), - ('telephone', self.gf('rpki.gui.app.models.TelephoneField')(max_length=40, null=True, blank=True)), - ('box', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('extended', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), - ('street', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), - ('city', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('region', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('code', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - ('country', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), - )) - db.send_create_signal('app', ['GhostbusterRequest']) - - # Adding model 'Timestamp' - db.create_table('app_timestamp', ( - ('name', self.gf('django.db.models.fields.CharField')(max_length=30, primary_key=True)), - ('ts', self.gf('django.db.models.fields.DateTimeField')()), - )) - db.send_create_signal('app', ['Timestamp']) - - - def backwards(self, orm): - # Deleting model 'ResourceCert' - db.delete_table('app_resourcecert') - - # Deleting model 'ResourceRangeAddressV4' - db.delete_table('app_resourcerangeaddressv4') - - # Deleting model 'ResourceRangeAddressV6' - db.delete_table('app_resourcerangeaddressv6') - - # Deleting model 'ResourceRangeAS' - db.delete_table('app_resourcerangeas') - - # Deleting model 'GhostbusterRequest' - db.delete_table('app_ghostbusterrequest') - - # Deleting model 'Timestamp' - db.delete_table('app_timestamp') - - - models = { - 'app.ghostbusterrequest': { - 'Meta': {'ordering': "('family_name', 'given_name')", 'object_name': 'GhostbusterRequest', '_ormbases': ['irdb.GhostbusterRequest']}, - 'additional_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), - 'box': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'city': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'code': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'country': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - 'extended': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'family_name': ('django.db.models.fields.CharField', [], {'max_length': '20'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}), - 'ghostbusterrequest_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['irdb.GhostbusterRequest']", 'unique': 'True', 'primary_key': 'True'}), - 'given_name': ('django.db.models.fields.CharField', [], {'max_length': '20'}), - 'honorific_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), - 'honorific_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), - 'organization': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'region': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), - 'street': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'telephone': ('rpki.gui.app.models.TelephoneField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) - }, - 'app.resourcecert': { - 'Meta': {'object_name': 'ResourceCert'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'not_after': ('django.db.models.fields.DateTimeField', [], {}), - 'not_before': ('django.db.models.fields.DateTimeField', [], {}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'certs'", 'to': "orm['irdb.Parent']"}), - 'uri': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - 'app.resourcerangeaddressv4': { - 'Meta': {'ordering': "('prefix_min',)", 'object_name': 'ResourceRangeAddressV4'}, - 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'address_ranges'", 'to': "orm['app.ResourceCert']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'prefix_max': ('rpki.gui.models.IPv4AddressField', [], {'db_index': 'True'}), - 'prefix_min': ('rpki.gui.models.IPv4AddressField', [], {'db_index': 'True'}) - }, - 'app.resourcerangeaddressv6': { - 'Meta': {'ordering': "('prefix_min',)", 'object_name': 'ResourceRangeAddressV6'}, - 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'address_ranges_v6'", 'to': "orm['app.ResourceCert']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'prefix_max': ('rpki.gui.models.IPv6AddressField', [], {'db_index': 'True'}), - 'prefix_min': ('rpki.gui.models.IPv6AddressField', [], {'db_index': 'True'}) - }, - 'app.resourcerangeas': { - 'Meta': {'ordering': "('min', 'max')", 'object_name': 'ResourceRangeAS'}, - 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'asn_ranges'", 'to': "orm['app.ResourceCert']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'max': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'min': ('django.db.models.fields.PositiveIntegerField', [], {}) - }, - 'app.timestamp': { - 'Meta': {'object_name': 'Timestamp'}, - 'name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}), - 'ts': ('django.db.models.fields.DateTimeField', [], {}) - }, - 'irdb.ghostbusterrequest': { - 'Meta': {'object_name': 'GhostbusterRequest'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'issuer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ghostbuster_requests'", 'to': "orm['irdb.ResourceHolderCA']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ghostbuster_requests'", 'null': 'True', 'to': "orm['irdb.Parent']"}), - 'vcard': ('django.db.models.fields.TextField', [], {}) - }, - 'irdb.parent': { - 'Meta': {'unique_together': "(('issuer', 'handle'),)", 'object_name': 'Parent', '_ormbases': ['irdb.Turtle']}, - 'certificate': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), - 'child_handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), - 'handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), - 'issuer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parents'", 'to': "orm['irdb.ResourceHolderCA']"}), - 'parent_handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), - 'referral_authorization': ('rpki.irdb.models.SignedReferralField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), - 'referrer': ('rpki.irdb.models.HandleField', [], {'max_length': '120', 'null': 'True', 'blank': 'True'}), - 'repository_type': ('rpki.irdb.models.EnumField', [], {}), - 'ta': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), - 'turtle_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['irdb.Turtle']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'irdb.resourceholderca': { - 'Meta': {'object_name': 'ResourceHolderCA'}, - 'certificate': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), - 'handle': ('rpki.irdb.models.HandleField', [], {'unique': 'True', 'max_length': '120'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_crl_update': ('rpki.irdb.models.SundialField', [], {}), - 'latest_crl': ('rpki.irdb.models.CRLField', [], {'default': 'None', 'blank': 'True'}), - 'next_crl_number': ('django.db.models.fields.BigIntegerField', [], {'default': '1'}), - 'next_crl_update': ('rpki.irdb.models.SundialField', [], {}), - 'next_serial': ('django.db.models.fields.BigIntegerField', [], {'default': '1'}), - 'private_key': ('rpki.irdb.models.RSAKeyField', [], {'default': 'None', 'blank': 'True'}) - }, - 'irdb.turtle': { - 'Meta': {'object_name': 'Turtle'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'service_uri': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - } - } - - complete_apps = ['app']
\ No newline at end of file +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import rpki.gui.models +import rpki.gui.app.models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('irdb', '0001_initial'), + ('routeview', '__first__'), + ] + + operations = [ + migrations.CreateModel( + name='Alert', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('severity', models.SmallIntegerField(default=0, choices=[(0, b'info'), (1, b'warning'), (2, b'error')])), + ('when', models.DateTimeField(auto_now_add=True)), + ('seen', models.BooleanField(default=False)), + ('subject', models.CharField(max_length=66)), + ('text', models.TextField()), + ], + ), + migrations.CreateModel( + name='ConfACL', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ], + ), + migrations.CreateModel( + name='GhostbusterRequest', + fields=[ + ('ghostbusterrequest_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='irdb.GhostbusterRequest')), + ('full_name', models.CharField(max_length=40)), + ('family_name', models.CharField(max_length=20)), + ('given_name', models.CharField(max_length=20)), + ('additional_name', models.CharField(max_length=20, null=True, blank=True)), + ('honorific_prefix', models.CharField(max_length=10, null=True, blank=True)), + ('honorific_suffix', models.CharField(max_length=10, null=True, blank=True)), + ('email_address', models.EmailField(max_length=254, null=True, blank=True)), + ('organization', models.CharField(max_length=255, null=True, blank=True)), + ('telephone', rpki.gui.app.models.TelephoneField(max_length=40, null=True, blank=True)), + ('box', models.CharField(max_length=40, null=True, verbose_name=b'P.O. Box', blank=True)), + ('extended', models.CharField(max_length=255, null=True, blank=True)), + ('street', models.CharField(max_length=255, null=True, blank=True)), + ('city', models.CharField(max_length=40, null=True, blank=True)), + ('region', models.CharField(help_text=b'state or province', max_length=40, null=True, blank=True)), + ('code', models.CharField(max_length=40, null=True, verbose_name=b'Postal Code', blank=True)), + ('country', models.CharField(max_length=40, null=True, blank=True)), + ], + options={ + 'ordering': ('family_name', 'given_name'), + }, + bases=('irdb.ghostbusterrequest',), + ), + migrations.CreateModel( + name='ResourceCert', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('not_before', models.DateTimeField()), + ('not_after', models.DateTimeField()), + ('uri', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='ResourceRangeAddressV4', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('prefix_min', rpki.gui.models.IPAddressField(db_index=True)), + ('prefix_max', rpki.gui.models.IPAddressField(db_index=True)), + ('cert', models.ForeignKey(related_name='address_ranges', to='app.ResourceCert')), + ], + options={ + 'ordering': ('prefix_min',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ResourceRangeAddressV6', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('prefix_min', rpki.gui.models.IPAddressField(db_index=True)), + ('prefix_max', rpki.gui.models.IPAddressField(db_index=True)), + ('cert', models.ForeignKey(related_name='address_ranges_v6', to='app.ResourceCert')), + ], + options={ + 'ordering': ('prefix_min',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ResourceRangeAS', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('min', models.BigIntegerField(validators=[rpki.gui.models.validate_asn])), + ('max', models.BigIntegerField(validators=[rpki.gui.models.validate_asn])), + ('cert', models.ForeignKey(related_name='asn_ranges', to='app.ResourceCert')), + ], + options={ + 'ordering': ('min', 'max'), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Timestamp', + fields=[ + ('name', models.CharField(max_length=30, serialize=False, primary_key=True)), + ('ts', models.DateTimeField()), + ], + ), + migrations.CreateModel( + name='Child', + fields=[ + ], + options={ + 'proxy': True, + 'verbose_name_plural': 'children', + }, + bases=('irdb.child',), + ), + migrations.CreateModel( + name='ChildASN', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.childasn',), + ), + migrations.CreateModel( + name='ChildNet', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.childnet',), + ), + migrations.CreateModel( + name='Client', + fields=[ + ], + options={ + 'verbose_name': 'Client', + 'proxy': True, + }, + bases=('irdb.client',), + ), + migrations.CreateModel( + name='Conf', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.resourceholderca',), + ), + migrations.CreateModel( + name='Parent', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.parent',), + ), + migrations.CreateModel( + name='Repository', + fields=[ + ], + options={ + 'verbose_name': 'Repository', + 'proxy': True, + 'verbose_name_plural': 'Repositories', + }, + bases=('irdb.repository',), + ), + migrations.CreateModel( + name='ROARequest', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.roarequest',), + ), + migrations.CreateModel( + name='ROARequestPrefix', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('irdb.roarequestprefix',), + ), + migrations.CreateModel( + name='RouteOrigin', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('routeview.routeorigin',), + ), + migrations.CreateModel( + name='RouteOriginV6', + fields=[ + ], + options={ + 'proxy': True, + }, + bases=('routeview.routeoriginv6',), + ), + migrations.AddField( + model_name='resourcecert', + name='conf', + field=models.ForeignKey(related_name='certs', to='app.Conf'), + ), + migrations.AddField( + model_name='resourcecert', + name='parent', + field=models.ForeignKey(related_name='certs', to='app.Parent', null=True), + ), + migrations.AddField( + model_name='confacl', + name='conf', + field=models.ForeignKey(to='app.Conf'), + ), + migrations.AddField( + model_name='confacl', + name='user', + field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='alert', + name='conf', + field=models.ForeignKey(related_name='alerts', to='app.Conf'), + ), + migrations.AlterUniqueTogether( + name='confacl', + unique_together=set([('user', 'conf')]), + ), + ] diff --git a/rpki/gui/app/models.py b/rpki/gui/app/models.py index 40bdbe2c..fb1cafff 100644 --- a/rpki/gui/app/models.py +++ b/rpki/gui/app/models.py @@ -1,5 +1,5 @@ # Copyright (C) 2010 SPARTA, Inc. dba Cobham Analytic Solutions -# Copyright (C) 2012 SPARTA, Inc. a Parsons Company +# Copyright (C) 2012, 2016 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 @@ -26,7 +26,6 @@ import rpki.irdb.models import rpki.gui.models import rpki.gui.routeview.models import rpki.oids -from south.modelsinspector import add_introspection_rules class TelephoneField(models.CharField): @@ -35,8 +34,6 @@ class TelephoneField(models.CharField): kwargs['max_length'] = 40 models.CharField.__init__(self, **kwargs) -add_introspection_rules([], [r'^rpki\.gui\.app\.models\.TelephoneField']) - class Parent(rpki.irdb.models.Parent): """proxy model for irdb Parent""" @@ -123,7 +120,7 @@ class Alert(models.Model): class Conf(rpki.irdb.models.ResourceHolderCA): """This is the center of the universe, also known as a place to - have a handle on a resource-holding entity. It's the <self> + have a handle on a resource-holding entity. It's the <tenant/> in the rpkid schema. """ @@ -262,7 +259,7 @@ class ResourceCert(models.Model): not_after = models.DateTimeField() # Locator for this object. Used to look up the validation status, expiry - # of ancestor certs in cacheview + # of ancestor certs in gui_rpki_cache uri = models.CharField(max_length=255) def __unicode__(self): diff --git a/rpki/gui/app/range_list.py b/rpki/gui/app/range_list.py index 21fd1f29..5cb4f5e4 100755 --- a/rpki/gui/app/range_list.py +++ b/rpki/gui/app/range_list.py @@ -70,6 +70,7 @@ class RangeList(list): def difference(self, other): """Return a RangeList object which contains ranges in this object which are not in "other".""" + it = iter(other) try: @@ -85,6 +86,7 @@ class RangeList(list): def V(v): """convert the integer value to the appropriate type for this range""" + return x.__class__.datum_type(v) try: diff --git a/rpki/gui/app/south_migrations/0001_initial.py b/rpki/gui/app/south_migrations/0001_initial.py new file mode 100644 index 00000000..80877901 --- /dev/null +++ b/rpki/gui/app/south_migrations/0001_initial.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'ResourceCert' + db.create_table('app_resourcecert', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('parent', self.gf('django.db.models.fields.related.ForeignKey')(related_name='certs', to=orm['irdb.Parent'])), + ('not_before', self.gf('django.db.models.fields.DateTimeField')()), + ('not_after', self.gf('django.db.models.fields.DateTimeField')()), + ('uri', self.gf('django.db.models.fields.CharField')(max_length=255)), + )) + db.send_create_signal('app', ['ResourceCert']) + + # Adding model 'ResourceRangeAddressV4' + db.create_table('app_resourcerangeaddressv4', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('prefix_min', self.gf('rpki.gui.models.IPv4AddressField')(db_index=True)), + ('prefix_max', self.gf('rpki.gui.models.IPv4AddressField')(db_index=True)), + ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='address_ranges', to=orm['app.ResourceCert'])), + )) + db.send_create_signal('app', ['ResourceRangeAddressV4']) + + # Adding model 'ResourceRangeAddressV6' + db.create_table('app_resourcerangeaddressv6', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('prefix_min', self.gf('rpki.gui.models.IPv6AddressField')(db_index=True)), + ('prefix_max', self.gf('rpki.gui.models.IPv6AddressField')(db_index=True)), + ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='address_ranges_v6', to=orm['app.ResourceCert'])), + )) + db.send_create_signal('app', ['ResourceRangeAddressV6']) + + # Adding model 'ResourceRangeAS' + db.create_table('app_resourcerangeas', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('min', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('max', self.gf('django.db.models.fields.PositiveIntegerField')()), + ('cert', self.gf('django.db.models.fields.related.ForeignKey')(related_name='asn_ranges', to=orm['app.ResourceCert'])), + )) + db.send_create_signal('app', ['ResourceRangeAS']) + + # Adding model 'GhostbusterRequest' + db.create_table('app_ghostbusterrequest', ( + ('ghostbusterrequest_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['irdb.GhostbusterRequest'], unique=True, primary_key=True)), + ('full_name', self.gf('django.db.models.fields.CharField')(max_length=40)), + ('family_name', self.gf('django.db.models.fields.CharField')(max_length=20)), + ('given_name', self.gf('django.db.models.fields.CharField')(max_length=20)), + ('additional_name', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True)), + ('honorific_prefix', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), + ('honorific_suffix', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)), + ('email_address', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True)), + ('organization', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('telephone', self.gf('rpki.gui.app.models.TelephoneField')(max_length=40, null=True, blank=True)), + ('box', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('extended', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('street', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('city', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('region', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('code', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + ('country', self.gf('django.db.models.fields.CharField')(max_length=40, null=True, blank=True)), + )) + db.send_create_signal('app', ['GhostbusterRequest']) + + # Adding model 'Timestamp' + db.create_table('app_timestamp', ( + ('name', self.gf('django.db.models.fields.CharField')(max_length=30, primary_key=True)), + ('ts', self.gf('django.db.models.fields.DateTimeField')()), + )) + db.send_create_signal('app', ['Timestamp']) + + + def backwards(self, orm): + # Deleting model 'ResourceCert' + db.delete_table('app_resourcecert') + + # Deleting model 'ResourceRangeAddressV4' + db.delete_table('app_resourcerangeaddressv4') + + # Deleting model 'ResourceRangeAddressV6' + db.delete_table('app_resourcerangeaddressv6') + + # Deleting model 'ResourceRangeAS' + db.delete_table('app_resourcerangeas') + + # Deleting model 'GhostbusterRequest' + db.delete_table('app_ghostbusterrequest') + + # Deleting model 'Timestamp' + db.delete_table('app_timestamp') + + + models = { + 'app.ghostbusterrequest': { + 'Meta': {'ordering': "('family_name', 'given_name')", 'object_name': 'GhostbusterRequest', '_ormbases': ['irdb.GhostbusterRequest']}, + 'additional_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'box': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'code': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'extended': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'family_name': ('django.db.models.fields.CharField', [], {'max_length': '20'}), + 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'ghostbusterrequest_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['irdb.GhostbusterRequest']", 'unique': 'True', 'primary_key': 'True'}), + 'given_name': ('django.db.models.fields.CharField', [], {'max_length': '20'}), + 'honorific_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'honorific_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), + 'organization': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'region': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'street': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'telephone': ('rpki.gui.app.models.TelephoneField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}) + }, + 'app.resourcecert': { + 'Meta': {'object_name': 'ResourceCert'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'not_after': ('django.db.models.fields.DateTimeField', [], {}), + 'not_before': ('django.db.models.fields.DateTimeField', [], {}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'certs'", 'to': "orm['irdb.Parent']"}), + 'uri': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'app.resourcerangeaddressv4': { + 'Meta': {'ordering': "('prefix_min',)", 'object_name': 'ResourceRangeAddressV4'}, + 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'address_ranges'", 'to': "orm['app.ResourceCert']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'prefix_max': ('rpki.gui.models.IPv4AddressField', [], {'db_index': 'True'}), + 'prefix_min': ('rpki.gui.models.IPv4AddressField', [], {'db_index': 'True'}) + }, + 'app.resourcerangeaddressv6': { + 'Meta': {'ordering': "('prefix_min',)", 'object_name': 'ResourceRangeAddressV6'}, + 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'address_ranges_v6'", 'to': "orm['app.ResourceCert']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'prefix_max': ('rpki.gui.models.IPv6AddressField', [], {'db_index': 'True'}), + 'prefix_min': ('rpki.gui.models.IPv6AddressField', [], {'db_index': 'True'}) + }, + 'app.resourcerangeas': { + 'Meta': {'ordering': "('min', 'max')", 'object_name': 'ResourceRangeAS'}, + 'cert': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'asn_ranges'", 'to': "orm['app.ResourceCert']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'max': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'min': ('django.db.models.fields.PositiveIntegerField', [], {}) + }, + 'app.timestamp': { + 'Meta': {'object_name': 'Timestamp'}, + 'name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}), + 'ts': ('django.db.models.fields.DateTimeField', [], {}) + }, + 'irdb.ghostbusterrequest': { + 'Meta': {'object_name': 'GhostbusterRequest'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issuer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ghostbuster_requests'", 'to': "orm['irdb.ResourceHolderCA']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ghostbuster_requests'", 'null': 'True', 'to': "orm['irdb.Parent']"}), + 'vcard': ('django.db.models.fields.TextField', [], {}) + }, + 'irdb.parent': { + 'Meta': {'unique_together': "(('issuer', 'handle'),)", 'object_name': 'Parent', '_ormbases': ['irdb.Turtle']}, + 'certificate': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), + 'child_handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), + 'handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), + 'issuer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parents'", 'to': "orm['irdb.ResourceHolderCA']"}), + 'parent_handle': ('rpki.irdb.models.HandleField', [], {'max_length': '120'}), + 'referral_authorization': ('rpki.irdb.models.SignedReferralField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), + 'referrer': ('rpki.irdb.models.HandleField', [], {'max_length': '120', 'null': 'True', 'blank': 'True'}), + 'repository_type': ('rpki.irdb.models.EnumField', [], {}), + 'ta': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), + 'turtle_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['irdb.Turtle']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'irdb.resourceholderca': { + 'Meta': {'object_name': 'ResourceHolderCA'}, + 'certificate': ('rpki.irdb.models.CertificateField', [], {'default': 'None', 'blank': 'True'}), + 'handle': ('rpki.irdb.models.HandleField', [], {'unique': 'True', 'max_length': '120'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_crl_update': ('rpki.irdb.models.SundialField', [], {}), + 'latest_crl': ('rpki.irdb.models.CRLField', [], {'default': 'None', 'blank': 'True'}), + 'next_crl_number': ('django.db.models.fields.BigIntegerField', [], {'default': '1'}), + 'next_crl_update': ('rpki.irdb.models.SundialField', [], {}), + 'next_serial': ('django.db.models.fields.BigIntegerField', [], {'default': '1'}), + 'private_key': ('rpki.irdb.models.RSAKeyField', [], {'default': 'None', 'blank': 'True'}) + }, + 'irdb.turtle': { + 'Meta': {'object_name': 'Turtle'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'service_uri': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + } + } + + complete_apps = ['app']
\ No newline at end of file diff --git a/rpki/gui/app/migrations/0002_auto__add_field_resourcecert_conf.py b/rpki/gui/app/south_migrations/0002_auto__add_field_resourcecert_conf.py index d3326f90..d3326f90 100644 --- a/rpki/gui/app/migrations/0002_auto__add_field_resourcecert_conf.py +++ b/rpki/gui/app/south_migrations/0002_auto__add_field_resourcecert_conf.py diff --git a/rpki/gui/app/migrations/0003_set_conf_from_parent.py b/rpki/gui/app/south_migrations/0003_set_conf_from_parent.py index a90a11cc..a90a11cc 100644 --- a/rpki/gui/app/migrations/0003_set_conf_from_parent.py +++ b/rpki/gui/app/south_migrations/0003_set_conf_from_parent.py diff --git a/rpki/gui/app/migrations/0004_auto__chg_field_resourcecert_conf.py b/rpki/gui/app/south_migrations/0004_auto__chg_field_resourcecert_conf.py index a236ad4a..a236ad4a 100644 --- a/rpki/gui/app/migrations/0004_auto__chg_field_resourcecert_conf.py +++ b/rpki/gui/app/south_migrations/0004_auto__chg_field_resourcecert_conf.py diff --git a/rpki/gui/app/migrations/0005_auto__chg_field_resourcecert_parent.py b/rpki/gui/app/south_migrations/0005_auto__chg_field_resourcecert_parent.py index 11e9c814..11e9c814 100644 --- a/rpki/gui/app/migrations/0005_auto__chg_field_resourcecert_parent.py +++ b/rpki/gui/app/south_migrations/0005_auto__chg_field_resourcecert_parent.py diff --git a/rpki/gui/app/migrations/0006_add_conf_acl.py b/rpki/gui/app/south_migrations/0006_add_conf_acl.py index 88fe8171..88fe8171 100644 --- a/rpki/gui/app/migrations/0006_add_conf_acl.py +++ b/rpki/gui/app/south_migrations/0006_add_conf_acl.py diff --git a/rpki/gui/app/migrations/0007_default_acls.py b/rpki/gui/app/south_migrations/0007_default_acls.py index 40656d0f..40656d0f 100644 --- a/rpki/gui/app/migrations/0007_default_acls.py +++ b/rpki/gui/app/south_migrations/0007_default_acls.py diff --git a/rpki/gui/app/migrations/0008_add_alerts.py b/rpki/gui/app/south_migrations/0008_add_alerts.py index 77af68d2..77af68d2 100644 --- a/rpki/gui/app/migrations/0008_add_alerts.py +++ b/rpki/gui/app/south_migrations/0008_add_alerts.py diff --git a/rpki/gui/app/south_migrations/__init__.py b/rpki/gui/app/south_migrations/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/rpki/gui/app/south_migrations/__init__.py diff --git a/rpki/gui/app/views.py b/rpki/gui/app/views.py index bf152f8e..03c7c168 100644 --- a/rpki/gui/app/views.py +++ b/rpki/gui/app/views.py @@ -1,5 +1,5 @@ # Copyright (C) 2010, 2011 SPARTA, Inc. dba Cobham Analytic Solutions -# Copyright (C) 2012, 2014 SPARTA, Inc. a Parsons Company +# Copyright (C) 2012, 2014, 2016 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 @@ -23,7 +23,6 @@ __version__ = '$Id$' import os import os.path -from tempfile import NamedTemporaryFile import cStringIO import csv import logging @@ -42,7 +41,8 @@ from django.forms.formsets import formset_factory, BaseFormSet from django.contrib import messages from django.db.models import Q -from rpki.irdb import Zookeeper, ChildASN, ChildNet, ROARequestPrefix +from rpki.irdb import Zookeeper +from rpki.irdb.models import ChildASN, ChildNet, ROARequestPrefix from rpki.gui.app import models, forms, glue, range_list from rpki.resource_set import (resource_range_as, resource_range_ip, roa_prefix_ipv4) @@ -50,7 +50,6 @@ from rpki import sundial import rpki.exceptions import rpki.csv_utils -from rpki.gui.cacheview.models import ROA from rpki.gui.routeview.models import RouteOrigin from rpki.gui.decorators import tls_required @@ -136,10 +135,6 @@ def generic_import(request, queryset, configure, form_class=None, if request.method == 'POST': form = form_class(request.POST, request.FILES) if form.is_valid(): - tmpf = NamedTemporaryFile(prefix='import', suffix='.xml', - delete=False) - tmpf.write(form.cleaned_data['xml'].read()) - tmpf.close() z = Zookeeper(handle=conf.handle) handle = form.cleaned_data.get('handle') # CharField uses an empty string for the empty value, rather than @@ -148,27 +143,25 @@ def generic_import(request, queryset, configure, form_class=None, if handle == '': handle = None try: - # configure_repository returns None, so can't use tuple expansion - # here. Unpack the tuple below if post_import_redirect is None. - r = configure(z, tmpf.name, handle) + # configure_repository returns None, so can't use tuple expansion + # here. Unpack the tuple below if post_import_redirect is None. + r = configure(z, form.cleaned_data['xml'], handle) except lxml.etree.XMLSyntaxError as e: - logger.exception('caught XMLSyntaxError while parsing uploaded file') + logger.exception('caught XMLSyntaxError while parsing uploaded file') messages.error( request, 'The uploaded file has an invalid XML syntax' ) else: - # force rpkid run now - z.synchronize_ca(poke=True) - if post_import_redirect: - url = post_import_redirect - else: - _, handle = r - url = queryset.get(issuer=conf, - handle=handle).get_absolute_url() - return http.HttpResponseRedirect(url) - finally: - os.remove(tmpf.name) + # force rpkid run now + z.synchronize_ca(poke=True) + if post_import_redirect: + url = post_import_redirect + else: + _, handle = r + url = queryset.get(issuer=conf, + handle=handle).get_absolute_url() + return http.HttpResponseRedirect(url) else: form = form_class() @@ -298,10 +291,10 @@ def serve_xml(content, basename, ext='xml'): `basename` is the prefix to specify for the XML filename. - `csv` is the type (default: xml) + `ext` is the type (default: xml) """ - resp = http.HttpResponse(content, mimetype='application/%s' % ext) + resp = http.HttpResponse(content, content_type='application/%s' % ext) resp['Content-Disposition'] = 'attachment; filename=%s.%s' % (basename, ext) return resp @@ -332,13 +325,10 @@ def import_asns(request): if request.method == 'POST': form = forms.ImportCSVForm(request.POST, request.FILES) if form.is_valid(): - f = NamedTemporaryFile(prefix='asns', suffix='.csv', delete=False) - f.write(request.FILES['csv'].read()) - f.close() z = Zookeeper(handle=conf.handle, disable_signal_handlers=True) try: z.load_asns( - f.name, + request.FILES['csv'], ignore_missing_children=form.cleaned_data['ignore_missing_children'] ) except rpki.irdb.models.Child.DoesNotExist: @@ -353,8 +343,6 @@ def import_asns(request): z.run_rpkid_now() messages.success(request, 'Successfully imported AS delgations from CSV file.') return redirect(dashboard) - finally: - os.unlink(f.name) else: form = forms.ImportCSVForm() return render(request, 'app/import_resource_form.html', { @@ -381,13 +369,10 @@ def import_prefixes(request): if request.method == 'POST': form = forms.ImportCSVForm(request.POST, request.FILES) if form.is_valid(): - f = NamedTemporaryFile(prefix='prefixes', suffix='.csv', delete=False) - f.write(request.FILES['csv'].read()) - f.close() z = Zookeeper(handle=conf.handle, disable_signal_handlers=True) try: z.load_prefixes( - f.name, + request.FILES['csv'], ignore_missing_children=form.cleaned_data['ignore_missing_children'] ) except rpki.irdb.models.Child.DoesNotExist: @@ -399,8 +384,6 @@ def import_prefixes(request): z.run_rpkid_now() messages.success(request, 'Successfully imported AS delgations from CSV file.') return redirect(dashboard) - finally: - os.unlink(f.name) else: form = forms.ImportCSVForm() return render(request, 'app/import_resource_form.html', { @@ -474,10 +457,10 @@ def child_add_prefix(request, pk): child.address_ranges.create(start_ip=str(r.min), end_ip=str(r.max), version=version) Zookeeper( - handle=conf.handle, - logstream=logstream, - disable_signal_handlers=True - ).run_rpkid_now() + handle=conf.handle, + logstream=logstream, + disable_signal_handlers=True + ).run_rpkid_now() return http.HttpResponseRedirect(child.get_absolute_url()) else: form = forms.AddNetForm(child=child) @@ -497,10 +480,10 @@ def child_add_asn(request, pk): r = resource_range_as.parse_str(asns) child.asns.create(start_as=r.min, end_as=r.max) Zookeeper( - handle=conf.handle, - logstream=logstream, - disable_signal_handlers=True - ).run_rpkid_now() + handle=conf.handle, + logstream=logstream, + disable_signal_handlers=True + ).run_rpkid_now() return http.HttpResponseRedirect(child.get_absolute_url()) else: form = forms.AddASNForm(child=child) @@ -531,10 +514,10 @@ def child_edit(request, pk): models.ChildASN.objects.filter(child=child).exclude(pk__in=form.cleaned_data.get('as_ranges')).delete() models.ChildNet.objects.filter(child=child).exclude(pk__in=form.cleaned_data.get('address_ranges')).delete() Zookeeper( - handle=conf.handle, - logstream=logstream, - disable_signal_handlers=True - ).run_rpkid_now() + handle=conf.handle, + logstream=log, + disable_signal_handlers=True + ).run_rpkid_now() return http.HttpResponseRedirect(child.get_absolute_url()) else: form = form_class(initial={ @@ -713,27 +696,27 @@ def roa_create_multi(request): v = [] rng.chop_into_prefixes(v) init.extend([{'asn': asn, 'prefix': str(p)} for p in v]) - extra = 0 if init else 1 + extra = 0 if init else 1 formset = formset_factory(forms.ROARequestFormFactory(conf), extra=extra)(initial=init) elif request.method == 'POST': formset = formset_factory(forms.ROARequestFormFactory(conf), extra=0)(request.POST, request.FILES) - # We need to check .has_changed() because .is_valid() will return true - # if the user clicks the Preview button without filling in the blanks - # in the ROA form, leaving the form invalid from this view's POV. + # We need to check .has_changed() because .is_valid() will return true + # if the user clicks the Preview button without filling in the blanks + # in the ROA form, leaving the form invalid from this view's POV. if formset.has_changed() and formset.is_valid(): routes = [] v = [] query = Q() # for matching routes roas = [] for form in formset: - asn = form.cleaned_data['asn'] - rng = resource_range_ip.parse_str(form.cleaned_data['prefix']) - max_prefixlen = int(form.cleaned_data['max_prefixlen']) + asn = form.cleaned_data['asn'] + rng = resource_range_ip.parse_str(form.cleaned_data['prefix']) + max_prefixlen = int(form.cleaned_data['max_prefixlen']) protect_children = form.cleaned_data['protect_children'] roas.append((rng, max_prefixlen, asn, protect_children)) - v.append({'prefix': str(rng), 'max_prefixlen': max_prefixlen, - 'asn': asn}) + v.append({'prefix': str(rng), 'max_prefixlen': max_prefixlen, + 'asn': asn}) query |= Q(prefix_min__gte=rng.min, prefix_max__lte=rng.max) @@ -903,14 +886,10 @@ def roa_import(request): if request.method == 'POST': form = forms.ImportCSVForm(request.POST, request.FILES) if form.is_valid(): - import tempfile - tmp = tempfile.NamedTemporaryFile(suffix='.csv', prefix='roas', delete=False) - tmp.write(request.FILES['csv'].read()) - tmp.close() z = Zookeeper(handle=request.session['handle'], disable_signal_handlers=True) try: - z.load_roa_requests(tmp.name) + z.load_roa_requests(request.FILES['csv']) except rpki.csv_utils.BadCSVSyntax as e: messages.error(request, 'CSV has bad syntax: %s' % (e,)) @@ -918,8 +897,6 @@ def roa_import(request): z.run_rpkid_now() messages.success(request, 'Successfully imported ROAs.') return redirect(dashboard) - finally: - os.unlink(tmp.name) else: form = forms.ImportCSVForm() return render(request, 'app/import_resource_form.html', { @@ -939,7 +916,7 @@ def roa_export(request): # each roa prefix gets a unique group so rpkid will issue separate roas for group, roapfx in enumerate(ROARequestPrefix.objects.filter(roa_request__issuer=conf)): csv_writer.writerow([str(roapfx.as_roa_prefix()), roapfx.roa_request.asn, '%s-%d' % (conf.handle, group)]) - resp = http.HttpResponse(f.getvalue(), mimetype='application/csv') + resp = http.HttpResponse(f.getvalue(), content_type='application/csv') resp['Content-Disposition'] = 'attachment; filename=roas.csv' return resp @@ -1215,7 +1192,7 @@ def resource_holder_delete(request, pk): form = forms.Empty(request.POST) if form.is_valid(): z = Zookeeper(handle=conf.handle, logstream=log) - z.delete_self() + z.delete_tenant() z.synchronize_deleted_ca() return redirect(resource_holder_list) else: @@ -1239,22 +1216,13 @@ def resource_holder_create(request): zk_child = Zookeeper(handle=handle, logstream=log) identity_xml = zk_child.initialize_resource_bpki() if parent: - # FIXME etree_wrapper should allow us to deal with file objects - t = NamedTemporaryFile(delete=False) - t.close() - - identity_xml.save(t.name) zk_parent = Zookeeper(handle=parent.handle, logstream=log) - parent_response, _ = zk_parent.configure_child(t.name) - parent_response.save(t.name) + parent_response, _ = zk_parent.configure_child(identity_xml) zk_parent.synchronize_ca() - repo_req, _ = zk_child.configure_parent(t.name) - repo_req.save(t.name) - repo_resp, _ = zk_parent.configure_publication_client(t.name) - repo_resp.save(t.name) + repo_req, _ = zk_child.configure_parent(parent_response) + repo_resp, _ = zk_parent.configure_publication_client(repo_req) zk_parent.synchronize_pubd() - zk_child.configure_repository(t.name) - os.remove(t.name) + zk_child.configure_repository(repo_resp) zk_child.synchronize_ca() return redirect(resource_holder_list) else: @@ -1460,14 +1428,9 @@ class RouterImportView(FormView): def form_valid(self, form): conf = get_conf(self.request.user, self.request.session['handle']) - tmpf = NamedTemporaryFile(prefix='import', suffix='.xml', - delete=False) - tmpf.write(form.cleaned_data['xml'].read()) - tmpf.close() z = Zookeeper(handle=conf.handle, disable_signal_handlers=True) - z.add_router_certificate_request(tmpf.name) + z.add_router_certificate_request(form.cleaned_data['xml']) z.run_rpkid_now() - os.remove(tmpf.name) return super(RouterImportView, self).form_valid(form) def get_context_data(self, **kwargs): |