From 01a4225a84970c48c426dd1d2c36d5091adf6868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie=20Krej=C4=8D=C3=AD?= Date: Mon, 11 Sep 2023 21:16:51 +0200 Subject: [PATCH 01/17] Add django-auth-ldap dependency --- conf/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/requirements.txt b/conf/requirements.txt index 64206b8..a9390be 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -20,3 +20,4 @@ djangorestframework==3.14.0 drf-nested-routers==0.93.4 drf-yasg==1.21.7 markdown>=3.4.1 +django-auth-ldap==4.5.0 From 74ee2c073a05995d454a5c35a753d92f43a179f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie=20Krej=C4=8D=C3=AD?= Date: Mon, 11 Sep 2023 21:19:36 +0200 Subject: [PATCH 02/17] Remove old LDAP backend files --- webvirtcloud/.dec_ldap_pwd.sh | 18 ----- webvirtcloud/ldapbackend.py | 142 ---------------------------------- 2 files changed, 160 deletions(-) delete mode 100755 webvirtcloud/.dec_ldap_pwd.sh delete mode 100644 webvirtcloud/ldapbackend.py diff --git a/webvirtcloud/.dec_ldap_pwd.sh b/webvirtcloud/.dec_ldap_pwd.sh deleted file mode 100755 index 2cda920..0000000 --- a/webvirtcloud/.dec_ldap_pwd.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -##### - -# - -# LDAP PASSWORD DECRYPTION SCRIPT - -# - -# - -##### - -ENC_PASSWD=$1 - -echo $(echo $ENC_PASSWD | base64 -d | openssl enc -pbkdf2 -salt -d -pass pass:MYPASSPHRASE ) - diff --git a/webvirtcloud/ldapbackend.py b/webvirtcloud/ldapbackend.py deleted file mode 100644 index 0f7a797..0000000 --- a/webvirtcloud/ldapbackend.py +++ /dev/null @@ -1,142 +0,0 @@ -from django.contrib.auth.backends import ModelBackend -from django.contrib.auth.models import User, Group -from django.conf import settings -from accounts.models import UserAttributes, UserInstance, UserSSHKey -from django.contrib.auth.models import Permission -from logs.models import Logs -import uuid - -try: - from ldap3 import Server, Connection, ALL - #/srv/webvirtcloud/ldap/ldapbackend.py - class LdapAuthenticationBackend(ModelBackend): - - def get_LDAP_user(self, username, password, filterString): - print('get_LDAP_user {}'.format(username)) - try: - server = Server(settings.LDAP_URL, port=settings.LDAP_PORT, - use_ssl=settings.USE_SSL,get_info=ALL) - connection = Connection(server, - settings.LDAP_MASTER_DN, - settings.LDAP_MASTER_PW, auto_bind=True) - connection.search(settings.LDAP_ROOT_DN, - '(&({attr}={login})({filter}))'.format( - attr=settings.LDAP_USER_UID_PREFIX, - login=username, - filter=filterString), attributes=['*']) - - if len(connection.response) == 0: - print('get_LDAP_user-no response') - return None - specificUser = connection.response[0] - userDn = str(specificUser.get('raw_dn'),'utf-8') - userGivenName = connection.entries[0].givenName - userSn = connection.entries[0].sn - userMail = connection.entries[0].mail - with Connection(server, userDn, password) as con: - return username, userGivenName, userSn, userMail - except Exception as e: - print("LDAP Exception: {}".format(e)) - return None - return None - - def authenticate(self, request, username=None, password=None, **kwargs): - if not settings.LDAP_ENABLED: - return None - print("authenticate_ldap") - # Get the user information from the LDAP if he can be authenticated - isAdmin = False - isStaff = False - isTechnician = False - - requeteLdap = self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_ADMINS) - isAdmin = requeteLdap is not None - isStaff = requeteLdap is not None - - if requeteLdap is None: - requeteLdap = self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_STAFF) - isStaff = requeteLdap is not None - - if requeteLdap is None: - requeteLdap = self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_TECHNICIANS) - isTechnician = requeteLdap is not None - - if requeteLdap is None: - requeteLdap = self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_USERS) - - if requeteLdap is None: - print("User does not belong to any search group. Check LDAP_SEARCH_GROUP_FILTER in settings.") - return None - - techniciansGroup = Group.objects.get(name='Technicians') - - try: - user = User.objects.get(username=username) - attributes = UserAttributes.objects.get(user=user) - user.is_staff = isStaff - user.is_superuser = isAdmin - if not isTechnician and user.groups.filter(name='Technicians').exists(): - user.groups.remove(techniciansGroup) - elif isTechnician and not user.groups.filter(name='Technicians').exists(): - user.groups.add(techniciansGroup) - else: - print("The user is already in the Technicians group") - user.save() - # TODO VERIFY - except User.DoesNotExist: - print(f"authenticate-create new user: {username}") - user = User(username=username) - user.first_name = requeteLdap[1] - user.last_name = requeteLdap[2] - user.email = requeteLdap[3] - user.is_active = True - user.is_staff = isStaff - user.is_superuser = isAdmin - user.set_password(uuid.uuid4().hex) - user.save() - if isTechnician: - user.groups.add(techniciansGroup) - maxInstances = 1 - maxCpus = 1 - maxMemory = 128 - maxDiskSize = 1 - if isStaff: - maxMemory = 2048 - maxDiskSize = 20 - permission = Permission.objects.get(codename='clone_instances') - user.user_permissions.add(permission) - if isAdmin: - maxInstances = -1 - maxCpus = -1 - maxMemory = -1 - maxDiskSize = -1 - permission = Permission.objects.get(codename='clone_instances') - user.user_permissions.add(permission) - user.save() - UserAttributes.objects.create( - user=user, - max_instances=maxInstances, - max_cpus=maxCpus, - max_memory=maxMemory, - max_disk_size=maxDiskSize, - ) - user.save() - - print("authenticate-user created") - return user - - def get_user(self, user_id): - if not settings.LDAP_ENABLED: - return None - print("get_user_ldap") - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - print("get_user-user not found") - return None -except: - class LdapAuthenticationBackend(ModelBackend): - def authenticate(self, request, username=None, password=None, **kwargs): - return None - def get_user(self, user_id): - return None From 561fedfccd4ec8a04174af644ab6c29a605a9bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie=20Krej=C4=8D=C3=AD?= Date: Mon, 11 Sep 2023 21:39:05 +0200 Subject: [PATCH 03/17] Add new template config and README blocks --- README.md | 82 +++++++++++++++++++------------ webvirtcloud/settings.py.template | 48 +++++++++--------- 2 files changed, 73 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index cbbfb29..7f9069f 100644 --- a/README.md +++ b/README.md @@ -385,55 +385,73 @@ python manage.py test ## LDAP Configuration -The example settings are based on an OpenLDAP server with groups defined as "cn" of class "groupOfUniqueNames" +The config options below can be changed in `webvirtcloud/settings.py` file. Variants for Active Directory and OpenLDAP are shown. This is a minimal config to get LDAP running, for further info read the [django-auth-ldap documentation](https://django-auth-ldap.readthedocs.io). Enable LDAP ```bash -sudo sed -i "s/LDAP_ENABLED = False/LDAP_ENABLED = True/g"" /srv/webvirtcloud/webvirtcloud/settings.py +sudo sed -i "s~#\"django_auth_ldap.backend.LDAPBackend\",~\"django_auth_ldap.backend.LDAPBackend\",~g" /srv/webvirtcloud/webvirtcloud/settings.py ``` -Set the LDAP server name and root DN +Set the LDAP server name and bind DN -```bash -sudo sed -i "s/LDAP_URL = ''/LDAP_URL = 'myldap.server.com'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -sudo sed -i "s/LDAP_ROOT_DN = ''/LDAP_ROOT_DN = 'dc=server,dc=com'/g"" /srv/webvirtcloud/webvirtcloud/settings.py +```python +# Active Directory +AUTH_LDAP_SERVER_URI = "ldap://example.com" +AUTH_LDAP_BIND_DN = "username@example.com" +AUTH_LDAP_BIND_PASSWORD = "password" + +# OpenLDAP +AUTH_LDAP_SERVER_URI = "ldap://example.com" +AUTH_LDAP_BIND_DN = "CN=username,CN=Users,OU=example,OU=com" +AUTH_LDAP_BIND_PASSWORD = "password" ``` -Set the passphrase to decrypt the password -```bash -sudo sed -i "s/pass:MYPASSPHRASE/pass:MYTRUEPASSPHRASE/g" /srv/webvirtcloud/webvirtcloud/.dec_ldap_pwd.sh +Set the user filter and user and group search base and filter + +```python +# Active Directory +AUTH_LDAP_USER_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)" +) +AUTH_LDAP_GROUP_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(objectClass=group)" +) +AUTH_LDAP_GROUP_TYPE = NestedActiveDirectoryGroupType() + +# OpenLDAP +AUTH_LDAP_USER_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(cn=%(user)s)" +) +AUTH_LDAP_GROUP_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(objectClass=groupOfUniqueNames)" +) +AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType() # import needs to be changed at the top of settings.py ``` -Encrypt the password -```bash -echo MYPASSWORD | openssl enc -pbkdf2 -salt -pass pass:MYTRUEPASSPHRASE | base64 +Set group which is required to access WebVirtCloud. You may set this to `False` to disable this filter. + +```python +AUTH_LDAP_REQUIRE_GROUP = "CN=WebVirtCloud Access,CN=Users,DC=example,DC=com" ``` -Set the user that has browse access to LDAP and its password encrypted +Populate user fields with values from LDAP -```bash -sudo sed -i "s/LDAP_MASTER_DN = ''/LDAP_MASTER_DN = 'cn=admin,ou=users,dc=kendar,dc=org'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -sudo sed -i "s/LDAP_MASTER_PW_ENC = ''/LDAP_MASTER_PW_ENC = 'MYPASSWORDENCRYPTED'/g"" /srv/webvirtcloud/webvirtcloud/settings.py +```python +AUTH_LDAP_USER_FLAGS_BY_GROUP = { + "is_staff": "CN=WebVirtCloud Staff,CN=Users,DC=example,DC=com", + "is_superuser": "CN=WebVirtCloud Admins,CN=Users,DC=example,DC=com", +} +AUTH_LDAP_USER_ATTR_MAP = { + "first_name": "givenName", + "last_name": "sn", + "email": "mail", +} ``` -Set the attribute that will be used to find the username, i usually use the cn +Now when you login with an LDAP user it will be assigned the rights defined. The user will be authenticated then with LDAP and authorized through the WebVirtCloud permissions. -```bash -sudo sed -i "s/LDAP_USER_UID_PREFIX = ''/LDAP_USER_UID_PREFIX = 'cn'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -``` - -You can now create the filters to retrieve the users for the various group. This will be used during the user creation only - -```bash -sudo sed -i "s/LDAP_SEARCH_GROUP_FILTER_ADMINS = ''/LDAP_SEARCH_GROUP_FILTER_ADMINS = 'memberOf=cn=admins,dc=kendar,dc=org'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -sudo sed -i "s/LDAP_SEARCH_GROUP_FILTER_STAFF = ''/LDAP_SEARCH_GROUP_FILTER_STAFF = 'memberOf=cn=staff,dc=kendar,dc=org'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -sudo sed -i "s/LDAP_SEARCH_GROUP_FILTER_USERS = ''/LDAP_SEARCH_GROUP_FILTER_USERS = 'memberOf=cn=users,dc=kendar,dc=org'/g"" /srv/webvirtcloud/webvirtcloud/settings.py -``` - -Now when you login with an LDAP user it will be assigned the rights defined. The user will be authenticated then with ldap and authorized through the WebVirtCloud permissions. - -If you'd like to move a user from ldap to WebVirtCloud, just change its password from the UI and (eventually) remove from the group in ldap +If you'd like to move a user from ldap to WebVirtCloud, just change its password from the UI and (eventually) remove from the group in LDAP. ## REST API / BETA diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 50dce23..fabe94c 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -3,7 +3,9 @@ Django settings for webvirtcloud project. """ +import ldap import subprocess +from django_auth_ldap.config import LDAPSearch, NestedActiveDirectoryGroupType from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -101,7 +103,7 @@ DATABASES = { AUTHENTICATION_BACKENDS = [ "django.contrib.auth.backends.ModelBackend", - "webvirtcloud.ldapbackend.LdapAuthenticationBackend", + #"django_auth_ldap.backend.LDAPBackend", ] LOGIN_URL = "/accounts/login/" @@ -280,27 +282,23 @@ EMAIL_HOST_PASSWORD = '' # LDAP Config # -LDAP_ENABLED = False -LDAP_URL = '' -LDAP_PORT = 389 -USE_SSL = False -## The user with search rights on ldap. (e.g cn=admin,dc=kendar,dc=org) -LDAP_MASTER_DN = '' -LDAP_MASTER_PW_ENC = '' -LDAP_MASTER_PW = subprocess.Popen(["bash", str(BASE_DIR) + "/webvirtcloud/.dec_ldap_pwd.sh", LDAP_MASTER_PW_ENC],stdout=subprocess.PIPE, encoding='utf8').stdout.read().strip('\n') -## The root dn (e.g. dc=kendar,dc=org) -LDAP_ROOT_DN = '' -## Queries to identify the users, i use groupOfUniqueNames on openldap - -### PLEASE BE SURE memberOf overlay is activated on slapd -## e.g. memberOf=cn=admins,cn=staff,cn=technicians,cn=webvirtcloud,ou=groups,dc=kendar,dc=org -LDAP_SEARCH_GROUP_FILTER_ADMINS = '' -## e.g. memberOf=cn=staff,cn=technicians,cn=webvirtcloud,ou=groups,dc=kendar,dc=org -LDAP_SEARCH_GROUP_FILTER_STAFF = '' -## e.g. memberOf=cn=technicians,cn=webvirtcloud,ou=groups,dc=kendar,dc=org -LDAP_SEARCH_GROUP_FILTER_TECHNICIANS = '' -## e.g. memberOf=cn=webvirtcloud,ou=groups,dc=kendar,dc=org -LDAP_SEARCH_GROUP_FILTER_USERS = '' - -## The user name prefix to identify the user name (e.g. cn) -LDAP_USER_UID_PREFIX = '' +AUTH_LDAP_SERVER_URI = "ldap://example.com" +AUTH_LDAP_BIND_DN = "username@example.com" +AUTH_LDAP_BIND_PASSWORD = "password" +AUTH_LDAP_USER_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)" +) +AUTH_LDAP_GROUP_SEARCH = LDAPSearch( + "CN=Users,DC=example,DC=com", ldap.SCOPE_SUBTREE, "(objectClass=group)" +) +AUTH_LDAP_GROUP_TYPE = NestedActiveDirectoryGroupType() +AUTH_LDAP_REQUIRE_GROUP = "CN=WebVirtCloud Access,CN=Users,DC=example,DC=com" +AUTH_LDAP_USER_FLAGS_BY_GROUP = { + "is_staff": "CN=WebVirtCloud Staff,CN=Users,DC=example,DC=com", + "is_superuser": "CN=WebVirtCloud Admins,CN=Users,DC=example,DC=com", +} +AUTH_LDAP_USER_ATTR_MAP = { + "first_name": "givenName", + "last_name": "sn", + "email": "mail", +} From 1b2b3a3bceb315a746bc2758c728b66d6c6e724d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie=20Krej=C4=8D=C3=AD?= Date: Sat, 23 Sep 2023 09:52:48 +0200 Subject: [PATCH 04/17] Get UserAttributes object using get_or_create This is done to automatically create the UserAttributes object in case LDAP User Backend didn't create it. --- admin/views.py | 2 +- instances/utils.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/views.py b/admin/views.py index fd4ead4..8b71baf 100644 --- a/admin/views.py +++ b/admin/views.py @@ -117,7 +117,7 @@ def user_create(request): @superuser_only def user_update(request, pk): user = get_object_or_404(User, pk=pk) - attributes = UserAttributes.objects.get(user=user) + attributes, attributes_created = UserAttributes.objects.get_or_create(user=user) user_form = forms.UserForm(request.POST or None, instance=user) attributes_form = forms.UserAttributesForm( request.POST or None, instance=attributes diff --git a/instances/utils.py b/instances/utils.py index 53752b6..f9f5dcf 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -2,7 +2,7 @@ import os import random import string -from accounts.models import UserInstance +from accounts.models import UserInstance, UserAttributes from appsettings.settings import app_settings from django.conf import settings from django.utils.translation import gettext_lazy as _ @@ -26,7 +26,7 @@ def get_clone_free_names(size=10): def check_user_quota(user, instance, cpu, memory, disk_size): - ua = user.userattributes + ua, attributes_created = UserAttributes.objects.get_or_create(user=user) msg = "" if user.is_superuser: From 53d140748330011ef344215caf34d3e7d1d262a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Am=C3=A9lie=20Krej=C4=8D=C3=AD?= Date: Mon, 25 Sep 2023 14:40:22 +0200 Subject: [PATCH 05/17] Replace ifnotequal with if ifequal and ifnotequal are deprecated in Django 4.0 --- storages/templates/storage.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storages/templates/storage.html b/storages/templates/storage.html index 8da0c31..4b6235b 100644 --- a/storages/templates/storage.html +++ b/storages/templates/storage.html @@ -160,7 +160,7 @@ - {% ifnotequal volume.type "iso" %} + {% if volume.type != "iso" %} @@ -168,7 +168,7 @@ - {% endifnotequal %} + {% endif %}
{% csrf_token %} From 3ef0fe19f874fff21fb0e04612bf358b1a151a9c Mon Sep 17 00:00:00 2001 From: Aldo Adirajasa Fathoni Date: Tue, 26 Sep 2023 13:21:02 +0700 Subject: [PATCH 06/17] Fix calling write() from int instead of os --- console/socketiod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console/socketiod b/console/socketiod index a53a6f1..3c3c9b6 100755 --- a/console/socketiod +++ b/console/socketiod @@ -176,7 +176,7 @@ def connect(sid, environ): if child_pid: # already started child process, don't start another # write a new line so that when a client refresh the shell prompt is printed - fd.write("\n") + os.write(fd, str.encode("\n")) return # create child process attached to a pty we can read from and write to From 84e22e4a8cdec677f157d1142560b40b0af31990 Mon Sep 17 00:00:00 2001 From: Aldo Adirajasa Fathoni Date: Tue, 26 Sep 2023 13:23:20 +0700 Subject: [PATCH 07/17] Ignore if pty process has exited --- console/socketiod | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/console/socketiod b/console/socketiod index 3c3c9b6..55342d1 100755 --- a/console/socketiod +++ b/console/socketiod @@ -200,8 +200,13 @@ def disconnect(sid): global child_pid # kill pty process - os.kill(child_pid, signal.SIGKILL) - os.wait() + try: + os.kill(child_pid, signal.SIGKILL) + os.wait() + except ProcessLookupError: + pass + except ChildProcessError: + pass # reset the variables fd = None From 64fdb9315d8ffbc608fbbb8492d20418b6f42b7b Mon Sep 17 00:00:00 2001 From: Aldo Adirajasa Fathoni Date: Tue, 26 Sep 2023 21:56:27 +0700 Subject: [PATCH 08/17] Fix socketio default host The previous value caused webvirtcloud to try to connect to socketiod with 0.0.0.0. --- webvirtcloud/settings.py.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index fabe94c..88146c1 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -201,7 +201,7 @@ WS_PUBLIC_PATH = "/novncd/" WS_CERT = None SOCKETIO_PORT = 6081 -SOCKETIO_HOST = '0.0.0.0' +SOCKETIO_HOST = "0.0.0.0" # Socketio public host SOCKETIO_PUBLIC_HOST = None From 5a211c0c566f1b9ec64a0cf356672eb776058cf3 Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Wed, 18 Oct 2023 17:34:40 -0400 Subject: [PATCH 09/17] Get MAC OUI from settings.py --- instances/utils.py | 2 +- vrtManager/util.py | 12 ++++++++---- webvirtcloud/settings.py.template | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/instances/utils.py b/instances/utils.py index f9f5dcf..19b2111 100644 --- a/instances/utils.py +++ b/instances/utils.py @@ -196,7 +196,7 @@ def get_dhcp_mac_address(vname): def get_random_mac_address(): - mac = "52:54:00:%02x:%02x:%02x" % ( + mac = settings.MAC_OUI + ":%02x:%02x:%02x" % ( random.randint(0x00, 0xFF), random.randint(0x00, 0xFF), random.randint(0x00, 0xFF), diff --git a/vrtManager/util.py b/vrtManager/util.py index ab47f32..81cb3d5 100644 --- a/vrtManager/util.py +++ b/vrtManager/util.py @@ -6,6 +6,8 @@ import string import libvirt import lxml.etree as etree +from django.conf import UserSettingsHolder, settings + def is_kvm_available(xml): kvm_domains = get_xml_path(xml, "//domain/@type='kvm'") @@ -15,10 +17,12 @@ def is_kvm_available(xml): def randomMAC(): """Generate a random MAC address.""" # qemu MAC - oui = [0x52, 0x54, 0x00] - - mac = oui + [random.randint(0x00, 0xFF), random.randint(0x00, 0xFF), random.randint(0x00, 0xFF)] - return ":".join(map(lambda x: "%02x" % x, mac)) + mac = settings.MAC_OUI + ":%02x:%02x:%02x" % ( + random.randint(0x00, 0xFF), + random.randint(0x00, 0xFF), + random.randint(0x00, 0xFF), + ) + return mac def randomUUID(): diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 88146c1..d3b9fd9 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -15,6 +15,8 @@ SECRET_KEY = "" DEBUG = False +MAC_OUI = '52:54:10' + ALLOWED_HOSTS = ["*"] CSRF_TRUSTED_ORIGINS = ['http://localhost',] From 149044a90ccebaf7c05d33244f21f4a80872eb6e Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:04:00 -0400 Subject: [PATCH 10/17] Fix templates - extends base.html --- accounts/templates/logout.html | 4 ++-- templates/403.html | 2 +- templates/404.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/templates/logout.html b/accounts/templates/logout.html index eb3a325..eb3b917 100644 --- a/accounts/templates/logout.html +++ b/accounts/templates/logout.html @@ -1,4 +1,4 @@ -{% extends "base_auth.html" %} +{% extends "base.html" %} {% load i18n %} {% block title %} {% trans "WebVirtCloud" %} - {% trans "Sign Out"%} @@ -14,4 +14,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/403.html b/templates/403.html index 4b320b4..6b0a7e8 100644 --- a/templates/403.html +++ b/templates/403.html @@ -1,4 +1,4 @@ -{% extends "base_auth.html" %} +{% extends "base.html" %} {% load i18n %} {% block title %}{% trans "403" %}{% endblock %} {% block content %} diff --git a/templates/404.html b/templates/404.html index c631d46..dd42e10 100644 --- a/templates/404.html +++ b/templates/404.html @@ -1,4 +1,4 @@ -{% extends "base_auth.html" %} +{% extends "base.html" %} {% load i18n %} {% block title %}{% trans "404" %}{% endblock %} {% block content %} From 31cace9994bd26b72ff03f8e96aef1f454c6b57b Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:42:57 -0400 Subject: [PATCH 11/17] nginx conf - Fix for issue #577 --- conf/nginx/webvirtcloud.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index 3ba36ec..144431b 100644 --- a/conf/nginx/webvirtcloud.conf +++ b/conf/nginx/webvirtcloud.conf @@ -34,6 +34,12 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } + location /websockify { + proxy_pass http://wssocketiod; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } } upstream wsnovncd { From 4aafad668ba33465dd68be0b421e7bb67f877ee0 Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Thu, 26 Oct 2023 13:12:20 -0400 Subject: [PATCH 12/17] Location /websockify proxy passes to wsnovncd --- conf/nginx/webvirtcloud.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index 144431b..153b389 100644 --- a/conf/nginx/webvirtcloud.conf +++ b/conf/nginx/webvirtcloud.conf @@ -35,7 +35,7 @@ server { proxy_set_header Connection "upgrade"; } location /websockify { - proxy_pass http://wssocketiod; + proxy_pass http://wsnovncd; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; From 2072890fc586325a123569df705b31eca74f7060 Mon Sep 17 00:00:00 2001 From: Mark <0x6d61726b@gmail.com> Date: Thu, 26 Oct 2023 21:53:04 +0200 Subject: [PATCH 13/17] Fixed nginx X-Forwarded-Proto to match the protocol ("http", "https") --- conf/nginx/webvirtcloud.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index 3ba36ec..f18585b 100644 --- a/conf/nginx/webvirtcloud.conf +++ b/conf/nginx/webvirtcloud.conf @@ -14,7 +14,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for; proxy_set_header Host $host:$server_port; - proxy_set_header X-Forwarded-Proto $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Ssl off; proxy_connect_timeout 1800; proxy_read_timeout 1800; From 5c6bcbe610fae62b208272c0416ede5dc8905768 Mon Sep 17 00:00:00 2001 From: Mark <0x6d61726b@gmail.com> Date: Thu, 26 Oct 2023 22:18:17 +0200 Subject: [PATCH 14/17] Fixes issue #614: Quick Install overrides nginx upstream wssocketiod port --- webvirtcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webvirtcloud.sh b/webvirtcloud.sh index 3df52bd..f66cb0f 100755 --- a/webvirtcloud.sh +++ b/webvirtcloud.sh @@ -174,7 +174,7 @@ configure_nginx () { fi novncd_port_escape="$(echo -n "$novncd_port"|sed -e 's/[](){}<>=:\!\?\+\|\/\&$*.^[]/\\&/g')" - sed -i "s|\\(server 127.0.0.1:\\).*|\\1$novncd_port_escape;|" "$nginxfile" + sed -i "s|server 127.0.0.1:6080;|server 127.0.0.1:$novncd_port_escape;|" "$nginxfile" } From cc867304414b5be9340aa76d7296576a4df4f1b1 Mon Sep 17 00:00:00 2001 From: Mark <0x6d61726b@gmail.com> Date: Thu, 26 Oct 2023 22:43:27 +0200 Subject: [PATCH 15/17] Corrected X-Forwarded-Proto meaning for Gunicorn --- conf/nginx/webvirtcloud.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index f18585b..16128f3 100644 --- a/conf/nginx/webvirtcloud.conf +++ b/conf/nginx/webvirtcloud.conf @@ -14,7 +14,7 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-for $proxy_add_x_forwarded_for; proxy_set_header Host $host:$server_port; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto http; proxy_set_header X-Forwarded-Ssl off; proxy_connect_timeout 1800; proxy_read_timeout 1800; From 7e8c05fff93646651f3345128623bea7ef9506b3 Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:08:38 -0400 Subject: [PATCH 16/17] Global setting for NIC type --- .../migrations/0009_alter_appsettings_id.py | 18 ++++++++++++ .../migrations/0010_auto_20231030_1305.py | 28 +++++++++++++++++++ instances/templates/create_instance_w2.html | 6 ++-- instances/views.py | 1 + 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 appsettings/migrations/0009_alter_appsettings_id.py create mode 100644 appsettings/migrations/0010_auto_20231030_1305.py diff --git a/appsettings/migrations/0009_alter_appsettings_id.py b/appsettings/migrations/0009_alter_appsettings_id.py new file mode 100644 index 0000000..5e588dc --- /dev/null +++ b/appsettings/migrations/0009_alter_appsettings_id.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.5 on 2023-10-30 17:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('appsettings', '0008_auto_20220905_1459'), + ] + + operations = [ + migrations.AlterField( + model_name='appsettings', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/appsettings/migrations/0010_auto_20231030_1305.py b/appsettings/migrations/0010_auto_20231030_1305.py new file mode 100644 index 0000000..606909d --- /dev/null +++ b/appsettings/migrations/0010_auto_20231030_1305.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.5 on 2023-10-30 17:05 + +from django.db import migrations +from django.utils.translation import gettext_lazy as _ + +def add_default_settings(apps, schema_editor): + setting = apps.get_model("appsettings", "AppSettings") + db_alias = schema_editor.connection.alias + setting.objects.using(db_alias).bulk_create([ + setting(35, _("VM NIC Type"), "INSTANCE_NIC_DEFAULT_TYPE", "default", "default,e1000,e1000e,rt18139,virtio", _("Change instance default NIC type")) + ]) + + +def del_default_settings(apps, schema_editor): + setting = apps.get_model("appsettings", "AppSettings") + db_alias = schema_editor.connection.alias + setting.objects.using(db_alias).filter(key="INSTANCE_NIC_DEFAULT_TYPE").delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('appsettings', '0009_alter_appsettings_id') + ] + + operations = [ + migrations.RunPython(add_default_settings,del_default_settings) + ] diff --git a/instances/templates/create_instance_w2.html b/instances/templates/create_instance_w2.html index 91ae2ec..1cf7d62 100644 --- a/instances/templates/create_instance_w2.html +++ b/instances/templates/create_instance_w2.html @@ -200,7 +200,7 @@
@@ -476,7 +476,7 @@
@@ -728,7 +728,7 @@
diff --git a/instances/views.py b/instances/views.py index 57d1598..cfaa157 100755 --- a/instances/views.py +++ b/instances/views.py @@ -1692,6 +1692,7 @@ def create_instance(request, compute_id, arch, machine): networks = sorted(conn.get_networks()) nwfilters = conn.get_nwfilters() net_models_host = conn.get_network_models() + default_nic_type = app_settings.INSTANCE_NIC_DEFAULT_TYPE storages = sorted(conn.get_storages(only_actives=True)) default_graphics = app_settings.QEMU_CONSOLE_DEFAULT_TYPE default_cdrom = app_settings.INSTANCE_CDROM_ADD From 2f24f77368af48f3353aa14d030bd7cfadc33e6f Mon Sep 17 00:00:00 2001 From: MisterBlueBear <51129551+MisterBlueBear@users.noreply.github.com> Date: Wed, 1 Nov 2023 20:35:15 -0400 Subject: [PATCH 17/17] Install script accepts default hostname --- webvirtcloud.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/webvirtcloud.sh b/webvirtcloud.sh index f66cb0f..b846b11 100755 --- a/webvirtcloud.sh +++ b/webvirtcloud.sh @@ -424,9 +424,15 @@ until [[ $setupfqdn == "yes" ]] || [[ $setupfqdn == "no" ]]; do case $setupfqdn in [yY] | [yY][Ee][Ss] ) - echo -n " Q. What is the FQDN of your server? ($(hostname --fqdn)): " - read -r fqdn + fqdn=$(hostname --fqdn) + echo -n " Q. What is the FQDN of your server? ($fqdn): " + read -r fqdn_from_user setupfqdn="yes" + + if [ ! -z $fqdn_from_user ]; then + fqdn=$fqdn_from_user + fi + echo " Setting to $fqdn" echo "" ;;