diff options
Diffstat (limited to 'portal-gui/rpkigui/myrpki')
-rw-r--r-- | portal-gui/rpkigui/myrpki/AllocationTree.py | 148 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/__init__.py | 0 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/admin.py | 52 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/asnset.py | 40 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/forms.py | 147 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/glue.py.in | 139 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/misc.py | 47 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/models.py | 207 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/urls.py | 50 | ||||
-rw-r--r-- | portal-gui/rpkigui/myrpki/views.py | 557 |
10 files changed, 0 insertions, 1387 deletions
diff --git a/portal-gui/rpkigui/myrpki/AllocationTree.py b/portal-gui/rpkigui/myrpki/AllocationTree.py deleted file mode 100644 index 13936797..00000000 --- a/portal-gui/rpkigui/myrpki/AllocationTree.py +++ /dev/null @@ -1,148 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -from rpkigui.myrpki import misc, models -from rpki import resource_set - -class AllocationTree(object): - '''Virtual class representing a tree of unallocated resource ranges. - Keeps track of which subsets of a resource range have been - allocated.''' - - def __init__(self, resource): - self.resource = resource - self.range = resource.as_resource_range() - self.need_calc = True - - def calculate(self): - if self.need_calc: - self.children = [] - self.alloc = self.__class__.set_type() - self.unalloc = self.__class__.set_type() - - if self.is_allocated(): - self.alloc.append(self.range) - else: - for child in self.resource.children.all(): - c = self.__class__(child) - if c.unallocated(): - self.children.append(c) - self.alloc = self.alloc.union(c.alloc) - total = self.__class__.set_type() - total.append(self.range) - self.unalloc = total.difference(self.alloc) - self.need_calc=False - - def unallocated(self): - self.calculate() - return self.unalloc - - def as_ul(self): - '''Returns a string of the tree as an unordered HTML list.''' - s = [] - s.append('<a href="%s">%s</a>' % (self.resource.get_absolute_url(), self.resource)) - - # when the unallocated range is a subset of the current range, - # display the missing ranges - u = self.unallocated() - if len(u) != 1 or self.range != u[0]: - s.append(' (missing: ') - s.append(', '.join(str(x) for x in u)) - s.append(')') - - # quick access links - if self.resource.parent: - s.append(' | <a href="%s/delete">delete</a>' % (self.resource.get_absolute_url(),)) - s.append(' | <a href="%s/allocate">give</a>' % (self.resource.get_absolute_url(),)) - if self.range.min != self.range.max: - s.append(' | <a href="%s/split">split</a>' % (self.resource.get_absolute_url(),)) - # add type-specific actions - a = self.supported_actions() - if a: - s.extend(a) - - if self.children: - s.append('\n<ul>\n') - for c in self.children: - s.append('<li>' + c.as_ul()) - s.append('\n</ul>') - - return ''.join(s) - - def supported_actions(self): - '''Virtual method allowing subclasses to add actions to the HTML list.''' - return None - - @classmethod - def from_resource_range(cls, resource): - if isinstance(resource, resource_set.resource_range_as): - return AllocationTreeAS(resource) - if isinstance(resource, resoute_set.resource_range_ip): - return AllocationTreeIP(resource) - raise ValueError, 'Unsupported resource range type' - -class AllocationTreeAS(AllocationTree): - set_type = resource_set.resource_set_as - - def __init__(self, *args, **kwargs): - AllocationTree.__init__(self, *args, **kwargs) - self.conf = misc.top_parent(self.resource).from_cert.all()[0].parent.conf - - def is_allocated(self): - '''Returns true if this AS has been allocated to a child or - used in a ROA request.''' - # FIXME: detect use in ROA requests - - if self.resource.allocated: - return True - - # for individual ASNs - if self.range.min == self.range.max: - # is this ASN used in any roa? - if self.conf.roas.filter(asn=self.range.min): - return True - - return False - -class AllocationTreeIP(AllocationTree): - '''virtual class representing a tree of IP address ranges.''' - - @classmethod - def from_prefix(cls, prefix): - r = prefix.as_resource_range() - if isinstance(r, resource_set.resource_range_ipv4): - return AllocationTreeIPv4(prefix) - elif isinstance(r, resource_set.resource_range_ipv6): - return AllocationTreeIPv6(prefix) - raise ValueError, 'Unsupported IP range type' - - def supported_actions(self): - '''add a link to issue a roa for this IP range''' - return[' | <a href="%s/roa">roa</a>' % (self.resource.get_absolute_url(),)] - - def is_allocated(self): - '''Return True if this IP range is allocated to a child or used - in a ROA request.''' - return self.resource.allocated or self.resource.roa_requests.count() - -class AllocationTreeIPv4(AllocationTreeIP): - set_type = resource_set.resource_set_ipv4 - -class AllocationTreeIPv6(AllocationTreeIP): - set_type = resource_set.resource_set_ipv6 - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/__init__.py b/portal-gui/rpkigui/myrpki/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/portal-gui/rpkigui/myrpki/__init__.py +++ /dev/null diff --git a/portal-gui/rpkigui/myrpki/admin.py b/portal-gui/rpkigui/myrpki/admin.py deleted file mode 100644 index b5d7ab66..00000000 --- a/portal-gui/rpkigui/myrpki/admin.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Copyright (C) 2010 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. -""" - -from django import forms -from django.contrib import admin -from rpkigui.myrpki import models - -class ConfAdmin( admin.ModelAdmin ): - pass - -class ChildAdmin( admin.ModelAdmin ): - pass - -class AddressRangeAdmin( admin.ModelAdmin ): - pass - -class AsnAdmin( admin.ModelAdmin ): - pass - -class ParentAdmin( admin.ModelAdmin ): - pass - -class RoaAdmin( admin.ModelAdmin ): - pass - -class ResourceCertAdmin(admin.ModelAdmin): - pass - -class RoaRequestAdmin(admin.ModelAdmin): - pass - -admin.site.register(models.Conf, ConfAdmin) -admin.site.register(models.Child, ChildAdmin) -admin.site.register(models.AddressRange, AddressRangeAdmin) -admin.site.register(models.Asn, AsnAdmin) -admin.site.register(models.Parent, ParentAdmin) -admin.site.register(models.Roa, RoaAdmin) -admin.site.register(models.RoaRequest, RoaRequestAdmin) -admin.site.register(models.ResourceCert, ResourceCertAdmin) diff --git a/portal-gui/rpkigui/myrpki/asnset.py b/portal-gui/rpkigui/myrpki/asnset.py deleted file mode 100644 index 6a2d562c..00000000 --- a/portal-gui/rpkigui/myrpki/asnset.py +++ /dev/null @@ -1,40 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -class asnset(object): - """A set-like object for containing sets of ASN values.""" - v = set() - - def __init__(self, init=None): - """ - May be initialized from a comma separated list of positive integers. - """ - if init: - self.v = set(int(x) for x in init.split(',') if x.strip() != '') - if any([x for x in self.v if x < 0]): - raise ValueError, "Can't contain negative values." - - def __str__(self): - return ','.join(str(x) for x in sorted(self.v)) - - def __iter__(self): - return iter(self.v) - - def add(self, n): - assert isinstance(n, int) - assert n > 0 - self.v.add(n) diff --git a/portal-gui/rpkigui/myrpki/forms.py b/portal-gui/rpkigui/myrpki/forms.py deleted file mode 100644 index 959d5a20..00000000 --- a/portal-gui/rpkigui/myrpki/forms.py +++ /dev/null @@ -1,147 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -from django import forms - -import rpki.ipaddrs - -from rpkigui.myrpki import models, misc -from rpkigui.myrpki.asnset import asnset - -class AddConfForm(forms.Form): - handle = forms.CharField(required=True, - help_text='your handle for your rpki instance') - run_rpkid = forms.BooleanField(required=False, initial=True, - label='Run rpkid?', - help_text='do you want to run your own instance of rpkid?') - rpkid_server_host = forms.CharField(initial='rpkid.example.org', - label='rpkid hostname', - help_text='publicly visible hostname for your rpkid instance') - rpkid_server_port = forms.IntegerField(initial=4404, - label='rpkid port') - run_pubd = forms.BooleanField(required=False, initial=False, - label='Run pubd?', - help_text='do you want to run your own instance of pubd?') - pubd_server_host = forms.CharField(initial='pubd.example.org', - label='pubd hostname', - help_text='publicly visible hostname for your pubd instance') - pubd_server_port = forms.IntegerField(initial=4402, label='pubd port') - pubd_contact_info = forms.CharField(initial='repo-man@rpki.example.org', - label='Pubd contact', - help_text='email address for the operator of your pubd instance') - -class ImportForm(forms.Form): - '''Form used for uploading parent/child identity xml files''' - handle = forms.CharField() - xml = forms.FileField() - -def PrefixSplitForm(parent, *args, **kwargs): - class _wrapper(forms.Form): - prefix = forms.CharField(max_length=200, help_text='CIDR or range') - - def clean(self): - p = self.cleaned_data.get('prefix') - try: - r = misc.parse_resource_range(p) - except ValueError, err: - print err - raise forms.ValidationError, 'invalid prefix or range' - # we get AssertionError is the range is misordered (hi before lo) - except AssertionError, err: - print err - raise forms.ValidationError, 'invalid prefix or range' - pr = parent.as_resource_range() - if r.min < pr.min or r.max > pr.max: - raise forms.ValidationError, \ - 'range is outside parent range' - if r.min == pr.min and r.max == pr.max: - raise forms.ValidationError, \ - 'range is equal to parent' - if parent.allocated: - raise forms.ValidationError, 'prefix is assigned to child' - for p in parent.children.all(): - c = p.as_resource_range() - if c.min <= r.min <= c.max or c.min <= r.max <= c.max: - raise forms.ValidationError, \ - 'overlap with another child prefix: %s' % (c,) - - return self.cleaned_data - return _wrapper(*args, **kwargs) - -def PrefixAllocateForm(iv, child_set, *args, **kwargs): - class _wrapper(forms.Form): - child = forms.ModelChoiceField(initial=iv, queryset=child_set, - required=False) - return _wrapper(*args, **kwargs) - -def PrefixRoaForm(prefix, *args, **kwargs): - prefix_range = prefix.as_resource_range() - - class _wrapper(forms.Form): - asns = forms.CharField(max_length=200, required=False, - help_text='Comma-separated list of ASNs') - max_length = forms.IntegerField(required=False, - min_value=prefix_range.prefixlen(), - max_value=prefix_range.datum_type.bits) - - def clean_max_length(self): - v = self.cleaned_data.get('max_length') - if not v: - v = prefix_range.prefixlen() - return v - - def clean_asns(self): - try: - v = asnset(self.cleaned_data.get('asns')) - return ','.join(str(x) for x in sorted(v)) - except ValueError: - raise forms.ValidationError, \ - 'Must be a list of integers separated by commas.' - return self.cleaned_data['asns'] - - def clean(self): - if not prefix.is_prefix(): - raise forms.ValidationError, \ - '%s can not be represented as a prefix.' % (prefix,) - if prefix.allocated: - raise forms.ValidationError, \ - 'Prefix is allocated to a child.' - return self.cleaned_data - - return _wrapper(*args, **kwargs) - -def PrefixDeleteForm(prefix, *args, **kwargs): - class _wrapped(forms.Form): - delete = forms.BooleanField(label='Yes, I want to delete this prefix:') - - def clean(self): - v = self.cleaned_data.get('delete') - if v: - if not prefix.parent: - raise forms.ValidationError, \ - 'Can not delete prefix received from parent' - if prefix.allocated: - raise forms.ValidationError, 'Prefix is allocated to child' - if prefix.roa_requests.all(): - raise forms.ValidationError, 'Prefix is used in your ROAs' - if prefix.children.all(): - raise forms.ValidationError, 'Prefix has been subdivided' - return self.cleaned_data - - return _wrapped(*args, **kwargs) - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/glue.py.in b/portal-gui/rpkigui/myrpki/glue.py.in deleted file mode 100644 index 897b23d4..00000000 --- a/portal-gui/rpkigui/myrpki/glue.py.in +++ /dev/null @@ -1,139 +0,0 @@ -""" -Copyright (C) 2010 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. -""" - -# $Id$ - -from __future__ import with_statement - -import os -import os.path -import csv -import stat -import sys - -from django.db.models import F - -import rpki -import rpki.config - -from rpkigui.myrpki import models - -confdir = '@CONFDIR@' - -def conf(handle): - return confdir + '/' + handle - -#def form_to_conf(data): -# """Write out a rpki.conf based on the given form data.""" -# handle = data['handle'] -# confdir = settings.MYRPKI_DATA_DIR + '/' + handle -# if os.path.exists(confdir): -# raise RuntimeError, '%s: directory already exists!' % (confdir, ) -# os.makedirs(confdir) -# template = open(settings.MYRPKI_DATA_DIR + '/examples/rpki.conf', 'r').read() -# # stuff the appropriate output directory into the dict -# data['MYRPKI_DATA_DIR'] = confdir -# with open(confdir + '/rpki.conf', 'w') as conf: -# print >>conf, template % data -# invoke_rpki(handle, ['initialize']) - -def invoke_rpki(handle, args): - """Invoke the myrpki cli for the specified configuration.""" - myrpki_dir = confdir(handle) - config = myrpki_dir + '/rpki.conf' - # default rpki.conf uses relative paths, so chdir() to the repo first - cmd = 'cd %s && @MYRPKI@ %s' % (myrpki_dir, ' '.join(['--config=' + config] + args)) - print >>sys.stderr, 'invoking', cmd - os.system(cmd) - -def read_file_from_handle(handle, fname): - """read a filename relative to the directory for the given resource handle. returns - a tuple of (content, mtime)""" - with open(conf(handle) + '/' + fname, 'r') as fp: - data = fp.read() - mtime = os.fstat(fp.fileno())[stat.ST_MTIME] - return data, mtime - -#def read_identity(handle): -# fname = settings.MYRPKI_DATA_DIR + '/' + handle + '/entitydb/identity.xml' -# with open(fname, 'r') as fp: -# data = fp.read() -# return data -read_identity = lambda h: read_file_from_handle(h, 'entitydb/identity.xml')[0] - -def read_child_response(handle, child): - fname = '%s/entitydb/children/%s.xml' % (conf(handle), child) - with open(fname, 'r') as fp: - data = fp.read() - return data - -# FIXME - remove this once rpki.myrpki.csv_writer is an object with a -# .file field -def csv_writer(f): - return csv.writer(f, dialect = csv.get_dialect("excel-tab")) - -def output_asns(path, handle): - '''Write out csv file containing asns delegated to my children.''' - qs = models.Asn.objects.filter(lo=F('hi'), allocated__in=handle.children.all()) - with open(path, 'w') as f: - w = csv_writer(f) - w.writerows([asn.allocated.handle, asn.lo] for asn in qs) - -def output_prefixes(path, handle): - '''Write out csv file containing prefixes delegated to my children.''' - qs = models.AddressRange.objects.filter(allocated__in=handle.children.all()) - with open(path, 'w') as f: - w = csv_writer(f) - w.writerows([p.allocated.handle, p.as_resource_range()] for p in qs) - -def output_roas(path, handle): - '''Write out csv file containing my roas.''' - qs = models.RoaRequest.objects.filter(roa__in=handle.roas.all()) - with open(path, 'w') as f: - w = csv_writer(f) - w.writerows([req.as_roa_prefix(), req.roa.asn, - '%s-group-%d' % (handle.handle, req.roa.pk)] for req in qs) - -def configure_daemons(handle): - args = ['configure_daemons'] - for hosted in handle.hosting.all(): - args.append(conf(hosted.handle) + '/myrpki.xml') - invoke_rpki(handle.handle, args) - -def configure_resources(handle): - '''Write out the csv files and invoke the myrpki.py command line tool.''' - # chdir to the repo dir since the default rpki.conf uses relative - # pathnames.. - os.chdir(conf(handle.handle)) - cfg = rpki.config.parser('rpki.conf', 'myrpki') - output_asns(cfg.get('asn_csv'), handle) - output_prefixes(cfg.get('prefix_csv'), handle) - output_roas(cfg.get('roa_csv'), handle) - run_rpkidemo = cfg.getboolean('run_rpkidemo', False) - if not run_rpkidemo: - run_rpkid = cfg.getboolean('run_rpkid') - if run_rpkid: - configure_daemons(handle) - else: - invoke_rpki(handle.handle, ['configure_resources']) - - # send the myrpki.xml to the rpkid hosting me - configure_daemons(handle.host) - - # process the response - invoke_rpki(handle.handle, ['configure_resources']) - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/misc.py b/portal-gui/rpkigui/myrpki/misc.py deleted file mode 100644 index 5d3cba93..00000000 --- a/portal-gui/rpkigui/myrpki/misc.py +++ /dev/null @@ -1,47 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -import rpki.resource_set -import rpki.ipaddrs - -def str_to_range(lo, hi): - """Convert IP address strings to resource_range_ip.""" - x = rpki.ipaddrs.parse(lo) - y = rpki.ipaddrs.parse(hi) - assert type(x) == type(y) - if isinstance(x, rpki.ipaddrs.v4addr): - return rpki.resource_set.resource_range_ipv4(x, y) - else: - return rpki.resource_set.resource_range_ipv6(x, y) - -def parse_resource_range(s): - '''Parse an IPv4/6 resource range.''' - # resource_set functions only accept str - if isinstance(s, unicode): - s = s.encode() - try: - return rpki.resource_set.resource_range_ipv4.parse_str(s) - except ValueError: - return rpki.resource_set.resource_range_ipv6.parse_str(s) - -def top_parent(prefix): - '''Returns the topmost resource from which the specified argument derives''' - while prefix.parent: - prefix = prefix.parent - return prefix - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/models.py b/portal-gui/rpkigui/myrpki/models.py deleted file mode 100644 index 7db5ef1d..00000000 --- a/portal-gui/rpkigui/myrpki/models.py +++ /dev/null @@ -1,207 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -import socket - -from django.db import models -from django.contrib.auth.models import User - -from rpkigui.myrpki.misc import str_to_range - -import rpki.resource_set -import rpki.exceptions - -class HandleField(models.CharField): - def __init__(self, **kwargs): - models.CharField.__init__(self, max_length=255, **kwargs) - -class IPAddressField(models.CharField): - def __init__( self, **kwargs ): - models.CharField.__init__(self, max_length=40, **kwargs) - -class Conf(models.Model): - '''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> - in the rpkid schema.''' - handle = HandleField(unique=True, db_index=True) - owner = models.ManyToManyField(User) - - # NULL if self-hosted, otherwise the conf that is hosting us - host = models.ForeignKey('Conf', related_name='hosting', null=True) - - def __unicode__(self): - return self.handle - -class AddressRange(models.Model): - '''An address range/prefix.''' - lo = IPAddressField(blank=False) - hi = IPAddressField(blank=False) - # parent address range - parent = models.ForeignKey('AddressRange', related_name='children', - blank=True, null=True) - # child to which this resource is delegated - allocated = models.ForeignKey('Child', related_name='address_range', - blank=True, null=True) - - def __unicode__(self): - if self.lo == self.hi: - return u"%s" % (self.lo,) - - try: - # pretty print cidr - return unicode(self.as_resource_range()) - except socket.error, err: - print err - # work around for bug when hi/lo get reversed - except AssertionError, err: - print err - return u'%s - %s' % (self.lo, self.hi) - - @models.permalink - def get_absolute_url(self): - return ('rpkigui.myrpki.views.address_view', [str(self.pk)]) - - def as_resource_range(self): - '''Convert to rpki.resource_set.resource_range_ip.''' - return str_to_range(self.lo, self.hi) - - def is_prefix(self): - '''Returns True if this address range can be represented as a - prefix.''' - try: - self.as_resource_range().prefixlen() - except rpki.exceptions.MustBePrefix, err: - print err - return False - return True - -class RoaRequest(models.Model): - roa = models.ForeignKey('Roa', related_name='from_roa_request') - max_length = models.IntegerField() - prefix = models.ForeignKey('AddressRange', related_name='roa_requests') - - def __unicode__(self): - return u'roa request for asn %d on %s-%d' % (self.roa.asn, self.prefix, - self.max_length) - - def as_roa_prefix(self): - '''Convert to a rpki.resouce_set.roa_prefix subclass.''' - r = self.prefix.as_resource_range() - if isinstance(r, rpki.resource_set.resource_set_ipv4): - return rpki.resource_set.roa_prefix_ipv4(r.min, r.prefixlen(), - self.max_length) - else: - return rpki.resource_set.roa_prefix_ipv6(r.min, r.prefixlen(), - self.max_length) - -class Asn(models.Model): - '''An ASN or range thereof.''' - lo = models.IntegerField(blank=False) - hi = models.IntegerField(blank=False) - # parent asn range - parent = models.ForeignKey('Asn', related_name='children', - blank=True, null=True) - # child to which this resource is delegated - allocated = models.ForeignKey('Child', related_name='asn', - blank=True, null=True) - - def __unicode__(self): - if self.lo == self.hi: - return u"ASN %d" % (self.lo,) - else: - return u"ASNs %d - %d" % (self.lo, self.hi) - - @models.permalink - def get_absolute_url(self): - return ('rpkigui.myrpki.views.asn_view', [str(self.pk)]) - - def as_resource_range(self): - # we force conversion to long() here because resource_range_as() wants - # the type of both arguments to be identical, and models.IntegerField - # will be a long when the value is large - return rpki.resource_set.resource_range_as(long(self.lo), long(self.hi)) - -class Child(models.Model): - conf = models.ForeignKey(Conf, related_name='children') - handle = HandleField() # parent's name for child - - def __unicode__(self): - return u"%s's child %s" % (self.conf, self.handle) - - @models.permalink - def get_absolute_url(self): - return ('rpkigui.myrpki.views.child_view', [self.handle]) - - class Meta: - verbose_name_plural = "children" - # children of a specific configuration should be unique - unique_together = ('conf', 'handle') - -class Parent(models.Model): - conf = models.ForeignKey(Conf, related_name='parents') - handle = HandleField() # my name for this parent - - def __unicode__(self): - return u"%s's parent %s" % (self.conf, self.handle) - - @models.permalink - def get_absolute_url(self): - return ('rpkigui.myrpki.views.parent_view', [self.handle]) - - class Meta: - # parents of a specific configuration should be unique - unique_together = ('conf', 'handle') - -class ResourceCert(models.Model): - parent = models.ForeignKey(Parent, related_name='resources') - - # resources granted from my parent - asn = models.ManyToManyField(Asn, related_name='from_cert', blank=True, - null=True) - address_range = models.ManyToManyField(AddressRange, - related_name='from_cert', blank=True, null=True) - - # unique id for this resource certificate - # FIXME: URLField(verify_exists=False) doesn't seem to work - the admin - # editor won't accept a rsync:// scheme as valid - uri = models.CharField(max_length=200) - - # certificate validity period - not_before = models.DateTimeField() - not_after = models.DateTimeField() - - def __unicode__(self): - return u"%s's resource cert from parent %s" % (self.parent.conf.handle, - self.parent.handle) - -class Roa(models.Model): - '''Maps an ASN to the set of prefixes it can originate routes for. - This differs from a real ROA in that prefixes from multiple - parents/resource certs can be selected. The glue module contains - code to split the ROAs into groups by common resource certs.''' - - conf = models.ForeignKey(Conf, related_name='roas') - asn = models.IntegerField() - active = models.BooleanField() - - # the resource cert from which all prefixes for this roa are derived - cert = models.ForeignKey(ResourceCert, related_name='roas') - - def __unicode__(self): - return u"%s's ROA for %d" % (self.conf, self.asn) - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/urls.py b/portal-gui/rpkigui/myrpki/urls.py deleted file mode 100644 index 96d93e2d..00000000 --- a/portal-gui/rpkigui/myrpki/urls.py +++ /dev/null @@ -1,50 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -from django.conf.urls.defaults import * -from django.views.generic.list_detail import object_list -from rpkigui.myrpki import views - -urlpatterns = patterns('', - (r'^$', views.dashboard), -# (r'^conf/add$', views.conf_add), - (r'^conf/export$', views.conf_export), - (r'^conf/list$', views.conf_list), - (r'^conf/select$', views.conf_select), -# (r'^import/parent$', views.parent_import), -# (r'^import/child$', views.child_import), - (r'^parent/(?P<parent_handle>[^/]+)$', views.parent_view), - (r'^child/(?P<child_handle>[^/]+)$', views.child_view), -# (r'^parent/(?P<parent_handle>[^/]+)/address$', views.parent_address), -# (r'^parent/(?P<parent_handle>[^/]+)/asn$', views.parent_asn), - (r'^address/(?P<pk>\d+)$', views.address_view), - (r'^address/(?P<pk>\d+)/split$', views.prefix_split_view), - (r'^address/(?P<pk>\d+)/allocate$', views.prefix_allocate_view), - (r'^address/(?P<pk>\d+)/roa$', views.prefix_roa_view), - (r'^address/(?P<pk>\d+)/delete$', views.prefix_delete_view), - (r'^asn/(?P<pk>\d+)$', views.asn_view), - (r'^asn/(?P<pk>\d+)/allocate$', views.asn_allocate_view), - (r'^roa/(?P<pk>\d+)/delete$', views.roa_request_delete_view), - (r'^demo/down/asns/(?P<self_handle>[^/]+)$', views.download_asns), - (r'^demo/down/prefixes/(?P<self_handle>[^/]+)$', views.download_prefixes), - (r'^demo/down/roas/(?P<self_handle>[^/]+)$', views.download_roas), - (r'^upload-parent-request/(?P<self_handle>[^/]+)$', views.upload_parent_request), - (r'^upload-repository-request/(?P<self_handle>[^/]+)$', views.upload_repository_request), - (r'^upload-myrpki-xml/(?P<self_handle>[^/]+)$', views.upload_myrpki_xml), -) - -# vim:sw=4 ts=8 expandtab diff --git a/portal-gui/rpkigui/myrpki/views.py b/portal-gui/rpkigui/myrpki/views.py deleted file mode 100644 index f15ebbdd..00000000 --- a/portal-gui/rpkigui/myrpki/views.py +++ /dev/null @@ -1,557 +0,0 @@ -# $Id$ -""" -Copyright (C) 2010 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. -""" - -import email.utils -import os -import os.path -import tempfile -import sys - -from django.contrib.auth.decorators import login_required -from django.shortcuts import get_object_or_404, render_to_response -from django.utils.http import urlquote -from django.template import RequestContext -from django.db import IntegrityError -from django import http -from django.views.generic.list_detail import object_list -from django.views.decorators.csrf import csrf_exempt -from django.conf import settings -from django.core.urlresolvers import reverse - -from rpkigui.myrpki import models, forms, glue, misc, AllocationTree -from rpkigui.myrpki.asnset import asnset - -debug = False - -# For each type of object, we have a detail view, a create view and -# an update view. We heavily leverage the generic views, only -# adding our own idea of authorization. - -def handle_required(f): - @login_required - def wrapped_fn(request, *args, **kwargs): - if 'handle' not in request.session: - if request.user.is_superuser: - conf = models.Conf.objects.all() - else: - conf = models.Conf.objects.filter(owner=request.user) - if conf.count() == 1: - handle = conf[0] - elif conf.count() == 0: - return render('myrpki/conf_empty.html', {}, request) - #return http.HttpResponseRedirect('/myrpki/conf/add') - else: - # Should reverse the view for this instead of hardcoding - # the URL. - return http.HttpResponseRedirect( - reverse(conf_list) + '?next=' + urlquote(request.get_full_path())) - request.session[ 'handle' ] = handle - return f(request, *args, **kwargs) - return wrapped_fn - -def render(template, context, request): - return render_to_response(template, context, - context_instance=RequestContext(request)) - -@handle_required -def dashboard(request): - '''The user's dashboard.''' - handle = request.session[ 'handle' ] - # ... pick out data for the dashboard and return it - # my parents - # the resources that my parents have given me - # the resources that I have accepted from my parents - # my children - # the resources that I have given my children - # my roas - - # get list of ASNs used in my ROAs - roa_asns = [r.asn for r in handle.roas.all()] - asns=[] - for a in models.Asn.objects.filter(from_cert__parent__in=handle.parents.all()): - f = AllocationTree.AllocationTreeAS(a) - if f.unallocated(): - asns.append(f) - - prefixes = [] - for p in models.AddressRange.objects.filter(from_cert__parent__in=handle.parents.all()): - f = AllocationTree.AllocationTreeIP.from_prefix(p) - if f.unallocated(): - prefixes.append(f) - - asns.sort(key=lambda x: x.range.min) - prefixes.sort(key=lambda x: x.range.min) - - return render('myrpki/dashboard.html', { 'conf': handle, 'asns': asns, - 'ars': prefixes }, request) - -#@login_required -#def conf_add(request): -# '''Allow the user to create a new configuration.''' -# errors = [] -# if request.method == 'POST': -# form = forms.AddConfForm(request.POST) -# if form.is_valid(): -# try: -# handle = form.cleaned_data['handle'] -# # ensure this user is in the group for this handle -# grps = request.user.groups.filter(name=handle) -# if len(grps) == 0: -# errors.append( -# 'You are not in the proper group for that handle.') -# else: -# conf = models.Conf.objects.create( -# handle=form.cleaned_data['handle'], owner=grps[0]) -# conf.save() -# glue.form_to_conf(form.cleaned_data) -# return http.HttpResponseRedirect('/myrpki/') -# # data model will ensure the handle is unique -# except IntegrityError, e: -# print e -# errors.append('That handle already exists.') -# else: -# errors.append("The form wasn't valid.") -# else: -# form = forms.AddConfForm() -# return render_to_response('myrpki/add_conf.html', -# { 'form': form, 'errors': errors }) - -@login_required -def conf_list(request): - """Allow the user to select a handle.""" - if request.user.is_superuser: - queryset = models.Conf.objects.all() - else: - queryset = models.Conf.objects.filter(owner=request.user) - return object_list(request, queryset, - template_name='myrpki/conf_list.html', template_object_name='conf', extra_context={ 'select_url' : reverse(conf_select) }) - -@login_required -def conf_select(request): - '''Change the handle for the current session.''' - if not 'handle' in request.GET: - return http.HttpResponseRedirect('/myrpki/conf/select') - handle = request.GET['handle'] - next_url = request.GET.get('next', reverse(dashboard)) - if next_url == '': - next_url = reverse(dashboard) - - if request.user.is_superuser: - conf = models.Conf.objects.filter(handle=handle) - else: - # since the handle is passed in as a parameter, need to verify that - # the user is actually in the group - conf = models.Conf.objects.filter(handle=handle, - owner=request.user) - if conf: - request.session['handle'] = conf[0] - return http.HttpResponseRedirect(next_url) - - return http.HttpResponseRedirect(reverse(conf_list) + '?next=' + next_url) - -def serve_xml(content, basename): - resp = http.HttpResponse(content , mimetype='application/xml') - resp['Content-Disposition'] = 'attachment; filename=%s.xml' % (basename, ) - return resp - -@handle_required -def conf_export(request): - """Return the identity.xml for the current handle.""" - handle = request.session['handle'] - return serve_xml(glue.read_identity(handle.handle), 'identity') - -@handle_required -def parent_import(request): - handle = request.session['handle'].handle - errs = [] - if request.method == 'POST': - form = forms.ImportForm(request.POST, request.FILES) - if form.is_valid(): - input_file = tempfile.NamedTemporaryFile(delete=False) - try: - parent_handle = form.cleaned_data['handle'] - parent = models.Parent( - conf=request.session['handle'], handle=parent_handle) - parent.save() - - input_file.write(request.FILES['xml'].read()) - input_file.close() - - args = ['configure_parent', '--parent_handle=' + parent_handle, - input_file.name] - glue.invoke_rpki(handle, args) - - return http.HttpResponseRedirect('/myrpki/') - except IntegrityError, e: - print e - errs.append('A parent with that handle already exists.') - finally: - os.remove(input_file.name) - else: - print 'invalid form' - errs.append('The form was invalid.') - else: - form = forms.ImportForm() - return render('myrpki/xml_import.html', { 'form': form, - 'kind': 'parent', 'post_url': '/myrpki/import/parent', - 'errors': errs }, request) - -@handle_required -def parent_view(request, parent_handle): - """Detail view for a particular parent.""" - handle = request.session['handle'] - parent = get_object_or_404(handle.parents, handle__exact=parent_handle) - return render('myrpki/parent_view.html', { 'parent': parent }, request) - -@handle_required -def child_import(request): - handle = request.session['handle'].handle - if request.method == 'POST': - form = forms.ImportForm(request.POST, request.FILES) - if form.is_valid(): - input_file = tempfile.NamedTemporaryFile(delete=False) - try: - child_handle = form.cleaned_data['handle'] - child = models.Child( - conf=request.session['handle'], handle=child_handle, - validity=form.cleaned_data['validity']) - child.save() - - input_file.write(request.FILES['xml'].read()) - input_file.close() - args = ['configure_child', '--child_handle=' + child_handle, - input_file.name] - glue.invoke_rpki(handle, args) - - # send response back to user - return serve_xml(glue.read_child_response(handle, - child_handle), child_handle) - finally: - os.remove(input_file.name) - else: - form = forms.ImportForm() - return render('myrpki/xml_import.html', - { 'form': form, 'kind': 'child', - 'post_url': '/myrpki/import/child'}, request) - -def get_parents_or_404(handle, obj): - '''Return the Parent object(s) that the given address range derives - from, or raise a 404 error.''' - cert_set = misc.top_parent(obj).from_cert.filter(parent__in=handle.parents.all()) - if cert_set.count() == 0: - raise http.Http404, 'Object is not delegated from any parent' - return [c.parent for c in cert_set] - -@handle_required -def asn_view(request, pk): - '''view/subdivide an asn range.''' - handle = request.session['handle'] - obj = get_object_or_404(models.Asn.objects, pk=pk) - # ensure this resource range belongs to a parent of the current conf - parent_set = get_parents_or_404(handle, obj) - roas = handle.roas.filter(asn=obj.lo) # roas which contain this asn - unallocated = AllocationTree.AllocationTreeAS(obj).unallocated() - - return render('myrpki/asn_view.html', - { 'asn': obj, 'parent': parent_set, 'roas': roas, - 'unallocated' : unallocated }, request) - -@handle_required -def child_view(request, child_handle): - '''Detail view of child for the currently selected handle.''' - handle = request.session['handle'] - child = get_object_or_404(handle.children, handle__exact=child_handle) - - return render('myrpki/child_view.html', { 'child': child }, request) - -class PrefixView(object): - '''Extensible view for address ranges/prefixes. This view can be - subclassed to add form handling for editing the prefix.''' - - def __init__(self, request, pk, form_class=None): - self.handle = request.session['handle'] - self.obj = get_object_or_404(models.AddressRange.objects, pk=pk) - # ensure this resource range belongs to a parent of the current conf - self.parent_set = get_parents_or_404(self.handle, self.obj) - self.form = None - self.form_class = form_class - self.request = request - - def __call__(self, *args, **kwargs): - if self.request.method == 'POST': - resp = self.handle_post() - else: - resp = self.handle_get() - - # allow get/post handlers to return a custom response - if resp: - return resp - - u = AllocationTree.AllocationTreeIP.from_prefix(self.obj).unallocated() - - return render('myrpki/prefix_view.html', - { 'addr': self.obj, 'parent': self.parent_set, 'unallocated': u, 'form': self.form }, - self.request) - - def handle_get(self): - '''Virtual method for extending GET handling. Default action is - to call the form class constructor with the prefix object.''' - if self.form_class: - self.form = self.form_class(self.obj) - - def form_valid(self): - '''Virtual method for handling a valid form. Called by the default - implementation of handle_post().''' - pass - - def handle_post(self): - '''Virtual method for extending POST handling. Default implementation - creates a form object using the form_class in the constructor and passing - the prefix object. If the form's is_valid() method is True, it then - invokes this class's form_valid() method.''' - resp = None - if self.form_class: - self.form = self.form_class(self.obj, self.request.POST) - if self.form.is_valid(): - resp = self.form_valid() - return resp - -@handle_required -def address_view(request, pk): - return PrefixView(request, pk)() - -class PrefixSplitView(PrefixView): - '''Class for handling the prefix split form.''' - def form_valid(self): - r = misc.parse_resource_range(self.form.cleaned_data['prefix']) - obj = models.AddressRange(lo=str(r.min), hi=str(r.max), parent=self.obj) - obj.save() - return http.HttpResponseRedirect(obj.get_absolute_url()) - -@handle_required -def prefix_split_view(request, pk): - return PrefixSplitView(request, pk, form_class=forms.PrefixSplitForm)() - -class PrefixAllocateView(PrefixView): - '''Class to handle the allocation to child form.''' - def handle_get(self): - self.form = forms.PrefixAllocateForm( - self.obj.allocated.pk if self.obj.allocated else None, - self.handle.children.all()) - - def handle_post(self): - self.form = forms.PrefixAllocateForm(None, self.handle.children.all(), self.request.POST) - if self.form.is_valid(): - self.obj.allocated = self.form.cleaned_data['child'] - self.obj.save() - glue.configure_resources(self.handle) - return http.HttpResponseRedirect(self.obj.get_absolute_url()) - -@handle_required -def prefix_allocate_view(request, pk): - return PrefixAllocateView(request, pk)() - -def add_roa_requests(handle, prefix, asns, max_length): - for asid in asns: - if debug: - print 'searching for a roa for AS %d containing %s-%d' % (asid, prefix, max_length) - req_set = prefix.roa_requests.filter(roa__asn=asid, max_length=max_length) - if not req_set: - if debug: - print 'no roa for AS %d containing %s-%d' % (asid, prefix, max_length) - - # find ROAs for prefixes derived from the same resource cert - # as this prefix - certs = misc.top_parent(prefix).from_cert.all() - roa_set = handle.roas.filter(asn=asid, cert__in=certs) - - # FIXME: currently only creates a ROA/request for the first - # resource cert, not all of them - if roa_set: - roa = roa_set[0] - else: - if debug: - print 'creating new roa for AS %d containg %s-%d' % (asid, prefix, max_length) - # no roa is present for this ASN, create a new one - roa = models.Roa.objects.create(asn=asid, conf=handle, - active=False, cert=certs[0]) - roa.save() - - req = models.RoaRequest.objects.create(prefix=prefix, roa=roa, - max_length=max_length) - req.save() - -class PrefixRoaView(PrefixView): - '''Class for handling the ROA creation form.''' - def form_valid(self): - asns = asnset(self.form.cleaned_data['asns']) - add_roa_requests(self.handle, self.obj, asns, self.form.cleaned_data['max_length']) - glue.configure_resources(self.handle) - return http.HttpResponseRedirect(self.obj.get_absolute_url()) - -@handle_required -def prefix_roa_view(request, pk): - return PrefixRoaView(request, pk, form_class=forms.PrefixRoaForm)() - -class PrefixDeleteView(PrefixView): - def form_valid(self): - if self.form.cleaned_data['delete']: - self.obj.delete() - return http.HttpResponseRedirect('/myrpki/') - -@handle_required -def prefix_delete_view(request, pk): - return PrefixDeleteView(request, pk, form_class=forms.PrefixDeleteForm)() - -@handle_required -def roa_request_delete_view(request, pk): - '''Remove a roa request from a particular prefix.''' - handle = request.session['handle'] - obj = get_object_or_404(models.RoaRequest.objects, pk=pk) - prefix = obj.prefix - # ensure this resource range belongs to a parent of the current conf - parent_set = get_parents_or_404(handle, prefix) - - roa = obj.roa - obj.delete() - if not roa.from_roa_request.all(): - roa.delete() - glue.configure_resources(handle) - - return http.HttpResponseRedirect(prefix.get_absolute_url()) - -@handle_required -def asn_allocate_view(request, pk): - handle = request.session['handle'] - obj = get_object_or_404(models.Asn.objects, pk=pk) - # ensure this resource range belongs to a parent of the current conf - parent_set = get_parents_or_404(handle, obj) - - if request.method == 'POST': - form = forms.PrefixAllocateForm(None, handle.children.all(), request.POST) - if form.is_valid(): - obj.allocated = form.cleaned_data['child'] - obj.save() - glue.configure_resources(handle) - return http.HttpResponseRedirect(obj.get_absolute_url()) - else: - form = forms.PrefixAllocateForm(obj.allocated.pk if obj.allocated else None, - handle.children.all()) - - return render('myrpki/asn_view.html', { 'form': form, - 'asn': obj, 'form': form, 'parent': parent_set }, request) - -# this is similar to handle_required, except that the handle is given in URL -def handle_or_404(request, handle): - "ensure the requested handle is available to this user" - if request.user.is_superuser: - conf_set = models.Conf.objects.filter(handle=handle) - else: - conf_set = models.Conf.objects.filter(owner=request.user, handle=handle) - if not conf_set: - raise http.Http404, 'resource handle not found' - return conf_set[0] - -def serve_file(handle, fname, content_type): - content, mtime = glue.read_file_from_handle(handle, fname) - resp = http.HttpResponse(content , mimetype=content_type) - resp['Content-Disposition'] = 'attachment; filename=%s' % (os.path.basename(fname), ) - resp['Last-Modified'] = email.utils.formatdate(mtime, usegmt=True) - return resp - -@login_required -def download_csv(request, self_handle, fname): - conf = handle_or_404(request, self_handle) - return serve_file(conf.handle, fname + '.csv', 'text/csv') - -def download_asns(request, self_handle): - return download_csv(request, self_handle, 'asns') - -def download_roas(request, self_handle): - return download_csv(request, self_handle, 'roas') - -def download_prefixes(request, self_handle): - return download_csv(request, self_handle, 'prefixes') - -def get_parent_handle(conf): - "determine who my parent is. for now just assume its hardcoded into the django db" - parent_set = models.Parent.objects.filter(conf=conf) - if parent_set: - return parent_set[0].handle - else: - raise http.Http404, 'you have no parents' - -@csrf_exempt -@login_required -def upload_parent_request(request, self_handle): - conf = handle_or_404(request, self_handle) - parent_handle = get_parent_handle(conf) - - if request.method == 'POST': - input_file = tempfile.NamedTemporaryFile(delete=False) - input_file.write(request.raw_post_data) - input_file.close() - - args = ['configure_child', input_file.name ] - glue.invoke_rpki(parent_handle, args) - - os.remove(input_file.name) - - return serve_file(parent_handle, 'entitydb/children/%s.xml' % self_handle, 'application/xml') - -@csrf_exempt -@login_required -def upload_repository_request(request, self_handle): - conf = handle_or_404(request, self_handle) - parent_handle = get_parent_handle(conf) - - if request.method == 'POST': - input_file = tempfile.NamedTemporaryFile(delete=False) - input_file.write(request.raw_post_data) - input_file.close() - - args = ['configure_publication_client', input_file.name ] - glue.invoke_rpki(parent_handle, args) - - os.remove(input_file.name) - - # FIXME: this assumes that the parent is running pubd. the actual filename - # will be different if the parent is not running pubd. see - # rpki.myrpki.do_configure_publication_client() - return serve_file(parent_handle, 'entitydb/pubclients/%s.%s.xml' % (parent_handle, self_handle), 'application/xml') - -@csrf_exempt -@login_required -def upload_myrpki_xml(request, self_handle): - "handles POST of the myrpki.xml file for a given resource handle." - conf = handle_or_404(request, self_handle) - - if request.method == 'POST': - try: - fname = '%s/%s/myrpki.xml' % (settings.MYRPKI_DATA_DIR, self_handle,) - print >>sys.stderr, 'writing ', fname - myrpki_xml = open(fname, 'w') - myrpki_xml.write(request.raw_post_data) - myrpki_xml.close() - - glue.configure_daemons(conf.host) - except: - print >>sys.stderr, ''.join(sys.exc_info()) - - return serve_file(self_handle, 'myrpki.xml', 'application/xml') - -# vim:sw=4 ts=8 expandtab |