aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--portal-gui/rpkigui/myrpki/glue.py2
-rw-r--r--portal-gui/rpkigui/myrpki/misc.py10
-rw-r--r--portal-gui/rpkigui/myrpki/views.py229
-rwxr-xr-xportal-gui/scripts/load_csv.py117
4 files changed, 92 insertions, 266 deletions
diff --git a/portal-gui/rpkigui/myrpki/glue.py b/portal-gui/rpkigui/myrpki/glue.py
index eececa7a..868687a5 100644
--- a/portal-gui/rpkigui/myrpki/glue.py
+++ b/portal-gui/rpkigui/myrpki/glue.py
@@ -7,8 +7,6 @@ import os.path
import math
import rpki
from rpki.myrpki import csv_writer
-from rpki.resource_set import resource_range_ipv4
-from rpki.ipaddrs import v4addr
from django.conf import settings
#def form_to_conf(data):
diff --git a/portal-gui/rpkigui/myrpki/misc.py b/portal-gui/rpkigui/myrpki/misc.py
index 3b54107f..4e0970a6 100644
--- a/portal-gui/rpkigui/myrpki/misc.py
+++ b/portal-gui/rpkigui/myrpki/misc.py
@@ -23,14 +23,4 @@ def str_to_range(lo, hi):
else:
return rpki.resource_set.resource_range_ipv6(x, y)
-#def str_to_roa(lo, hi):
-# """Convert IP address strings to a subclass of roa_prefix."""
-# x = str_to_addr(lo)
-# y = str_to_addr(hi)
-# assert type(x) == type(y)
-# if isinstance(x, rpki.ipaddrs.v4addr):
-# return rpki.resource_set.roa_prefix_ipv4(x, y)
-# else:
-# return rpki.resource_set.roa_prefix_ipv6(x, y)
-
# vim:sw=4 ts=8 expandtab
diff --git a/portal-gui/rpkigui/myrpki/views.py b/portal-gui/rpkigui/myrpki/views.py
index 33502631..24e095f4 100644
--- a/portal-gui/rpkigui/myrpki/views.py
+++ b/portal-gui/rpkigui/myrpki/views.py
@@ -15,7 +15,6 @@ from functools import update_wrapper
import models
import forms
import glue
-from asnset import asnset
from rpkigui.myrpki.misc import str_to_range
from rpkigui.myrpki.asnset import asnset
@@ -45,38 +44,6 @@ def handle_required(f):
return f(request, *args, **kwargs)
return wrapped_fn
-#class handle_required(object):
-# '''A decorator to require picking a configuration. __call__ is
-# decorated with login_required so that we can be sure that the
-# request has a user.
-#
-# We don't support picking the configuration yet -- if multiple
-# configurations match, we redirect to handle_picker, which should
-# allow a staff member to pick any handle.
-# '''
-#
-# def __init__(self, f):
-# self.f = f
-# update_wrapper( self, f )
-#
-# @login_required
-# def __call__(self, request, *args, **kwargs):
-# if 'handle' not in request.session:
-# conf = models.Conf.objects.all().filter(
-# owner__in=request.user.groups.all())
-# if conf.count() == 1:
-# handle = conf[ 0 ]
-# elif conf.count() == 0:
-# return http.HttpResponseRedirect('/myrpki/conf/add')
-# else:
-# # Should reverse the view for this instead of hardcoding
-# # the URL.
-# return http.HttpResponseRedirect(
-# '/myrpki/conf/select?next=%s' %
-# urlquote(request.get_full_path()))
-# request.session[ 'handle' ] = handle
-# return self.f(request, *args, **kwargs)
-
def render(template, context, request):
return render_to_response(template, context,
context_instance=RequestContext(request))
@@ -112,14 +79,16 @@ def dashboard(request):
# get list of ASNs used in my ROAs
roa_asns = [r.asn for r in handle.roas.all()]
# get list of address ranges included in ROAs
- roa_addrs = [p.prefix for r in handle.roas.all() for p in r.from_roa_request.all()]
+ roa_addrs = [p.prefix for r in handle.roas.all()
+ for p in r.from_roa_request.all()]
asns=[]
prefixes=[]
for p in handle.parents.all():
for c in p.resources.all():
asns.extend(c.asn.filter(allocated__isnull=True).exclude(lo__in=roa_asns))
- prefixes.extend(c.address_range.filter(allocated__isnull=True, roa_requests__isnull=True))
+ prefixes.extend(c.address_range.filter(allocated__isnull=True,
+ roa_requests__isnull=True))
asns, prefixes = unallocated_resources(handle, roa_asns, roa_addrs, asns,
prefixes)
@@ -128,40 +97,6 @@ def dashboard(request):
return render('myrpki/dashboard.html', { 'conf': handle, 'asns': asns,
'ars': prefixes }, request)
-#@handle_required
-#def cert_add( request ):
-# return create_object( request, form_class=forms.ConfCertForm( request ),
-# post_save_redirect='/myrpki/cert/' )
-
-#@handle_required
-#def cert_view( request, id ):
-# handle = request.session[ 'handle' ]
-# queryset = models.Cert.objects.filter( conf=handle )
-# return object_detail( request, queryset=queryset, object_id=id,
-# template_object_name='cert' )
-#
-#@handle_required
-#def cert_list( request ):
-# handle = request.session[ 'handle' ]
-# queryset = models.Cert.objects.filter( conf=handle )
-# return object_list( request, queryset=queryset,
-# template_object_name='cert' )
-#
-#@handle_required
-#def cert_edit( request, id ):
-# handle = request.session[ 'handle' ]
-# cert = get_object_or_404( models.Cert, pk=id, conf=handle )
-# return update_object( request, form_class=forms.ConfCertForm( request ),
-# object_id=id,
-# post_save_redirect='/myrpki/cert/' )
-#
-#@handle_required
-#def cert_delete( request, id ):
-# handle = request.session[ 'handle' ]
-# cert = get_object_or_404( models.Cert, pk=id, conf=handle )
-# return delete_object( request, model=models.Cert, object_id=id,
-# post_delete_redirect='/dashboard/' )
-
#@login_required
#def conf_add(request):
# '''Allow the user to create a new configuration.'''
@@ -281,35 +216,6 @@ def parent_view(request, parent_handle):
handle__exact=parent_handle)
return render('myrpki/parent_view.html', { 'parent': parent }, request)
-#def parent_resource(request, parent_handle, obj_type, form_type):
-# """Add an resource range to a parent."""
-# handle = request.session['handle']
-# parent = get_object_or_404(handle.parents.all(),
-# handle__exact=parent_handle)
-# if request.method == 'POST':
-# form = form_type(request.POST)
-# if form.is_valid():
-# obj = obj_type(parent).create(
-# lo=form.cleaned_data['lo'], hi=form.cleaned_data['hi'])
-#
-# glue.configure_resources(handle)
-#
-# return http.HttpResponseRedirect('/myrpki/parent/' + parent_handle)
-# else:
-# form = form_type()
-# return render('myrpki/parent_resource.html',
-# { 'parent': parent, 'form': form }, request)
-
-#@handle_required
-#def parent_address(request, parent_handle):
-# return parent_resource(request, parent_handle,
-# lambda p: p.address_range, forms.AddressRangeForm)
-
-#@handle_required
-#def parent_asn(request, parent_handle):
-# return parent_resource(request, parent_handle,
-# lambda p: p.asn, forms.AsnRangeForm)
-
@handle_required
def child_import(request):
handle = request.session['handle'].handle
@@ -355,38 +261,6 @@ def get_parents_or_404(handle, obj):
return handle.parents.filter(pk__in=[c.parent.pk for c in cert_set])
-#def resource_view(request, object_type, form_type, pk, resource_type):
-# '''view/subdivide an address range.'''
-# handle = request.session['handle']
-# obj = get_object_or_404(object_type, 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 = form_type(handle, obj, request.POST)
-# if form.is_valid():
-# if form.cleaned_data['child'] is None:
-# hi = form.cleaned_data['hi']
-# lo = form.cleaned_data['lo']
-# print hi, lo
-# # if a range is given, create a new object
-# if hi and lo:
-# subobj = object_type.objects.create(
-# lo=lo, hi=hi, parent=obj, allocated=None)
-# subobj.save()
-# if obj.allocated:
-# obj.allocated = None
-# obj.save()
-# else:
-# obj.allocated = form.cleaned_data['child']
-# obj.save()
-#
-# glue.configure_resources(handle)
-# else:
-# form = form_type(handle, obj)
-# return render('myrpki/resource_view.html', { 'addr': obj, 'form': form,
-# 'parent': parent_set, 'resource_type': resource_type }, request)
-
@handle_required
def address_view(request, pk):
handle = request.session['handle']
@@ -408,42 +282,6 @@ def asn_view(request, pk):
return render('myrpki/asn_view.html',
{ 'asn': obj, 'parent': parent_set }, request)
-#@handle_required
-#def roa_edit(request, pk=None):
-# '''Create or edit a ROA.'''
-#
-# handle = request.session['handle']
-#
-# if not pk is None:
-# obj = get_object_or_404(models.Roa, pk=pk)
-# if obj.conf != handle:
-# raise http.Http404
-# else:
-# obj = None
-#
-# if request.method == 'POST':
-# form = forms.RoaForm(handle, None, None, None, request.POST)
-# if form.is_valid():
-# if not obj:
-# obj = models.Roa(conf=handle, asn=form.cleaned_data['asn'],
-# comments=form.cleaned_data['comments'], max_len=0)
-# else:
-# obj.asn = form.cleaned_data['asn']
-# obj.comments = form.cleaned_data['comments']
-# obj.save()
-# obj.prefix.clear()
-# obj.prefix.add(*form.cleaned_data['prefix'])
-#
-# glue.configure_resources(handle)
-#
-# return http.HttpResponseRedirect('/myrpki/')
-# else:
-# asn = obj.asn if obj else None
-# comments = obj.comments if obj else None
-# prefix = [o.pk for o in obj.prefix.all()] if obj else []
-# form = forms.RoaForm(handle, asn, comments, prefix)
-# return render('myrpki/roaform.html', { 'form': form }, request)
-
@handle_required
def child_view(request, child_handle):
'''Detail view of child for the currently selected handle.'''
@@ -462,7 +300,8 @@ def prefix_split_view(request, pk):
if request.method == 'POST':
form = forms.PrefixSplitForm(prefix, request.POST)
if form.is_valid():
- obj = models.AddressRange(lo=form.cleaned_data['lo'], hi=form.cleaned_data['hi'], parent=prefix)
+ obj = models.AddressRange(lo=form.cleaned_data['lo'],
+ hi=form.cleaned_data['hi'], parent=prefix)
obj.save()
return http.HttpResponseRedirect(obj.get_absolute_url())
else:
@@ -486,65 +325,13 @@ def prefix_allocate_view(request, pk):
glue.configure_resources(handle)
return http.HttpResponseRedirect(prefix.get_absolute_url())
else:
- form = forms.PrefixAllocateForm(prefix.allocated.pk if prefix.allocated else None,
+ form = forms.PrefixAllocateForm(
+ prefix.allocated.pk if prefix.allocated else None,
handle.children.all())
return render('myrpki/prefix_view.html', { 'form': form,
'addr': prefix, 'form': form, 'parent': parent_set }, request)
-def parent_prefix(prefix):
- '''Returns the top-most parent prefix for the given prefix.'''
- while prefix.parent:
- prefix = prefix.parent
- return prefix
-
-def common_cert(prefix, prefix_set):
- '''Return true if prefix is derived from the same resource cert
- as all the addresses in prefix_set.'''
- while prefix.parent:
- prefix = prefix.parent
-
- # list of certs for the target prefix
- certs = prefix.from_cert.all()
- # all prefixes will have the same cert, so just check the first one
- prefix_certs = prefix_set[0].from_cert.all()
- # all we need is one match
- for c in certs:
- if c in prefix_certs:
- return True
- return False
-
-def update_roas(handle, prefix):
- '''Recompute the required ROAs for the prefix that was changed.'''
- # generate the list of ASNs
- asns = list(asnset(prefix.asns))
-
- print 'updating roas for %s: asns=%r' % (prefix, asns)
-
- # remove this prefix from any roa not on the updated list
- for roa in prefix.from_roa.exclude(asn__in=asns):
- print 'removing %s from roa for asn %d' % (prefix, roa.asn)
- roa.prefix.remove(prefix)
- # if the roa is empty, delete it now
- if roa.prefix.all().count() == 0:
- print 'deleting roa for asn %d because it is empty' % (roa.asn,)
- roa.delete()
-
- for asid in asns:
- for roa in handle.roas.filter(asn=asid):
- # determine if this roa includes prefixes from the same
- # resource cert as the prefix we just changed
- if common_cert(prefix, roa.prefix.all()):
- roa.prefix.add(prefix)
- break
- else:
- # no roa is present for this ASN, create a new one
- print 'creating new roa for asn %d with %s' % (asid, prefix)
- roa = models.Roa.objects.create(asn=asid, conf=handle,
- active=False)
- roa.save()
- roa.prefix.add(prefix)
-
def add_roa_requests(handle, prefix, asns, max_length):
for asid in asns:
req_set = prefix.roa_requests.filter(roa__asn=asid,
diff --git a/portal-gui/scripts/load_csv.py b/portal-gui/scripts/load_csv.py
index ed046c5a..de48447e 100755
--- a/portal-gui/scripts/load_csv.py
+++ b/portal-gui/scripts/load_csv.py
@@ -19,8 +19,7 @@ import rpki.ipaddrs
from rpki.myrpki import csv_reader
from rpkigui.myrpki import models
-from rpkigui.myrpki.views import update_roas
-from rpkigui.myrpki.asnset import asnset
+from rpkigui.myrpki.views import add_roa_requests
cfg_file = os.getenv("MYRPKI_CONF", "myrpki.conf")
cfg = rpki.config.parser(cfg_file, "myrpki")
@@ -33,39 +32,91 @@ print 'processing csv files for resource handle', handle
conf = models.Conf.objects.get(handle=handle)
-for child_handle, asn in csv_reader(asn_csv, columns=2):
- child = conf.children.get(handle=child_handle)
- asn = models.Asn.objects.get(lo=asn, hi=asn,
- from_cert__parent__in=conf.parents.all())
- child.asn.add(asn)
-
-for child_handle, prefix in csv_reader(prefix_csv, columns=2):
- child = conf.children.get(handle=child_handle)
- try:
- rs = rpki.resource_set.resource_range_ipv4.from_str(prefix)
- except socket.error:
- rs = rpki.resource_set.resource_range_ipv6.from_str(prefix)
- obj = models.AddressRange.objects.get(lo=str(rs.min), hi=str(rs.max),
- from_cert__parent__in=conf.parents.all())
- child.address_range.add(obj)
+# every parent has a favorite
+def best_child(parent, parent_range):
+ '''Return the child address range that is the closest match, or
+ returns the arguments if no children.'''
+ best = None
+ best_range = None
+ for q in parent.children.all():
+ if best is None:
+ best = q
+ best_range = q.as_resource_range()
+ else:
+ t = q.as_resource_range()
+ if t.min >= best_range.min and t.max <= best_range.max:
+ best = q
+ best_range = t
+ if best:
+ if best.children.all():
+ best, best_range = best_child(best, best_range)
+ return (best, best_range)
-for prefix, asn, group in csv_reader(roa_csv, columns=3):
- try:
- rs = rpki.resource_set.roa_prefix_set_ipv4().parse_str(prefix)
- except socket.error:
- rs = rpki.resource_set.roa_prefix_set_ipv6().parse_str(prefix)
+ return parent, parent_range
- if rs.prefixlen != rs.max_prefixlen:
- raise ValueError, \
- "%s: max prefixlen larger than prefixlen is not currently supported." % (prefix,)
+def get_or_create_prefix(address_range):
+ '''Returns a AddressRange object for the resource_range_ip specified
+ as an argument. If no match is found, a new AddressRange object is
+ created as a child of the best matching received resource.'''
- print str(rs.min()), str(rs.max())
- obj = models.AddressRange.objects.get(lo=str(rs.min()), hi=str(rs.max()),
+ # get all resources from our parents
+ prefix_set = models.AddressRange.objects.filter(
from_cert__parent__in=conf.parents.all())
- roa_asns = asnset(obj.asns)
- asid = int(asn)
- if asid not in roa_asns:
- roa_asns.add(asid)
- obj.asns = str(roa_asns)
+
+ # gross, since we store the address ranges as strings in the django
+ # db, we can't use the normal __lte and __gte filters, so we get to
+ # do it in python instead.
+ for prefix in prefix_set:
+ prefix_range = prefix.as_resource_range()
+ if (prefix_range.min <= address_range.min and
+ prefix_range.max >= address_range.max):
+ # there should only ever be a single matching prefix
+ break
+ else:
+ raise RuntimeError, '%s does not match any received address range.' % (
+ address_range,)
+
+ # find the best match among the children + grandchildren
+ prefix, prefix_range = best_child(prefix, prefix_range)
+
+ print 'best match for %s is %s' % (address_range, prefix)
+ if prefix_range.min != address_range.min or prefix_range.max != address_range.max:
+ # create suballocation
+ print 'creating new range'
+ prefix = models.AddressRange.objects.create(lo=str(address_range.min),
+ hi=str(address_range.max), parent=prefix)
+
+ return prefix
+
+def do_asns():
+ for child_handle, asn in csv_reader(asn_csv, columns=2):
+ child = conf.children.get(handle=child_handle)
+ asn = models.Asn.objects.get(lo=asn, hi=asn,
+ from_cert__parent__in=conf.parents.all())
+ child.asn.add(asn)
+
+def do_prefixes():
+ for child_handle, prefix in csv_reader(prefix_csv, columns=2):
+ child = conf.children.get(handle=child_handle)
+ try:
+ rs = rpki.resource_set.resource_set_ipv4().parse_str(prefix)
+ except socket.error:
+ rs = rpki.resource_set.resource_set_ipv6().parse_str(prefix)
+ obj = get_or_create_prefix(rs)
+ obj.allocated = child
obj.save()
- update_roas(conf, obj)
+
+def do_roas():
+ for prefix, asn, group in csv_reader(roa_csv, columns=3):
+ try:
+ rs = rpki.resource_set.roa_prefix_set_ipv4().parse_str(prefix)
+ except socket.error:
+ rs = rpki.resource_set.roa_prefix_set_ipv6().parse_str(prefix)
+
+ print str(rs.min()), str(rs.max()), rs.max_prefixlen
+ obj = get_or_create_prefix(rs.to_resource_range())
+ add_roa_requests(conf, obj, [int(asn)], rs.max_prefixlen)
+
+do_asns()
+do_prefixes()
+do_roas()