aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/gui
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki/gui')
-rw-r--r--rpkid/rpki/gui/app/forms.py70
-rw-r--r--rpkid/rpki/gui/app/glue.py17
-rw-r--r--rpkid/rpki/gui/app/settings.py.in4
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/child_wizard_form.html13
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/dashboard.html8
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/import_child_form.html13
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/import_parent_form.html13
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/import_pubclient_form.html13
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/import_repository_form.html13
-rw-r--r--rpkid/rpki/gui/app/templates/rpkigui/initialize_form.html13
-rw-r--r--rpkid/rpki/gui/app/urls.py6
-rw-r--r--rpkid/rpki/gui/app/views.py146
12 files changed, 324 insertions, 5 deletions
diff --git a/rpkid/rpki/gui/app/forms.py b/rpkid/rpki/gui/app/forms.py
index c638c287..bb5b6da9 100644
--- a/rpkid/rpki/gui/app/forms.py
+++ b/rpkid/rpki/gui/app/forms.py
@@ -46,8 +46,8 @@ class AddConfForm(forms.Form):
class ImportForm(forms.Form):
'''Form used for uploading parent/child identity xml files'''
- handle = forms.CharField()
- xml = forms.FileField()
+ handle = forms.CharField(max_length=30, help_text='your name for this entity')
+ xml = forms.FileField(help_text='xml filename')
def PrefixSplitForm(parent, *args, **kwargs):
class _wrapper(forms.Form):
@@ -207,4 +207,70 @@ class ChildForm(forms.ModelForm):
model = models.Child
exclude = [ 'conf', 'handle' ]
+def ImportChildForm(parent_conf, *args, **kwargs):
+ class wrapped(forms.Form):
+ handle = forms.CharField(max_length=30, help_text="Child's RPKI handle")
+
+ child = forms.ModelChoiceField(queryset=models.Conf.objects.all(), required=False,
+ help_text="import locally hosted child")
+ xml = forms.FileField(help_text="Child's identity.xml files", required=False)
+
+ def clean_handle(self):
+ if parent_conf.children.filter(handle=self.cleaned_data['handle']):
+ raise forms.ValidationError, "a child with that handle already exists"
+ return self.cleaned_data['handle']
+
+ def clean(self):
+ if ((self.cleaned_data.get('child') and self.cleaned_data.get('xml')) or
+ not (self.cleaned_data.get('child') or self.cleaned_data.get('xml'))):
+ raise forms.ValidationError, "specify either a locally hosted resource handle OR identity.xml file"
+ return self.cleaned_data
+
+ return wrapped(*args, **kwargs)
+
+def ImportParentForm(conf, *args, **kwargs):
+ class wrapped(forms.Form):
+ handle = forms.CharField(max_length=30, help_text="Parent's RPKI handle")
+
+ parent = forms.ModelChoiceField(queryset=models.Conf.objects.all(), required=False,
+ help_text="import locally hosted parent")
+ xml = forms.FileField(help_text="Parent's identity.xml files", required=False)
+
+ def clean_handle(self):
+ if conf.parents.filter(handle=self.cleaned_data['handle']):
+ raise forms.ValidationError, "a parent with that handle already exists"
+ return self.cleaned_data['handle']
+
+ def clean(self):
+ if ((self.cleaned_data.get('parent') and self.cleaned_data.get('xml')) or
+ not (self.cleaned_data.get('parent') or self.cleaned_data.get('xml'))):
+ raise forms.ValidationError, "specify either a locally hosted resource handle OR xml file"
+ return self.cleaned_data
+
+ return wrapped(*args, **kwargs)
+
+class ImportRepositoryForm(forms.Form):
+ parent_handle = forms.CharField(max_length=30, required=False, help_text='(optional)')
+ xml = forms.FileField(help_text='xml file from repository operator')
+
+class ImportPubClientForm(forms.Form):
+ xml = forms.FileField(help_text='xml file from publication client')
+
+class InitializeForm(forms.Form):
+ """
+ Stub form for initialize new resource handles.
+ """
+ pass
+
+def ChildWizardForm(parent, *args, **kwargs):
+ class wrapped(forms.Form):
+ handle = forms.CharField(max_length=30, help_text='handle for new child')
+
+ def clean_handle(self):
+ if parent.children.filter(handle=self.cleaned_data['handle']):
+ raise forms.ValidationError, 'a child with that handle already exists'
+ return self.cleaned_data['handle']
+
+ return wrapped(*args, **kwargs)
+
# vim:sw=4 ts=8 expandtab
diff --git a/rpkid/rpki/gui/app/glue.py b/rpkid/rpki/gui/app/glue.py
index e99aa837..0664e86c 100644
--- a/rpkid/rpki/gui/app/glue.py
+++ b/rpkid/rpki/gui/app/glue.py
@@ -70,6 +70,10 @@ def output_roas(path, handle):
'%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
@@ -126,8 +130,18 @@ def configure_resources(log, handle):
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 = confpath(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()
@@ -168,7 +182,8 @@ def configure_resources(log, handle):
ghostbusters.append((None, vcard))
# for hosted handles, get the config for the irdbd/rpkid host
- cfg = rpki.config.parser(confpath(handle.host.handle if handle.host else handle.handle, 'rpki.conf'), 'myrpki')
+ if handle.host:
+ cfg = rpki.config.parser(confpath(handle.host.handle, 'rpki.conf'), 'myrpki')
irdb = IRDB(cfg)
irdb.update(handle, roa_requests, children, ghostbusters)
diff --git a/rpkid/rpki/gui/app/settings.py.in b/rpkid/rpki/gui/app/settings.py.in
index 0ee436b7..28410f35 100644
--- a/rpkid/rpki/gui/app/settings.py.in
+++ b/rpkid/rpki/gui/app/settings.py.in
@@ -7,8 +7,6 @@
from django.conf import settings
-MYRPKI = settings.MYRPKI if hasattr(settings, 'MYRPKI') else '%(AC_MYRPKI)s'
-
# directory containing the resource handles served by the rpki portal gui
CONFDIR = settings.MYRPKI if hasattr(settings, 'CONFDIR') else '%(AC_LOCALSTATEDIR)s/rpki/conf'
@@ -20,3 +18,5 @@ OUTBOX = settings.MYRPKI if hasattr(settings, 'OUTBOX') else '%(AC_LOCALSTATEDIR
# uid the web server runs as
WEB_USER = settings.MYRPKI if hasattr(settings, 'WEB_USER') else '%(AC_WEBUSER)s'
+
+RPKI_CONF_TEMPLATE = settings.RPKI_CONF_TEMPLATE = settings.RPKI_CONF_TEMPLATE if hasattr(settings, 'RPKI_CONF_TEMPLATE') else '%(AC_DATAROOTDIR)s/rpki/gui/rpki.conf.template'
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/child_wizard_form.html b/rpkid/rpki/gui/app/templates/rpkigui/child_wizard_form.html
new file mode 100644
index 00000000..85c85ed5
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/child_wizard_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<form enctype="multipart/form-data" method="POST" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <table>
+{{ form.as_table }}
+</table>
+<input type="submit" value="Create">
+</form>
+
+{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/dashboard.html b/rpkid/rpki/gui/app/templates/rpkigui/dashboard.html
index d31d01c2..bcb2d4fd 100644
--- a/rpkid/rpki/gui/app/templates/rpkigui/dashboard.html
+++ b/rpkid/rpki/gui/app/templates/rpkigui/dashboard.html
@@ -22,6 +22,14 @@ h2 { text-align:center; background-color:#dddddd }
</ul>
<ul class='compact'>
+ <li><a href="{% url rpki.gui.app.views.import_child %}">import child</a></li>
+ <li><a href="{% url rpki.gui.app.views.import_parent %}">import parent</a></li>
+ <li><a href="{% url rpki.gui.app.views.import_repository %}">import repository</a></li>
+ <li><a href="{% url rpki.gui.app.views.import_pubclient %}">import pubclient</a></li>
+ <li><a href="{% url rpki.gui.app.views.child_wizard %}">create child wizard</a></li>
+</ul>
+
+<ul class='compact'>
<li><a href="{% url rpki.gui.app.views.refresh %}">refresh</a></li>
</ul>
{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/import_child_form.html b/rpkid/rpki/gui/app/templates/rpkigui/import_child_form.html
new file mode 100644
index 00000000..acd6bf61
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/import_child_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<form enctype="multipart/form-data" method="POST" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <table>
+{{ form.as_table }}
+</table>
+<input type="submit" value="Import">
+</form>
+
+{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/import_parent_form.html b/rpkid/rpki/gui/app/templates/rpkigui/import_parent_form.html
new file mode 100644
index 00000000..acd6bf61
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/import_parent_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<form enctype="multipart/form-data" method="POST" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <table>
+{{ form.as_table }}
+</table>
+<input type="submit" value="Import">
+</form>
+
+{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/import_pubclient_form.html b/rpkid/rpki/gui/app/templates/rpkigui/import_pubclient_form.html
new file mode 100644
index 00000000..acd6bf61
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/import_pubclient_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<form enctype="multipart/form-data" method="POST" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <table>
+{{ form.as_table }}
+</table>
+<input type="submit" value="Import">
+</form>
+
+{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/import_repository_form.html b/rpkid/rpki/gui/app/templates/rpkigui/import_repository_form.html
new file mode 100644
index 00000000..acd6bf61
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/import_repository_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<form enctype="multipart/form-data" method="POST" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <table>
+{{ form.as_table }}
+</table>
+<input type="submit" value="Import">
+</form>
+
+{% endblock %}
diff --git a/rpkid/rpki/gui/app/templates/rpkigui/initialize_form.html b/rpkid/rpki/gui/app/templates/rpkigui/initialize_form.html
new file mode 100644
index 00000000..372316ee
--- /dev/null
+++ b/rpkid/rpki/gui/app/templates/rpkigui/initialize_form.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<p>Your account has not been initialized. Please click on the button to initialize.</P>
+
+<form method="post" action="{{ request.get_full_path }}">
+ {% csrf_token %}
+ <input type=submit value='Intialize'>
+</form>
+
+{% endblock %}
+
diff --git a/rpkid/rpki/gui/app/urls.py b/rpkid/rpki/gui/app/urls.py
index 050a03a7..dff8b69c 100644
--- a/rpkid/rpki/gui/app/urls.py
+++ b/rpkid/rpki/gui/app/urls.py
@@ -49,6 +49,12 @@ urlpatterns = patterns('',
(r'^demo/myrpki-xml/(?P<self_handle>[^/]+)$', views.myrpki_xml),
(r'^demo/parent-request/(?P<self_handle>[^/]+)$', views.parent_request),
(r'^demo/repository-request/(?P<self_handle>[^/]+)$', views.repository_request),
+ (r'^import_child$', views.import_child),
+ (r'^import_parent$', views.import_parent),
+ (r'^import_pubclient$', views.import_pubclient),
+ (r'^import_repository$', views.import_repository),
+# (r'^initialize$', views.initialize),
+ (r'^child_wizard$', views.child_wizard),
)
# vim:sw=4 ts=8 expandtab
diff --git a/rpkid/rpki/gui/app/views.py b/rpkid/rpki/gui/app/views.py
index 6521618d..4b175ee8 100644
--- a/rpkid/rpki/gui/app/views.py
+++ b/rpkid/rpki/gui/app/views.py
@@ -643,4 +643,150 @@ def refresh(request):
glue.list_received_resources(request.META['wsgi.errors'], request.session['handle'])
return http.HttpResponseRedirect(reverse(dashboard))
+@handle_required
+def import_parent(request):
+ conf = request.session['handle']
+ log = request.META['wsgi.errors']
+
+ if request.method == 'POST':
+ form = forms.ImportParentForm(conf, request.POST, request.FILES)
+ if form.is_valid():
+ tmpf = None
+
+ # determine if we are importing a locally hosted parent or an identity.xml file
+ if form.get('parent'):
+ # locally hosted
+ f = confdir(form['parent'].handle, 'entitydb', 'children', conf.handle + '.xml')
+ else:
+ # uploaded xml file
+ tmpf = NamedTemporaryFile(prefix='parent', suffix='xml', delete=False)
+ f = tmpf.name
+ tmpf.write(f.read())
+ tmpf.close()
+
+ obj = glue.import_parent(log, conf, form.get('handle'), f)
+
+ if tmpf:
+ os.remove(tmpf.name)
+
+ return http.HttpResponseRedirect(obj.get_absolute_url())
+ else:
+ form = forms.ImportParentForm(conf)
+
+ return render('rpkigui/import_parent_form.html', { 'form': form }, request)
+
+@handle_required
+def import_repository(request):
+ conf = request.session['handle']
+ log = request.META['wsgi.errors']
+
+ if request.method == 'POST':
+ form = forms.ImportRepositoryForm(request.POST, request.FILES)
+ if form.is_valid():
+ # uploaded xml file
+ tmpf = NamedTemporaryFile(prefix='repository', suffix='xml', delete=False)
+ f = tmpf.name
+ tmpf.write(f.read())
+ tmpf.close()
+
+ obj = glue.import_repository(log, conf, f)
+
+ os.remove(tmpf.name)
+
+ return http.HttpResponseRedirect(obj.get_absolute_url())
+ else:
+ form = forms.ImportRepositoryForm()
+
+ return render('rpkigui/import_repository_form.html', { 'form': form }, request)
+
+@handle_required
+def import_pubclient(request):
+ conf = request.session['handle']
+ log = request.META['wsgi.errors']
+
+ if request.method == 'POST':
+ form = forms.ImportPubClientForm(request.POST, request.FILES)
+ if form.is_valid():
+ # uploaded xml file
+ tmpf = NamedTemporaryFile(prefix='pubclient', suffix='xml', delete=False)
+ f = tmpf.name
+ tmpf.write(f.read())
+ tmpf.close()
+
+ obj = glue.import_repository(log, conf, f)
+
+ os.remove(tmpf.name)
+
+ return http.HttpResponseRedirect(obj.get_absolute_url())
+ else:
+ form = forms.ImportPubClientForm()
+
+ return render('rpkigui/import_pubclient_form.html', { 'form': form }, request)
+
+@handle_required
+def import_child(request):
+ """
+ Import a repository response.
+ """
+ conf = request.session['handle']
+ log = request.META['wsgi.errors']
+ tmpf = None
+
+ if request.method == 'POST':
+ form = forms.ImportChildForm(conf, request.POST, request.FILES)
+ if form.is_valid():
+ # determine if we are importing a locally hosted child or an identity.xml file
+ if form.get('child'):
+ # locally hosted
+ f = confdir(child.handle, 'entitydb', 'identity.xml')
+ else:
+ # identity.xml
+ tmpf = NamedTemporaryFile(prefix='identity', suffix='xml', delete=False)
+ f = tmpf.name
+ tmpf.write(f.read())
+ tmpf.close()
+
+ obj = glue.import_child(log, conf, form.cleaned_data['handle'], f)
+
+ if tmpf:
+ os.remove(tmpf.name)
+
+ return http.HttpResponseRedirect(obj.get_absolute_url())
+ else:
+ form = forms.ImportChildForm(conf)
+
+ return render('rpkigui/import_child_form.html', { 'form': form }, request)
+
+@login_required
+def initialize(request):
+ """
+ Initialize a new user account.
+ """
+ if request.method == 'POST':
+ form = forms.InitializeForm(request.POST)
+ if form.is_valid():
+ glue.initialize_handle(request.META['wsgi.errors'], handle=request.user.username, owner=request.user)
+ return http.HttpResponseRedirect(reverse(dashboard))
+ else:
+ form = forms.InitializeForm()
+
+ return render('rpkigui/initialize_form.html', { 'form': form }, request)
+
+@handle_required
+def child_wizard(request):
+ """
+ Wizard mode to create a new locally hosted child.
+ """
+ conf = request.session['handle']
+ log = request.META['wsgi.errors']
+ if request.method == 'POST':
+ form = forms.ChildWizardForm(conf, request.POST)
+ if form.is_valid():
+ glue.create_child(log, conf, form.cleaned_data['handle'])
+ return http.HttpResponseRedirect(reverse(dashboard))
+ else:
+ form = forms.ChildWizardForm(conf)
+
+ return render('rpkigui/child_wizard_form.html', { 'form': form }, request)
+
# vim:sw=4 ts=8 expandtab