From 10e456b2027df45baf0af1b6872c0a23ed883255 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Tue, 21 Jan 2025 13:22:18 -0300 Subject: [PATCH] User toggle for webconsole and enhanced filter --- console/views.py | 29 +++++++++++++------ templates/user_manager/list.html | 12 ++++++++ templates/user_manager/list_buttons.html | 4 +-- user_manager/forms.py | 23 ++++++++++++++- .../0005_useracl_enable_console_and_more.py | 23 +++++++++++++++ user_manager/models.py | 2 ++ user_manager/views.py | 6 ++++ wireguard/views.py | 18 ++++++++---- 8 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 user_manager/migrations/0005_useracl_enable_console_and_more.py diff --git a/console/views.py b/console/views.py index b8d59cf..39d7f07 100644 --- a/console/views.py +++ b/console/views.py @@ -1,13 +1,19 @@ from wireguard.models import WireGuardInstance from wgwadmlibrary.tools import is_valid_ip_or_hostname -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required +from user_manager.models import UserAcl import subprocess @login_required def view_console(request): page_title = 'Console' + user_acl = get_object_or_404(UserAcl, user=request.user) + + if not user_acl.enable_console: + return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) + wireguard_instances = WireGuardInstance.objects.all().order_by('instance_id') if wireguard_instances.filter(pending_changes=True).exists(): pending_changes_warning = True @@ -59,14 +65,19 @@ def view_console(request): command_output = requested_command + ': Invalid target' bash_command = None command_success = False - - if bash_command: - try: - command_output = subprocess.check_output(bash_command, stderr=subprocess.STDOUT).decode('utf-8') - command_success = True - except subprocess.CalledProcessError as e: - command_output = e.output.decode('utf-8') - command_success = False + + if user_acl.enable_enhanced_filter and requested_command == 'wgshow': + command_output = 'Enhanced filter is enabled. This command is not available.' + bash_command = None + command_success = False + else: + if bash_command: + try: + command_output = subprocess.check_output(bash_command, stderr=subprocess.STDOUT).decode('utf-8') + command_success = True + except subprocess.CalledProcessError as e: + command_output = e.output.decode('utf-8') + command_success = False context = {'page_title': page_title, 'command_output': command_output, 'command_success': command_success, 'pending_changes_warning': pending_changes_warning} return render(request, 'console/console.html', context) \ No newline at end of file diff --git a/templates/user_manager/list.html b/templates/user_manager/list.html index 532a5d3..be45bb0 100644 --- a/templates/user_manager/list.html +++ b/templates/user_manager/list.html @@ -8,6 +8,8 @@ User Level Peer Groups + + @@ -24,6 +26,16 @@ Any {% endif %} + + {% if user_acl.enable_console %} + + {% endif %} + + + {% if user_acl.enable_enhanced_filter %} + + {% endif %} + diff --git a/templates/user_manager/list_buttons.html b/templates/user_manager/list_buttons.html index cb2ceaa..f3d10e4 100644 --- a/templates/user_manager/list_buttons.html +++ b/templates/user_manager/list_buttons.html @@ -1,6 +1,4 @@ Add User List Users List Peer Groups -Add Peer Group -


Warning:
-

The limitation of Peer Groups for users is implemented. However, in some places, information about other peers may still leak, such as in Console -> wg show or through the endpoint /api/wireguard_status/. In the next version, we will add a fix for this.

