diff options
Diffstat (limited to 'rpki/gui')
-rw-r--r-- | rpki/gui/app/check_expired.py | 43 | ||||
-rw-r--r-- | rpki/gui/app/glue.py | 75 | ||||
-rw-r--r-- | rpki/gui/app/models.py | 14 | ||||
-rwxr-xr-x | rpki/gui/app/range_list.py | 2 | ||||
-rw-r--r-- | rpki/gui/app/templates/app/route_detail.html | 8 | ||||
-rw-r--r-- | rpki/gui/app/urls.py | 10 | ||||
-rw-r--r-- | rpki/gui/app/views.py | 39 | ||||
-rw-r--r-- | rpki/gui/cacheview/models.py | 8 | ||||
-rw-r--r-- | rpki/gui/cacheview/tests.py | 1 | ||||
-rw-r--r-- | rpki/gui/cacheview/util.py | 3 | ||||
-rw-r--r-- | rpki/gui/cacheview/views.py | 1 | ||||
-rw-r--r-- | rpki/gui/decorators.py | 15 | ||||
-rw-r--r-- | rpki/gui/default_settings.py | 180 | ||||
-rw-r--r-- | rpki/gui/models.py | 4 | ||||
-rw-r--r-- | rpki/gui/routeview/api.py | 2 | ||||
-rw-r--r-- | rpki/gui/routeview/util.py | 2 | ||||
-rw-r--r-- | rpki/gui/script_util.py | 60 |
17 files changed, 141 insertions, 326 deletions
diff --git a/rpki/gui/app/check_expired.py b/rpki/gui/app/check_expired.py index a084af79..62292e66 100644 --- a/rpki/gui/app/check_expired.py +++ b/rpki/gui/app/check_expired.py @@ -25,9 +25,10 @@ from rpki.gui.cacheview.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' @@ -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", self_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/glue.py b/rpki/gui/app/glue.py index a2dddb51..bfade6d8 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 def ghostbuster_to_vcard(gbr): """Convert a GhostbusterRequest object into a vCard object.""" + import vobject vcard = vobject.vCard() @@ -66,18 +67,6 @@ 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 def list_received_resources(log, conf): """ @@ -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, self_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/models.py b/rpki/gui/app/models.py index d3b0733d..ed32e9d2 100644 --- a/rpki/gui/app/models.py +++ b/rpki/gui/app/models.py @@ -121,16 +121,16 @@ class Conf(rpki.irdb.models.ResourceHolderCA): def parents(self): """Simulates irdb.models.Parent.objects, but returns app.models.Parent proxy objects. - """ + return Parent.objects.filter(issuer=self) @property def children(self): """Simulates irdb.models.Child.objects, but returns app.models.Child proxy objects. - """ + return Child.objects.filter(issuer=self) @property @@ -149,8 +149,8 @@ class Conf(rpki.irdb.models.ResourceHolderCA): def routes(self): """Return all IPv4 routes covered by RPKI certs issued to this resource holder. - """ + # build a Q filter to select all RouteOrigin objects covered by # prefixes in the resource holder's certificates prefixes = ResourceRangeAddressV4.objects.filter(cert__conf=self) @@ -167,8 +167,8 @@ class Conf(rpki.irdb.models.ResourceHolderCA): def routes_v6(self): """Return all IPv6 routes covered by RPKI certs issued to this resource holder. - """ + # build a Q filter to select all RouteOrigin objects covered by # prefixes in the resource holder's certificates prefixes = ResourceRangeAddressV6.objects.filter(cert__conf=self) @@ -183,6 +183,7 @@ class Conf(rpki.irdb.models.ResourceHolderCA): def send_alert(self, subject, message, from_email, severity=Alert.INFO): """Store an alert for this resource holder.""" + self.alerts.create(subject=subject, text=message, severity=severity) send_mail( @@ -198,8 +199,8 @@ class Conf(rpki.irdb.models.ResourceHolderCA): Contact emails are extract from any ghostbuster requests, and any linked user accounts. - """ + notify_emails = [gbr.email_address for gbr in self.ghostbusters if gbr.email_address] notify_emails.extend( [acl.user.email for acl in ConfACL.objects.filter(conf=self) if acl.user.email] @@ -224,7 +225,6 @@ class ResourceCert(models.Model): """Represents a resource certificate. This model is used to cache the output of <list_received_resources/>. - """ # Handle to which this cert was issued @@ -252,6 +252,7 @@ class ResourceCert(models.Model): def get_cert_chain(self): """Return a list containing the complete certificate chain for this certificate.""" + cert = self x = [cert] while cert.issuer: @@ -425,7 +426,6 @@ class RouteOriginV6(rpki.gui.routeview.models.RouteOriginV6): class ConfACL(models.Model): """Stores access control for which users are allowed to manage a given resource handle. - """ conf = models.ForeignKey(Conf) 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/templates/app/route_detail.html b/rpki/gui/app/templates/app/route_detail.html index 8bd744df..84add4a8 100644 --- a/rpki/gui/app/templates/app/route_detail.html +++ b/rpki/gui/app/templates/app/route_detail.html @@ -42,15 +42,13 @@ </thead> <tbody> {% for pfx in roa_prefixes %} - {% for roa in pfx.roas.all %} <tr> <td>{{ pfx.as_resource_range }}</td> <td>{{ pfx.max_length }}</td> - <td>{{ roa.asid }}</td> - <td>{{ roa.not_after }}</td> - <td>{{ roa.repo.uri }}</td> + <td>{{ pfx.roas.all.0.asid }}</td> + <td>{{ pfx.roas.all.0.not_after }}</td> + <td>{{ pfx.roas.all.0.repo.uri }}</td> </tr> - {% endfor %} {% endfor %} </tbody> </table> diff --git a/rpki/gui/app/urls.py b/rpki/gui/app/urls.py index 81c9b127..f595ea8f 100644 --- a/rpki/gui/app/urls.py +++ b/rpki/gui/app/urls.py @@ -88,14 +88,12 @@ urlpatterns = patterns( #{'post_reset_redirect' : '/user/password/reset/done/'}, {'extra_context': {'form_title': 'Password Reset'}}, name="password_reset"), - url(r'^user/password/reset/done/$', - 'django.contrib.auth.views.password_reset_done', - name='password_reset_done'), + (r'^user/password/reset/done/$', + 'django.contrib.auth.views.password_reset_done'), url(r'^user/password/reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 'django.contrib.auth.views.password_reset_confirm', #{'post_reset_redirect' : '/user/password/done/'}, name="password_reset_confirm"), - url(r'^user/password/done/$', - 'django.contrib.auth.views.password_reset_complete', - name='password_reset_complete'), + (r'^user/password/done/$', + 'django.contrib.auth.views.password_reset_complete'), ) diff --git a/rpki/gui/app/views.py b/rpki/gui/app/views.py index c739b55e..dfd36dbb 100644 --- a/rpki/gui/app/views.py +++ b/rpki/gui/app/views.py @@ -27,7 +27,6 @@ from tempfile import NamedTemporaryFile import cStringIO import csv import logging -import lxml.etree from django.utils.decorators import method_decorator from django.contrib.auth.decorators import login_required @@ -147,28 +146,19 @@ def generic_import(request, queryset, configure, form_class=None, # expects it. 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) - except lxml.etree.XMLSyntaxError as e: - logger.exception('caught XMLSyntaxError while parsing uploaded file') - messages.error( - request, - 'The uploaded file has an invalid XML syntax' - ) + # 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) + # force rpkid run now + z.synchronize_ca(poke=True) + os.remove(tmpf.name) + if post_import_redirect: + url = post_import_redirect 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) + _, handle = r + url = queryset.get(issuer=conf, + handle=handle).get_absolute_url() + return http.HttpResponseRedirect(url) else: form = form_class() @@ -718,10 +708,7 @@ def roa_create_multi(request): 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. - if formset.has_changed() and formset.is_valid(): + if formset.is_valid(): routes = [] v = [] for form in formset: diff --git a/rpki/gui/cacheview/models.py b/rpki/gui/cacheview/models.py index c3ee8421..08acfa2d 100644 --- a/rpki/gui/cacheview/models.py +++ b/rpki/gui/cacheview/models.py @@ -58,6 +58,7 @@ class ValidationLabel(models.Model): Represents a specific error condition defined in the rcynic XML output file. """ + label = models.CharField(max_length=79, db_index=True, unique=True) status = models.CharField(max_length=255) kind = models.PositiveSmallIntegerField(choices=kinds) @@ -70,6 +71,7 @@ class RepositoryObject(models.Model): """ Represents a globally unique RPKI repository object, specified by its URI. """ + uri = models.URLField(unique=True, db_index=True) generations = list(enumerate(('current', 'backup'))) @@ -89,6 +91,7 @@ class SignedObject(models.Model): The signing certificate is ommitted here in order to give a proper value for the 'related_name' attribute. """ + repo = models.ForeignKey(RepositoryObject, related_name='cert', unique=True) # on-disk file modification time @@ -108,6 +111,7 @@ class SignedObject(models.Model): """ convert the local timestamp to UTC and convert to a datetime object """ + return datetime.utcfromtimestamp(self.mtime + time.timezone) def status_id(self): @@ -116,6 +120,7 @@ class SignedObject(models.Model): The selector is chosen based on the current generation only. If there is any bad status, return bad, else if there are any warn status, return warn, else return good. """ + for x in reversed(kinds): if self.repo.statuses.filter(generation=generations_dict['current'], status__kind=x[0]): return x[1] @@ -129,6 +134,7 @@ class Cert(SignedObject): """ Object representing a resource certificate. """ + addresses = models.ManyToManyField(AddressRange, related_name='certs') addresses_v6 = models.ManyToManyField(AddressRangeV6, related_name='certs') asns = models.ManyToManyField(ASRange, related_name='certs') @@ -141,6 +147,7 @@ class Cert(SignedObject): def get_cert_chain(self): """Return a list containing the complete certificate chain for this certificate.""" + cert = self x = [cert] while cert != cert.issuer: @@ -180,6 +187,7 @@ class ROAPrefixV4(ROAPrefix, rpki.gui.models.PrefixV4): @property def routes(self): """return all routes covered by this roa prefix""" + return RouteOrigin.objects.filter(prefix_min__gte=self.prefix_min, prefix_max__lte=self.prefix_max) diff --git a/rpki/gui/cacheview/tests.py b/rpki/gui/cacheview/tests.py index 2247054b..daca07bf 100644 --- a/rpki/gui/cacheview/tests.py +++ b/rpki/gui/cacheview/tests.py @@ -12,6 +12,7 @@ class SimpleTest(TestCase): """ Tests that 1 + 1 always equals 2. """ + self.failUnlessEqual(1 + 1, 2) __test__ = {"doctest": """ diff --git a/rpki/gui/cacheview/util.py b/rpki/gui/cacheview/util.py index 9e8748bf..31ad8b8b 100644 --- a/rpki/gui/cacheview/util.py +++ b/rpki/gui/cacheview/util.py @@ -310,8 +310,8 @@ def fetch_published_objects(): """Query rpkid for all objects published by local users, and look up the current validation status of each object. The validation status is used later to send alerts for objects which have transitioned to invalid. - """ + logger.info('querying for published objects') handles = [conf.handle for conf in Conf.objects.all()] @@ -353,7 +353,6 @@ class Handle(object): def notify_invalid(): """Send email alerts to the addresses registered in ghostbuster records for any invalid objects that were published by users of this system. - """ logger.info('sending notifications for invalid objects') diff --git a/rpki/gui/cacheview/views.py b/rpki/gui/cacheview/views.py index 94870eb2..451c0d1e 100644 --- a/rpki/gui/cacheview/views.py +++ b/rpki/gui/cacheview/views.py @@ -29,6 +29,7 @@ def cert_chain(obj): """ returns an iterator covering all certs from the root cert down to the EE. """ + chain = [obj] while obj != obj.issuer: obj = obj.issuer diff --git a/rpki/gui/decorators.py b/rpki/gui/decorators.py index 69d20c46..75efeae0 100644 --- a/rpki/gui/decorators.py +++ b/rpki/gui/decorators.py @@ -15,15 +15,22 @@ __version__ = '$Id$' from django import http +from os import getenv -def tls_required(f): - """Decorator which returns a 500 error if the connection is not secured - with TLS (https). +# Don't set this in production, ever. Really. You have been warned. +# +_allow_plain_http_for_testing = getenv("ALLOW_PLAIN_HTTP_FOR_TESTING") == "I solemnly swear that I am not running this in production" + +def tls_required(f): + """ + Decorator which returns a 500 error if the connection is not + secured with TLS (https). """ + def _tls_required(request, *args, **kwargs): - if not request.is_secure(): + if not request.is_secure() and not _allow_plain_http_for_testing: return http.HttpResponseServerError( 'This resource may only be accessed securely via https', content_type='text/plain') diff --git a/rpki/gui/default_settings.py b/rpki/gui/default_settings.py deleted file mode 100644 index 2f1a08ed..00000000 --- a/rpki/gui/default_settings.py +++ /dev/null @@ -1,180 +0,0 @@ -""" -This module contains static configuration settings for the web portal. -""" - -__version__ = '$Id$' - -import os -import random -import string -import socket - -import rpki.config -import rpki.autoconf - -# Where to put static files. -STATIC_ROOT = rpki.autoconf.datarootdir + '/rpki/media' - -# Must end with a slash! -STATIC_URL = '/media/' - -# Where to email server errors. -ADMINS = (('Administrator', 'root@localhost'),) - -LOGGING = { - 'version': 1, - 'formatters': { - 'verbose': { - # see http://docs.python.org/2.7/library/logging.html#logging.LogRecord - 'format': '%(levelname)s %(asctime)s %(name)s %(message)s' - }, - }, - 'handlers': { - 'stderr': { - 'class': 'logging.StreamHandler', - 'level': 'DEBUG', - 'formatter': 'verbose', - }, - 'mail_admins': { - 'level': 'ERROR', - 'class': 'django.utils.log.AdminEmailHandler', - }, - }, - 'loggers': { - 'rpki.async': { - # enabled for tracking https://trac.rpki.net/ticket/681 - # need to change this to WARNING once ticket is closed - 'level': 'DEBUG', - }, - # The Django default LOGGING configuration disables propagate on these - # two loggers. Re-enable propagate so they will hit our root logger. - 'django.request': { - 'propagate': True, - }, - 'django.security': { - 'propagate': True, - }, - }, - 'root': { - 'level': 'WARNING', - 'handlers': ['stderr', 'mail_admins'], - }, -} - -# Load the SQL authentication bits from the system rpki.conf. -rpki_config = rpki.config.parser(section='web_portal') - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': rpki_config.get('sql-database'), - 'USER': rpki_config.get('sql-username'), - 'PASSWORD': rpki_config.get('sql-password'), - - # Ensure the default storage engine is InnoDB since we need - # foreign key support. The Django documentation suggests - # removing this after the syncdb is performed as an optimization, - # but there isn't an easy way to do this automatically. - - 'OPTIONS': { - 'init_command': 'SET storage_engine=INNODB', - } - } -} - - -def select_tz(): - "Find a supported timezone that looks like UTC" - for tz in ('UTC', 'GMT', 'Etc/UTC', 'Etc/GMT'): - if os.path.exists('/usr/share/zoneinfo/' + tz): - return tz - # Can't determine the proper timezone, fall back to UTC and let Django - # report the error to the user. - return 'UTC' - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = select_tz() - -def get_secret_key(): - """Retrieve the secret-key value from rpki.conf or generate a random value - if it is not present.""" - d = string.letters + string.digits - val = ''.join([random.choice(d) for _ in range(50)]) - return rpki_config.get('secret-key', val) - -# Make this unique, and don't share it with anybody. -SECRET_KEY = get_secret_key() - -# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts -# for details on why you might need this. -def get_allowed_hosts(): - allowed_hosts = set(rpki_config.multiget("allowed-hosts")) - allowed_hosts.add(socket.getfqdn()) - try: - import netifaces - for interface in netifaces.interfaces(): - addresses = netifaces.ifaddresses(interface) - for af in (netifaces.AF_INET, netifaces.AF_INET6): - if af in addresses: - for address in addresses[af]: - if "addr" in address: - allowed_hosts.add(address["addr"]) - except ImportError: - pass - return list(allowed_hosts) - -ALLOWED_HOSTS = get_allowed_hosts() - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - 'django.template.loaders.eggs.Loader' -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware' -) - -ROOT_URLCONF = 'rpki.gui.urls' - -INSTALLED_APPS = ( - 'django.contrib.auth', - #'django.contrib.admin', - #'django.contrib.admindocs', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.staticfiles', - 'rpki.irdb', - 'rpki.gui.app', - 'rpki.gui.cacheview', - 'rpki.gui.routeview', - 'south', -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - "django.contrib.auth.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "django.contrib.messages.context_processors.messages", - "django.core.context_processors.request", - "django.core.context_processors.static" -) - -# Allow local site to override any setting above -- but if there's -# anything that local sites routinely need to modify, please consider -# putting that configuration into rpki.conf and just adding code here -# to read that configuration. -try: - from local_settings import * -except: - pass diff --git a/rpki/gui/models.py b/rpki/gui/models.py index 184383c0..62400d2a 100644 --- a/rpki/gui/models.py +++ b/rpki/gui/models.py @@ -42,8 +42,8 @@ class IPv6AddressField(models.Field): """ Note that we add a custom conversion to encode long values as hex strings in SQL statements. See settings.get_conv() for details. - """ + return value.toBytes() @@ -82,6 +82,7 @@ class Prefix(models.Model): """ Returns the prefix as a rpki.resource_set.resource_range_ip object. """ + return self.range_cls(self.prefix_min, self.prefix_max) @property @@ -96,6 +97,7 @@ class Prefix(models.Model): def __unicode__(self): """This method may be overridden by subclasses. The default implementation calls get_prefix_display(). """ + return self.get_prefix_display() class Meta: diff --git a/rpki/gui/routeview/api.py b/rpki/gui/routeview/api.py index cf699c9a..b4ff297a 100644 --- a/rpki/gui/routeview/api.py +++ b/rpki/gui/routeview/api.py @@ -29,8 +29,8 @@ def route_list(request): By default, only returns up to 10 matching routes, but the client may request a different limit with the 'count=' query string parameter. - """ + hard_limit = 100 if request.method == 'GET' and 'prefix__in' in request.GET: diff --git a/rpki/gui/routeview/util.py b/rpki/gui/routeview/util.py index 54d50f24..a2b515c8 100644 --- a/rpki/gui/routeview/util.py +++ b/rpki/gui/routeview/util.py @@ -179,8 +179,8 @@ def import_routeviews_dump(filename=DEFAULT_URL, filetype='auto'): filename [optional]: the full path to the downloaded file to parse filetype [optional]: 'text' or 'mrt' - """ + start_time = time.time() if filename.startswith('http://'): diff --git a/rpki/gui/script_util.py b/rpki/gui/script_util.py index fb15403d..1941f6f7 100644 --- a/rpki/gui/script_util.py +++ b/rpki/gui/script_util.py @@ -16,13 +16,6 @@ This module contains utility functions for use in standalone scripts. """ -import django - -from django.conf import settings - -from rpki import config -from rpki import autoconf - __version__ = '$Id$' @@ -30,20 +23,39 @@ def setup(): """ Configure Django enough to use the ORM. """ - cfg = config.parser(section='web_portal') - # INSTALLED_APPS doesn't seem necessary so long as you are only accessing - # existing tables. - settings.configure( - DATABASES={ - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': cfg.get('sql-database'), - 'USER': cfg.get('sql-username'), - 'PASSWORD': cfg.get('sql-password'), - } - }, - MIDDLEWARE_CLASSES = (), - ) - if django.VERSION >= (1, 7): - from django.apps import apps - apps.populate(settings.INSTALLED_APPS) + + # In theory we no longer need to call settings.configure, which + # probably means this whole module can go away soon, but leave + # breadcrumbs for now. + + if True: + import os + os.environ.update(DJANGO_SETTINGS_MODULE = "rpki.django_settings") + + else: + import django + from rpki import config + from rpki import autoconf + from django.conf import settings + + cfg = config.parser(section='web_portal') + # INSTALLED_APPS doesn't seem necessary so long as you are only accessing + # existing tables. + settings.configure( + DATABASES={ + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': cfg.get('sql-database'), + 'USER': cfg.get('sql-username'), + 'PASSWORD': cfg.get('sql-password'), + }, + }, + MIDDLEWARE_CLASSES = (), + ) + # Can't populate apps if we don't know what they are. If this + # explodes with an AppRegistryNotReady exception, the above comment + # about not needing to set INSTALLED_APPS is no longer true and + # you'll need to fix that here. + if False and django.VERSION >= (1, 7): + from django.apps import apps + apps.populate(settings.INSTALLED_APPS) |