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/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/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/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/conf/nginx/webvirtcloud.conf b/conf/nginx/webvirtcloud.conf index 3ba36ec..ae2edf8 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 http; proxy_set_header X-Forwarded-Ssl off; proxy_connect_timeout 1800; proxy_read_timeout 1800; @@ -34,6 +34,12 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } + location /websockify { + proxy_pass http://wsnovncd; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } } upstream wsnovncd { diff --git a/conf/requirements.txt b/conf/requirements.txt index e8866e4..d0569f0 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -4,6 +4,7 @@ django-bootstrap-icons==0.8.6 django-login-required-middleware==0.9.0 django-otp==1.3.0 django-qr-code==3.1.1 +django-auth-ldap==4.5.0 gunicorn==21.2.0 libsass==0.22.0 libvirt-python==9.8.0 diff --git a/console/socketiod b/console/socketiod index a53a6f1..55342d1 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 @@ -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 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/utils.py b/instances/utils.py index 53752b6..19b2111 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: @@ -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/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 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 %} 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.sh b/webvirtcloud.sh index 3df52bd..b846b11 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" } @@ -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 "" ;; 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 diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 3525e48..560ea0f 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'. @@ -13,6 +15,8 @@ SECRET_KEY = "" DEBUG = False +MAC_OUI = '52:54:10' + ALLOWED_HOSTS = ["*"] CSRF_TRUSTED_ORIGINS = ['http://localhost',] @@ -102,7 +106,7 @@ DATABASES = { AUTHENTICATION_BACKENDS = [ "django.contrib.auth.backends.ModelBackend", - "webvirtcloud.ldapbackend.LdapAuthenticationBackend", + #"django_auth_ldap.backend.LDAPBackend", ] LOGIN_URL = "/accounts/login/" @@ -196,7 +200,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 @@ -277,27 +281,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", +}