\ No newline at end of file +Add Peer Group \ No newline at end of file diff --git a/user_manager/forms.py b/user_manager/forms.py index 145641d..fc8a0e4 100644 --- a/user_manager/forms.py +++ b/user_manager/forms.py @@ -12,6 +12,8 @@ class UserAclForm(forms.Form): username = forms.CharField(max_length=150) password1 = forms.CharField(widget=forms.PasswordInput, required=False, label="Password") password2 = forms.CharField(widget=forms.PasswordInput, required=False, label="Password confirmation") + enable_console = forms.BooleanField(required=False, label="Enable Console") + enable_enhanced_filter = forms.BooleanField(required=False, label="Enable Enhanced Filter") user_level = forms.ChoiceField(choices=UserAcl.user_level.field.choices, required=True, label="User Level") peer_groups = forms.ModelMultipleChoiceField( queryset=PeerGroup.objects.all(), @@ -27,9 +29,16 @@ class UserAclForm(forms.Form): self.fields['username'].initial = self.instance.username self.fields['username'].widget.attrs['readonly'] = True self.fields['peer_groups'].initial = self.instance.useracl.peer_groups.all() + self.fields['enable_console'].initial = self.instance.useracl.enable_console + self.fields['enable_enhanced_filter'].initial = self.instance.useracl.enable_enhanced_filter else: self.fields['password1'].required = True self.fields['password2'].required = True + self.fields['enable_console'].initial = True + self.fields['enable_enhanced_filter'].initial = False + + self.fields['enable_console'].label = "Console" + self.fields['enable_enhanced_filter'].label = "Enhanced Filter" self.helper = FormHelper() self.helper.form_method = 'post' @@ -60,6 +69,14 @@ class UserAclForm(forms.Form): Column('peer_groups', css_class='form-group col-md-12 mb-0'), css_class='form-row' ), + Row( + Column('enable_console', css_class='form-group col-md-12 mb-0'), + css_class='form-row' + ), + Row( + Column('enable_enhanced_filter', css_class='form-group col-md-12 mb-0'), + css_class='form-row' + ), Row( Column( Submit('submit', 'Save', css_class='btn btn-success'), @@ -100,6 +117,8 @@ class UserAclForm(forms.Form): password = self.cleaned_data.get('password1') user_level = self.cleaned_data['user_level'] peer_groups = self.cleaned_data.get('peer_groups', []) + enable_console = self.cleaned_data.get('enable_console', False) + enable_enhanced_filter = self.cleaned_data.get('enable_enhanced_filter', False) if self.instance: user = self.instance @@ -115,7 +134,9 @@ class UserAclForm(forms.Form): user_acl, created = UserAcl.objects.update_or_create( user=user, defaults={ - 'user_level': user_level + 'user_level': user_level, + 'enable_console': enable_console, + 'enable_enhanced_filter': enable_enhanced_filter } ) diff --git a/user_manager/migrations/0005_useracl_enable_console_and_more.py b/user_manager/migrations/0005_useracl_enable_console_and_more.py new file mode 100644 index 0000000..e72c91a --- /dev/null +++ b/user_manager/migrations/0005_useracl_enable_console_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.5 on 2025-01-21 15:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user_manager', '0004_useracl_peer_groups'), + ] + + operations = [ + migrations.AddField( + model_name='useracl', + name='enable_console', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='useracl', + name='enable_enhanced_filter', + field=models.BooleanField(default=False), + ), + ] diff --git a/user_manager/models.py b/user_manager/models.py index 923edcb..56c4bea 100644 --- a/user_manager/models.py +++ b/user_manager/models.py @@ -14,6 +14,8 @@ class UserAcl(models.Model): (50, 'Administrator'), )) peer_groups = models.ManyToManyField(PeerGroup, blank=True) + enable_console = models.BooleanField(default=True) + enable_enhanced_filter = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) diff --git a/user_manager/views.py b/user_manager/views.py index 6550416..5299c32 100644 --- a/user_manager/views.py +++ b/user_manager/views.py @@ -156,6 +156,12 @@ def view_manage_user(request):

Peer Groups

Select which peer groups this user can access. If no peer groups are selected, the user will have access to all peers.

+

Console

+

Enable or disable web console access for this user.

+ +

Enhanced Filter

+

This option filters the API status response to include only peers that the user has access to. Depending on the size of your environment, enabling this option may impact performance. To mitigate this, consider increasing the "Web Refresh Interval" to reduce the number of requests.

+ ''' } diff --git a/wireguard/views.py b/wireguard/views.py index 3ab12d9..378bb8e 100644 --- a/wireguard/views.py +++ b/wireguard/views.py @@ -78,19 +78,25 @@ def view_welcome(request): @login_required def view_wireguard_status(request): + user_acl = get_object_or_404(UserAcl, user=request.user) page_title = 'WireGuard Status' wireguard_instances = WireGuardInstance.objects.all().order_by('instance_id') if wireguard_instances.filter(pending_changes=True).exists(): pending_changes_warning = True else: pending_changes_warning = False - bash_command = ['bash', '-c', 'wg show'] - try: - command_output = subprocess.check_output(bash_command, stderr=subprocess.STDOUT).decode('utf-8') + + if user_acl.enable_enhanced_filter: + command_output = 'Enhanced filter is enabled. This command is not available.' command_success = True - except subprocess.CalledProcessError as e: - command_output = e.output.decode('utf-8') - command_success = False + else: + bash_command = ['bash', '-c', 'wg show'] + try: + command_output = subprocess.check_output(bash_command, stderr=subprocess.STDOUT).decode('utf-8') + command_success = True + except subprocess.CalledProcessError as e: + command_output = e.output.decode('utf-8') + command_success = False context = {'page_title': page_title, 'command_output': command_output, 'command_success': command_success, 'pending_changes_warning': pending_changes_warning, 'wireguard_instances': wireguard_instances} return render(request, 'wireguard/wireguard_status.html', context)