aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--portal-gui/templates/myrpki/child_view.html11
-rw-r--r--portal-gui/templates/myrpki/dashboard.html7
-rw-r--r--rpkid/rpki/gui/app/glue.py193
-rw-r--r--rpkid/rpki/gui/app/models.py4
-rw-r--r--rpkid/rpki/gui/app/views.py8
-rw-r--r--rpkid/rpki/gui/scripts/list_resources.py46
-rwxr-xr-xrpkid/rpki/gui/scripts/load_csv.py12
7 files changed, 142 insertions, 139 deletions
diff --git a/portal-gui/templates/myrpki/child_view.html b/portal-gui/templates/myrpki/child_view.html
index 0721cc65..9bcdf948 100644
--- a/portal-gui/templates/myrpki/child_view.html
+++ b/portal-gui/templates/myrpki/child_view.html
@@ -3,28 +3,29 @@
{% block content %}
<p>Handle: <a href="{% url rpki.gui.app.views.dashboard %}">{{ request.session.handle.handle }}</a>
<h1>Child View</h1>
-<p>Child: {{ child.handle }}
+<p>Child: {{ child.handle }}</p>
+<p>Valid until: {{ child.valid_until }}</p>
<h2>Delegated Addresses</h2>
{% if child.address_range.all %}
<ul>
{% for a in child.address_range.all %}
-<li><a href="{{ a.get_absolute_url }}">{{ a }}</a>
+<li><a href="{{ a.get_absolute_url }}">{{ a }}</a></li>
{% endfor %}
</ul>
{% else %}
-<p>--none--
+<p>--none--</p>
{% endif %}
<h2>Delegated ASNs</h2>
{% if child.asn.all %}
<ul>
{% for a in child.asn.all %}
-<li><a href="{{ a.get_absolute_url }}">{{ a }}</a>
+<li><a href="{{ a.get_absolute_url }}">{{ a }}</a></li>
{% endfor %}
</ul>
{% else %}
-<p>--none--
+<p>--none--</p>
{% endif %}
{% endblock %}
diff --git a/portal-gui/templates/myrpki/dashboard.html b/portal-gui/templates/myrpki/dashboard.html
index 116ea792..dea03c31 100644
--- a/portal-gui/templates/myrpki/dashboard.html
+++ b/portal-gui/templates/myrpki/dashboard.html
@@ -54,18 +54,19 @@ td { border: solid 1px; text-align: center; padding-left: 1em; padding-right: 1e
{% if request.session.handle.children.all %}
<ul>
{% for child in request.session.handle.children.all %}
-<li><a href="{% url rpki.gui.app.views.child_view child.handle %}">{{ child.handle }}</a>
+<li><a href="{% url rpki.gui.app.views.child_view child.handle %}">{{ child.handle }}</a>, valid until {{ child.valid_until }}
{% if child.address_range.count or child.asn.count %}
<p>Delegated resources:
<ul>
{% for asn in child.asn.all %}
-<li><a href="{{ asn.get_absolute_url }}">{{ asn }}</a>
+<li><a href="{{ asn.get_absolute_url }}">{{ asn }}</a></li>
{% endfor %}
{% for address in child.address_range.all %}
-<li><a href="{{ address.get_absolute_url}}">{{ address }}</a>
+<li><a href="{{ address.get_absolute_url}}">{{ address }}</a></li>
{% endfor %}
</ul>
{% endif %}
+</li>
{% endfor %}
</ul>
<!--
diff --git a/rpkid/rpki/gui/app/glue.py b/rpkid/rpki/gui/app/glue.py
index 0a5e9af3..a00eff50 100644
--- a/rpkid/rpki/gui/app/glue.py
+++ b/rpkid/rpki/gui/app/glue.py
@@ -19,121 +19,140 @@ PERFORMANCE OF THIS SOFTWARE.
from __future__ import with_statement
-import os
-import os.path
-import csv
-import stat
-import sys
+import os, os.path, csv, stat, sys
from django.db.models import F
-import rpki
-import rpki.config
-
+import rpki, rpki.async, rpki.http, rpki.x509, rpki.left_right
+from rpki.myrpki import CA, IRDB, csv_writer
from rpki.gui import settings
from rpki.gui.app import models
-def conf(handle):
- return settings.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(log, handle, args):
- """Invoke the myrpki cli for the specified configuration."""
- myrpki_dir = conf(handle)
- config = myrpki_dir + '/rpki.conf'
- # default rpki.conf uses relative paths, so chdir() to the repo first
- cmd = 'cd %s && %s %s' % (myrpki_dir, settings.MYRPKI, ' '.join(['--config=' + config] + args))
- print >>log, 'invoking', cmd
- os.system(cmd)
+def conf(*handle):
+ """
+ Return the absolute pathname to the configuration directory for
+ the given resource handle. If additional arguments are given, they
+ are taken to mean files/subdirectories.
+ """
+ argv = [ settings.CONFDIR ]
+ argv.extend(handle)
+ return os.path.join(*argv)
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:
+ 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)
+ w = csv_writer(path)
+ w.writerows([asn.allocated.handle, asn.lo] for asn in qs)
+ w.close()
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)
+ w = csv_writer(path)
+ w.writerows([p.allocated.handle, p.as_resource_range()] for p in qs)
+ w.close()
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(log, handle):
- args = ['configure_daemons']
- for hosted in handle.hosting.all():
- args.append(conf(hosted.handle) + '/myrpki.xml')
- invoke_rpki(log, handle.handle, args)
+ w = csv_writer(path)
+ w.writerows([req.as_roa_prefix(), req.roa.asn,
+ '%s-group-%d' % (handle.handle, req.roa.pk)] for req in qs)
+ w.close()
+
+def qualify_path(pfx, fname):
+ """Ensure 'path' is an absolute filename."""
+ return fname if fname.startswith('/') else os.path.join(pfx, fname)
+
+def build_rpkid_caller(cfg, verbose=False):
+ """
+ Returns a function suitable for calling rpkid using the
+ configuration information specified in the rpki.config.parser
+ object.
+ """
+ bpki_servers_dir = cfg.get("bpki_servers_directory")
+ if not bpki_servers_dir.startswith('/'):
+ bpki_servers_dir = conf(cfg.get('handle'), bpki_servers_dir)
+
+ bpki_servers = CA(cfg.filename, bpki_servers_dir)
+ rpkid_base = "http://%s:%s/" % (cfg.get("rpkid_server_host"), cfg.get("rpkid_server_port"))
+
+ return rpki.async.sync_wrapper(rpki.http.caller(
+ proto = rpki.left_right,
+ client_key = rpki.x509.RSA(PEM_file = bpki_servers.dir + "/irbe.key"),
+ client_cert = rpki.x509.X509(PEM_file = bpki_servers.dir + "/irbe.cer"),
+ server_ta = rpki.x509.X509(PEM_file = bpki_servers.cer),
+ server_cert = rpki.x509.X509(PEM_file = bpki_servers.dir + "/rpkid.cer"),
+ url = rpkid_base + "left-right",
+ debug = verbose))
def configure_resources(log, 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(log, handle)
- else:
- invoke_rpki(log, handle.handle, ['configure_resources'])
-
- # send the myrpki.xml to the rpkid hosting me
- configure_daemons(log, handle.host)
-
- # process the response
- invoke_rpki(log, handle.handle, ['configure_resources'])
+ """
+ This function should be called when resources for this resource
+ holder have changed. It updates IRDB and notifies rpkid to
+ immediately process the changes, rather than waiting for the cron
+ job to run.
+
+ For backwards compatability (and backups), it also writes the csv
+ files for use with the myrpki.py command line script.
+ """
+
+ path = conf(handle.handle)
+ cfg = rpki.config.parser(os.path.join(path, 'rpki.conf'), 'myrpki')
+
+ output_asns(qualify_path(path, cfg.get('asn_csv')), handle)
+ output_prefixes(qualify_path(path, cfg.get('prefix_csv')), handle)
+ output_roas(qualify_path(path, cfg.get('roa_csv')), handle)
+
+ roa_requests = []
+ for roa in handle.roas.all():
+ v4 = rpki.resource_set.roa_prefix_set_ipv4()
+ v6 = rpki.resource_set.roa_prefix_set_ipv6()
+ for req in roa.from_roa_request.all():
+ pfx = req.as_roa_prefix()
+ if isinstance(pfx, rpki.resource_set.roa_prefix_ipv4):
+ v4.append(pfx)
+ else:
+ v6.append(pfx)
+ roa_requests.append((roa.asn, v4, v6))
+
+ children = []
+ for child in handle.children.all():
+ asns = rpki.resource_set.resource_set_as(a.as_resource_range() for a in child.asns.all())
+
+ v4 = rpki.resource_set.resource_set_ipv4()
+ v6 = rpki.resource_set.resource_set_ipv6()
+ for pfx in child.address_range.all():
+ rng = pfx.as_resource_range()
+ if isinstance(rng, rpki.resource_set.resource_range_ipv4):
+ v4.append(rng)
+ else:
+ v6.append(rng)
+
+ # convert from datetime.datetime to rpki.sundial.datetime
+ valid_until = rpki.sundial.datetime.fromdatetime(child.valid_until)
+ children.append((child.handle, asns, v4, v6, valid_until))
+
+ irdb = IRDB(cfg)
+ irdb.update(handle, roa_requests, children)
+ irdb.close()
+
+ # for hosted handles, get the config for the rpkid host
+ if handle.host:
+ cfg = rpki.config.parser(conf(handle.host.handle, 'rpki.conf'), 'myrpki')
+
+ # contact rpkid to request immediate update
+ call_rpkid = build_rpkid_caller(cfg)
+ call_rpkid(rpki.left_right.self_elt.make_pdu(action='set', self_handle=handle.handle, run_now=True))
# vim:sw=4 ts=8 expandtab
diff --git a/rpkid/rpki/gui/app/models.py b/rpkid/rpki/gui/app/models.py
index 78327b8f..3b161a59 100644
--- a/rpkid/rpki/gui/app/models.py
+++ b/rpkid/rpki/gui/app/models.py
@@ -90,7 +90,6 @@ class AddressRange(models.Model):
try:
self.as_resource_range().prefixlen()
except rpki.exceptions.MustBePrefix, err:
- print err
return False
return True
@@ -106,7 +105,7 @@ class RoaRequest(models.Model):
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):
+ if isinstance(r, rpki.resource_set.resource_range_ipv4):
return rpki.resource_set.roa_prefix_ipv4(r.min, r.prefixlen(),
self.max_length)
else:
@@ -152,6 +151,7 @@ class Asn(models.Model):
class Child(models.Model):
conf = models.ForeignKey(Conf, related_name='children')
handle = HandleField() # parent's name for child
+ valid_until = models.DateTimeField()
def __unicode__(self):
return u"%s's child %s" % (self.conf, self.handle)
diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py
index 77360d7d..db1cff3f 100644
--- a/rpkid/rpki/gui/app/views.py
+++ b/rpkid/rpki/gui/app/views.py
@@ -492,9 +492,13 @@ def myrpki_xml(request, self_handle):
with open(fname, 'w') as myrpki_xml :
myrpki_xml.write(request.POST['content'])
- glue.configure_daemons(log, conf.host)
+ # FIXME: used to run configure_daemons here, but it takes too
+ # long with many hosted handles. rpkidemo still needs a way
+ # to do initial bpki setup with rpkid!
- return serve_file(self_handle, 'myrpki.xml', 'application/xml')
+ return http.HttpResponse('<p>success</p>')
+ else:
+ return serve_file(self_handle, 'myrpki.xml', 'application/xml')
def login(request):
"""
diff --git a/rpkid/rpki/gui/scripts/list_resources.py b/rpkid/rpki/gui/scripts/list_resources.py
index 2b547e45..13864705 100644
--- a/rpkid/rpki/gui/scripts/list_resources.py
+++ b/rpkid/rpki/gui/scripts/list_resources.py
@@ -34,45 +34,23 @@ import sys
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'rpki.gui.settings'
-from datetime import datetime
import getopt
+from datetime import datetime, timedelta
from os.path import basename
-from rpki.myrpki import CA
-import rpki.config
-import rpki.x509
-import rpki.http
-import rpki.async
-import rpki.left_right
-import rpki.resource_set
-
-from rpki.gui.app import models
+import rpki.config, rpki.left_right, rpki.resource_set
+from rpki.gui.app import models, glue
verbose = False
version = '$Id$'
def query_rpkid():
- """Fetch our received resources from the local rpkid using the rpki.conf
- in the current directory."""
- cfg_file = os.getenv("RPKI_CONF", "rpki.conf")
- cfg = rpki.config.parser(cfg_file, "myrpki")
- bpki_servers = CA(cfg_file, cfg.get("bpki_servers_directory"))
- rpkid_base = "http://%s:%s/" % (cfg.get("rpkid_server_host"), cfg.get("rpkid_server_port"))
-
- if verbose:
- print 'current directory is', os.getcwd()
- print 'cfg_file=', cfg_file
- print 'bpki_servers=', bpki_servers.dir
- print 'rpkid_base=', rpkid_base
-
- call_rpkid = rpki.async.sync_wrapper(rpki.http.caller(
- proto = rpki.left_right,
- client_key = rpki.x509.RSA(PEM_file = bpki_servers.dir + "/irbe.key"),
- client_cert = rpki.x509.X509(PEM_file = bpki_servers.dir + "/irbe.cer"),
- server_ta = rpki.x509.X509(PEM_file = bpki_servers.cer),
- server_cert = rpki.x509.X509(PEM_file = bpki_servers.dir + "/rpkid.cer"),
- url = rpkid_base + "left-right",
- debug = verbose))
+ """
+ Fetch our received resources from the local rpkid using the rpki.conf
+ in the current directory.
+ """
+ cfg = rpki.config.parser(section='myrpki')
+ call_rpkid = glue.build_rpkid_caller(cfg, verbose)
if verbose:
print 'retrieving the list of <self/> handles served by this rpkid'
@@ -138,7 +116,11 @@ for pdu in pdus:
if not child_set:
if verbose:
print 'creating new child %s' % (pdu.child_handle,)
- child = models.Child(conf=conf, handle=pdu.child_handle)
+ # default to 1 year. no easy way to query irdb for the
+ # current value.
+ valid_until = datetime.now() + timedelta(days=365)
+ child = models.Child(conf=conf, handle=pdu.child_handle,
+ valid_until=valid_until)
child.save()
#elif isinstance(x, rpki.left_right.list_roa_requests_elt):
# print x.asn, x.ipv4, x.ipv6
diff --git a/rpkid/rpki/gui/scripts/load_csv.py b/rpkid/rpki/gui/scripts/load_csv.py
index 0ef49cce..ebb995b6 100755
--- a/rpkid/rpki/gui/scripts/load_csv.py
+++ b/rpkid/rpki/gui/scripts/load_csv.py
@@ -1,6 +1,6 @@
# $Id$
#
-# Copyright (C) 2010 SPARTA, Inc. dba Cobham Analytic Solutions
+# Copyright (C) 2010, 2011 SPARTA, Inc. dba Cobham Analytic Solutions
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -23,22 +23,18 @@
# for the handle you are loading data
#
-import sys, os
+import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'rpki.gui.settings'
import csv
import socket # for socket.error
-import rpki
-import rpki.resource_set
-import rpki.ipaddrs
+import rpki.resource_set, rpki.ipaddrs
from rpki.myrpki import csv_reader
-
from rpki.gui.app import models
from rpki.gui.app.views import add_roa_requests
-cfg_file = os.getenv("RPKI_CONF", "rpki.conf")
-cfg = rpki.config.parser(cfg_file, "myrpki")
+cfg = rpki.config.parser(section='myrpki')
handle = cfg.get('handle')
asn_csv = cfg.get('asn_csv')
prefix_csv = cfg.get('prefix_csv')