wireguard_webadmin integration

This commit is contained in:
Eduardo Silva 2024-04-03 18:20:21 -03:00
parent fe604a8a49
commit 19b714dc21
13 changed files with 274 additions and 1 deletions

View file

View file

@ -0,0 +1,9 @@
from django.contrib import admin
from .models import ExternalIntegration
class ExternalIntegrationAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'integration_type', 'integration_url', 'wireguard_webadmin_default_user_level', 'token', 'created_at', 'updated_at')
search_fields = ('name', 'integration_type', 'integration_url', 'wireguard_webadmin_default_user_level', 'token', 'created_at', 'updated_at')
readonly_fields = ('created_at', 'updated_at')
admin.site.register(ExternalIntegration, ExternalIntegrationAdmin)

View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class IntegrationManagerConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'integration_manager'

View file

@ -0,0 +1,88 @@
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column, HTML
from .models import ExternalIntegration
import requests
class WireGuardWebAdminForm(forms.ModelForm):
token = forms.CharField(widget=forms.PasswordInput, required=False)
class Meta:
model = ExternalIntegration
fields = ['integration_url', 'wireguard_webadmin_default_user_level', 'token']
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(WireGuardWebAdminForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
if self.instance.token:
self.fields['token'].widget.attrs['placeholder'] = '************'
else:
delete_html = ''
self.helper.layout = Layout(
Row(
Column('integration_url', css_class='col-md-12'),
),
Row(
Column('wireguard_webadmin_default_user_level', css_class='col-md-12'),
),
Row(
Column('token', css_class='col-md-12'),
),
Row(
Column(
Submit('submit', 'Salvar', css_class='btn btn-success'),
HTML(' <a class="btn btn-secondary" href="/wireguard_webadmin/">Back</a> '),
HTML(delete_html),
css_class='col-md-12'),
css_class='form-row'
)
)
def clean(self):
cleaned_data = super().clean()
integration_url = cleaned_data.get('integration_url')
wireguard_webadmin_default_user_level = cleaned_data.get('wireguard_webadmin_default_user_level')
token = cleaned_data.get('token')
if integration_url.endswith('/'):
cleaned_data['integration_url'] = integration_url[:-1]
if not token and self.instance.token:
cleaned_data['token'] = self.instance.token
if not integration_url.startswith('https://'):
raise forms.ValidationError('Please use https://')
api_test_url = f"{cleaned_data['integration_url']}/api/routerfleet_get_user_token/"
api_test_url += f"?key={cleaned_data['token']}"
api_test_url += f"&username={self.user.username}&action=test"
try:
api_test = requests.get(api_test_url)
except:
raise forms.ValidationError('Error connecting to API')
try:
if api_test.status_code == 403:
api_response = {}
else:
api_response = api_test.json()
except:
raise forms.ValidationError('Error parsing API response')
if api_test.status_code == 403:
raise forms.ValidationError('Invalid token')
elif api_test.status_code == 400:
if api_response.get('message'):
raise forms.ValidationError(api_response.get('message'))
else:
raise forms.ValidationError(f'Error authenticating with API. Status Code: {api_test.status_code}')
elif api_test.status_code != 200:
raise forms.ValidationError(f'Error connecting to API. Status Code: {api_test.status_code}')
return cleaned_data

View file

@ -0,0 +1,27 @@
# Generated by Django 5.0.3 on 2024-04-03 19:21
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ExternalIntegration',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
('integration_type', models.CharField(choices=[('wireguard_webadmin', 'WireGuard WebAdmin')], max_length=100)),
('integration_url', models.URLField()),
('wireguard_webadmin_default_user_level', models.PositiveIntegerField(choices=[(10, 'Debugging Analyst'), (20, 'View Only User'), (30, 'Peer Manager'), (40, 'Manager'), (50, 'Administrator')], default=0)),
('token', models.CharField(max_length=100)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
),
]

View file

@ -0,0 +1,14 @@
from django.db import models
class ExternalIntegration(models.Model):
name = models.CharField(max_length=100, unique=True)
integration_type = models.CharField(max_length=100, choices=(('wireguard_webadmin', 'WireGuard WebAdmin'), ))
integration_url = models.URLField()
wireguard_webadmin_default_user_level = models.PositiveIntegerField(default=0, choices=((0, 'Do not create users'), (10, 'Debugging Analyst'), (20, 'View Only User'), (30, 'Peer Manager'), (40, 'Manager'), (50, 'Administrator')))
token = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name

View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View file

