From aa02f4d710a9a9fff787461adb41cff823bdbd43 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Thu, 5 Sep 2019 11:46:31 -0400 Subject: [PATCH] wireguard: Implement adding client Signed-off-by: James Valleroy Reviewed-by: Sunil Mohan Adapa --- actions/wireguard | 57 +++++++++++++++++++ plinth/modules/wireguard/__init__.py | 6 +- plinth/modules/wireguard/forms.py | 29 ++++++++++ plinth/modules/wireguard/manifest.py | 3 +- .../wireguard/templates/wireguard.html | 7 ++- .../templates/wireguard_add_client.html | 37 ++++++++++++ plinth/modules/wireguard/urls.py | 2 + plinth/modules/wireguard/views.py | 27 +++++++++ 8 files changed, 164 insertions(+), 4 deletions(-) create mode 100755 actions/wireguard create mode 100644 plinth/modules/wireguard/forms.py create mode 100644 plinth/modules/wireguard/templates/wireguard_add_client.html diff --git a/actions/wireguard b/actions/wireguard new file mode 100755 index 000000000..261b90452 --- /dev/null +++ b/actions/wireguard @@ -0,0 +1,57 @@ +#!/usr/bin/python3 +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Configuration helper for WireGuard. +""" + +import argparse +import subprocess + +SERVER_INTERFACE = 'wg0' + + +def parse_arguments(): + """Return parsed command line arguments as dictionary.""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') + + add_client = subparsers.add_parser('add-client', help='Add a client') + add_client.add_argument('publickey', help='Public key for the client') + + subparsers.required = True + return parser.parse_args() + + +def subcommand_add_client(arguments): + """Add a client.""" + subprocess.run( + ['wg', 'set', SERVER_INTERFACE, 'peer', arguments.publickey], + check=True) + + +def main(): + """Parse arguments and perform all duties.""" + arguments = parse_arguments() + + subcommand = arguments.subcommand.replace('-', '_') + subcommand_method = globals()['subcommand_' + subcommand] + subcommand_method(arguments) + + +if __name__ == '__main__': + main() diff --git a/plinth/modules/wireguard/__init__.py b/plinth/modules/wireguard/__init__.py index 6656b4cdb..fd67c345e 100644 --- a/plinth/modules/wireguard/__init__.py +++ b/plinth/modules/wireguard/__init__.py @@ -18,6 +18,7 @@ FreedomBox app for wireguard. """ +from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ from plinth import app as app_module @@ -71,8 +72,9 @@ class WireguardApp(app_module.App): shortcut = frontpage.Shortcut( 'shortcut-wireguard', name, short_description=short_description, - icon='wireguard', url='/wireguard', clients=clients, - login_required=True) + icon='wireguard', description=description, + configure_url=reverse_lazy('wireguard:index'), login_required=True, + clients=clients) self.add(shortcut) firewall = Firewall('firewall-wireguard', name, diff --git a/plinth/modules/wireguard/forms.py b/plinth/modules/wireguard/forms.py new file mode 100644 index 000000000..54c65a584 --- /dev/null +++ b/plinth/modules/wireguard/forms.py @@ -0,0 +1,29 @@ +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +""" +Forms for wireguard module. +""" + +from django import forms +from django.utils.translation import ugettext_lazy as _ + + +class AddClientForm(forms.Form): + """Form to add client.""" + public_key = forms.CharField( + label=_('Public Key'), strip=True, + help_text=_('Public key of the peer.')) diff --git a/plinth/modules/wireguard/manifest.py b/plinth/modules/wireguard/manifest.py index ac8c286f5..2322d3895 100644 --- a/plinth/modules/wireguard/manifest.py +++ b/plinth/modules/wireguard/manifest.py @@ -33,7 +33,8 @@ clients = validate([{ 'os': 'windows', 'url': - 'https://download.wireguard.com/windows-client/wireguard-amd64-0.0.23.msi' + 'https://download.wireguard.com/windows-client/' + 'wireguard-amd64-0.0.23.msi' }, { 'type': 'download', diff --git a/plinth/modules/wireguard/templates/wireguard.html b/plinth/modules/wireguard/templates/wireguard.html index cb59e21d5..499a3368f 100644 --- a/plinth/modules/wireguard/templates/wireguard.html +++ b/plinth/modules/wireguard/templates/wireguard.html @@ -27,7 +27,12 @@
    {% trans "public key" %}
    {% trans "last connected time" %}
    {% trans "edit" %}
-
    {% trans "Add Client" %}
+ + + {% trans "Add Client" %} +

{% trans "Client" %}

{% trans "Peer servers that FreedomBox will connect to" %}

diff --git a/plinth/modules/wireguard/templates/wireguard_add_client.html b/plinth/modules/wireguard/templates/wireguard_add_client.html new file mode 100644 index 000000000..3aa891a17 --- /dev/null +++ b/plinth/modules/wireguard/templates/wireguard_add_client.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% comment %} +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} + +{% block content %} + +

{{ title }}

+ +
+ {% csrf_token %} + + {{ form|bootstrap }} + + +
+ +{% endblock %} diff --git a/plinth/modules/wireguard/urls.py b/plinth/modules/wireguard/urls.py index 7fb96603b..96b2f5de0 100644 --- a/plinth/modules/wireguard/urls.py +++ b/plinth/modules/wireguard/urls.py @@ -24,4 +24,6 @@ from plinth.modules.wireguard import views urlpatterns = [ url(r'^apps/wireguard/$', views.WireguardView.as_view(), name='index'), + url(r'^apps/wireguard/client/add/$', views.AddClientView.as_view(), + name='add-client') ] diff --git a/plinth/modules/wireguard/views.py b/plinth/modules/wireguard/views.py index 7962659ec..1e72dd21d 100644 --- a/plinth/modules/wireguard/views.py +++ b/plinth/modules/wireguard/views.py @@ -18,9 +18,17 @@ Views for WireGuard application. """ +from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin +from django.utils.translation import ugettext as _ +from django.views.generic import FormView + import plinth.modules.wireguard as wireguard +from plinth import actions from plinth.views import AppView +from . import forms + class WireguardView(AppView): """Serve configuration page.""" @@ -32,3 +40,22 @@ class WireguardView(AppView): show_status_block = False template_name = 'wireguard.html' port_forwarding_info = wireguard.port_forwarding_info + + +class AddClientView(SuccessMessageMixin, FormView): + """View to add a client.""" + form_class = forms.AddClientForm + template_name = 'wireguard_add_client.html' + + def get_context_data(self, **kwargs): + """Return additional context for rendering the template.""" + context = super().get_context_data(**kwargs) + context['title'] = _('Add Client') + return context + + def form_valid(self, form): + """Add the client.""" + public_key = form.cleaned_data.get('public_key') + actions.superuser_run( + 'wireguard', ['add-client', public_key]) + messages.success(self.request, _('Added new client.'))