@ -0,0 +1,76 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from .models import ExternalIntegration
from .forms import WireGuardWebAdminForm
from django.contrib import messages
import requests
@login_required()
def view_wireguard_webadmin_launcher(request):
context = {
'page_title': 'WireGuard WebAdmin Launcher',
'wireguard_integration': ExternalIntegration.objects.filter(name='wireguard_webadmin', integration_type='wireguard_webadmin').first()
}
return render(request, 'integration_manager/wireguard_webadmin_launcher.html', context=context)
@login_required()
def view_launch_wireguard_webadmin(request):
wireguard_integration = get_object_or_404(ExternalIntegration, name='wireguard_webadmin', integration_type='wireguard_webadmin')
api_url = f"{wireguard_integration.integration_url}/api/routerfleet_get_user_token/"
api_url += f"?key={wireguard_integration.token}"
api_url += f"&username={request.user.username}&action=login"
api_url += f"&default_user_level={wireguard_integration.wireguard_webadmin_default_user_level}"
try:
api_response = requests.get(api_url)
except:
messages.warning(request, 'Error connecting to API')
return redirect('/wireguard_webadmin/')
try:
if api_response.status_code == 200:
api_json = api_response.json()
else:
api_json = {}
except:
messages.warning(request, 'Error parsing API response')
return redirect('/wireguard_webadmin/')
if api_response.status_code == 200:
redirect_url = f"{wireguard_integration.integration_url}/accounts/routerfleet_authenticate_session/"
redirect_url += f"?token={api_json.get('authentication_token')}"
return redirect(redirect_url)
else:
messages.warning(request, f'Error authenticating with API. Status Code: {api_response.status_code}')
return redirect('/wireguard_webadmin/')
@login_required()
def view_manage_wireguard_integration(request):
context = {
'page_title': 'Manage WireGuard Integration',
'delete_confirmation_message': 'Are you sure you want to delete this integration? This action cannot be undone. Type delete in the box below to confirm.'
}
wireguard_integration = ExternalIntegration.objects.filter(name='wireguard_webadmin', integration_type='wireguard_webadmin').first()
if request.GET.get('action') == 'delete':
if request.GET.get('confirmation') == 'delete':
wireguard_integration.delete()
messages.success(request, 'WireGuard WebAdmin integration deleted')
return redirect('/wireguard_webadmin/')
else:
messages.warning(request, 'Invalid confirmation. Integration not deleted')
return redirect('/wireguard_webadmin/')
form = WireGuardWebAdminForm(request.POST or None, instance=wireguard_integration, user=request.user)
if form.is_valid():
this_form = form.save(commit=False)
this_form.name = 'wireguard_webadmin'
this_form.integration_type = 'wireguard_webadmin'
this_form.save()
messages.success(request, 'WireGuard WebAdmin integration saved')
return redirect('/wireguard_webadmin/')
context['form'] = form
return render(request, 'generic_form.html', context=context)

View file

@ -44,7 +44,8 @@ INSTALLED_APPS = [
'router_manager',
'monitoring',
'backup',
'backup_data'
'backup_data',
'integration_manager',
]
MIDDLEWARE = [

View file

@ -1,6 +1,7 @@
from django.contrib import admin
from django.urls import path
from dashboard.views import view_dashboard, view_status
from integration_manager.views import view_wireguard_webadmin_launcher, view_manage_wireguard_integration, view_launch_wireguard_webadmin
from user_manager.views import view_manage_user, view_user_list
from accounts.views import view_login, view_logout, view_create_first_user
from router_manager.views import view_router_list, view_manage_router, view_router_group_list, view_ssh_key_list, view_manage_router_group, view_manage_sshkey, view_router_details, view_create_instant_backup_task
@ -40,4 +41,7 @@ urlpatterns = [
path('cron/create_backup_tasks/', view_create_backup_tasks, name='create_backup_tasks'),
path('cron/perform_backup_tasks/', view_perform_backup_tasks, name='perform_backup_tasks'),
path('cron/housekeeping/', view_housekeeping, name='housekeeping'),
path('wireguard_webadmin/', view_wireguard_webadmin_launcher, name='wireguard_webadmin_launcher'),
path('wireguard_webadmin/manage/', view_manage_wireguard_integration, name='manage_wireguard_integration'),
path('wireguard_webadmin/launch/', view_launch_wireguard_webadmin, name='launch_wireguard_webadmin')
]

View file

@ -131,6 +131,15 @@
</a>
</li>
<li class="nav-item">
<a href="/wireguard_webadmin/" class="nav-link {% if '/wireguard_webadmin/' in request.path %}active{% endif %}">
<i class="fas fa-project-diagram nav-icon"></i>
<p>
WireGuard WebAdmin
</p>
</a>
</li>
</ul>
</nav>
<!-- /.sidebar-menu -->

View file

@ -0,0 +1,36 @@
{% extends 'base.html' %}
{% block content %}
<div class='row'>
<div class='col-lg-6'>
<div class="card card-primary card-outline">
<div class="card-header">
<h3 class="card-title">wireguard_webadmin</h3>
</div>
<div class="card-body ">
<div class="row">
<div class="col-lg-12">
<p>
<strong>wireguard_webadmin</strong> is a full-featured yet easy-to-configure web interface for managing WireGuard VPN instances. Designed to simplify the administration of WireGuard networks, it provides a user-friendly interface that supports multiple users with varying access levels, multiple WireGuard instances with individual peer management, and support for crypto key routing for site-to-site interconnections.<br><br>
For more information, please visit the project's GitHub repository<br> <a href="https://github.com/eduardogsilva/wireguard_webadmin" target="_blank"><i class="fab fa-github"></i> eduardogsilva/wireguard_webadmin</a>
</p>
</div>
<div class="col-md-6">
{% if wireguard_integration %}
<a href="/wireguard_webadmin/launch/" class="btn btn-primary btn-block" target="_blank"><i class="fas fa-project-diagram"></i> Launch wireguard_webadmin</a>
{% else %}
<a href="#" class="btn btn-primary btn-block disabled" ><i class="fas fa-project-diagram"></i> Launch wireguard_webadmin</a>
{% endif %}
</div>
<div class="col-md-6">
<a href="/wireguard_webadmin/manage/" class="btn btn-primary btn-block"><i class="fas fa-cogs"></i> Configure Integration</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}