mirror of
https://github.com/retspen/webvirtcloud
synced 2024-12-25 23:55:24 +00:00
LDAP Integration ( https://github.com/retspen/webvirtcloud/issues/243 ) (#443)
* Added ldap support * Update * Added logging * Update * Working * Working * Working * Working * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Check for ldap3 existence * Add eol Co-authored-by: Kendar <unknown@kendar.org>
This commit is contained in:
parent
a20fa8e8d7
commit
e9b57bfcf7
5 changed files with 183 additions and 2 deletions
|
@ -21,6 +21,9 @@ RUN apt-get update -qqy \
|
||||||
nginx \
|
nginx \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
gcc \
|
gcc \
|
||||||
|
libldap2-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libsasl2-dev \
|
||||||
libsasl2-modules \
|
libsasl2-modules \
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
|
|
46
README.md
46
README.md
|
@ -57,7 +57,7 @@ print(''.join([random.SystemRandom().choice(haystack) for _ in range(50)]))
|
||||||
### Install WebVirtCloud panel (Ubuntu 18.04+ LTS)
|
### Install WebVirtCloud panel (Ubuntu 18.04+ LTS)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get -y install git virtualenv python3-virtualenv python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs
|
sudo apt-get -y install git virtualenv python3-virtualenv python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs libsasl2-dev libldap2-dev libssl-dev
|
||||||
git clone https://github.com/retspen/webvirtcloud
|
git clone https://github.com/retspen/webvirtcloud
|
||||||
cd webvirtcloud
|
cd webvirtcloud
|
||||||
cp webvirtcloud/settings.py.template webvirtcloud/settings.py
|
cp webvirtcloud/settings.py.template webvirtcloud/settings.py
|
||||||
|
@ -97,7 +97,7 @@ Go to http://serverip and you should see the login screen.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo yum -y install epel-release
|
sudo yum -y install epel-release
|
||||||
sudo yum -y install python3-virtualenv python3-devel libvirt-devel glibc gcc nginx supervisor python3-lxml git python3-libguestfs iproute-tc cyrus-sasl-md5 python3-libguestfs
|
sudo yum -y install python3-virtualenv python3-devel libvirt-devel glibc gcc nginx supervisor python3-lxml git python3-libguestfs iproute-tc cyrus-sasl-md5 python3-libguestfs libsasl2-dev libldap2-dev libssl-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Creating directories and cloning repo
|
#### Creating directories and cloning repo
|
||||||
|
@ -380,6 +380,48 @@ Run tests
|
||||||
python manage.py test
|
python manage.py test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## LDAP Configuration
|
||||||
|
|
||||||
|
The example settings are based on an OpenLDAP server with groups defined as "cn" of class "groupOfUniqueNames"
|
||||||
|
|
||||||
|
Enable LDAP
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo sed -i "s/LDAP_ENABLED = False/LDAP_ENABLED = True/g"" /srv/webvirtcloud/webvirtcloud/settings.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the LDAP server name and root 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
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the user that has browse access to LDAP and its password
|
||||||
|
|
||||||
|
```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 = ''/LDAP_MASTER_PW = 'password'/g"" /srv/webvirtcloud/webvirtcloud/settings.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the attribute that will be used to find the username, i usually use the cn
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
Instance Detail:
|
Instance Detail:
|
||||||
|
|
|
@ -12,3 +12,4 @@ qrcode==6.1
|
||||||
rwlock==0.0.7
|
rwlock==0.0.7
|
||||||
websockify==0.9.0
|
websockify==0.9.0
|
||||||
zipp==3.4.0
|
zipp==3.4.0
|
||||||
|
ldap3==2.9.0
|
||||||
|
|
113
webvirtcloud/ldapbackend.py
Normal file
113
webvirtcloud/ldapbackend.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
from django.contrib.auth.backends import ModelBackend
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
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')
|
||||||
|
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')
|
||||||
|
with Connection(server,
|
||||||
|
userDn,
|
||||||
|
password) as con:
|
||||||
|
return username
|
||||||
|
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
|
||||||
|
|
||||||
|
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_ADMINS) is None:
|
||||||
|
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_STAFF) is None:
|
||||||
|
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_USERS) is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
isStaff = True
|
||||||
|
else:
|
||||||
|
isAdmin = True
|
||||||
|
isStaff = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = User.objects.get(username=username)
|
||||||
|
attributes = UserAttributes.objects.get(user=user)
|
||||||
|
# TODO VERIFY
|
||||||
|
except User.DoesNotExist:
|
||||||
|
print("authenticate-create new user")
|
||||||
|
user = User(username=username)
|
||||||
|
user.is_active = True
|
||||||
|
user.is_staff = isStaff
|
||||||
|
user.is_superuser = isAdmin
|
||||||
|
user.set_password(uuid.uuid4().hex)
|
||||||
|
user.save()
|
||||||
|
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
|
|
@ -95,6 +95,7 @@ DATABASES = {
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = [
|
AUTHENTICATION_BACKENDS = [
|
||||||
"django.contrib.auth.backends.ModelBackend",
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"webvirtcloud.ldapbackend.LdapAuthenticationBackend",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGIN_URL = "/accounts/login/"
|
LOGIN_URL = "/accounts/login/"
|
||||||
|
@ -212,3 +213,24 @@ SHOW_PROFILE_EDIT_PASSWORD = True
|
||||||
OTP_ENABLED = False
|
OTP_ENABLED = False
|
||||||
|
|
||||||
LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ["accounts:email_otp"]
|
LOGIN_REQUIRED_IGNORE_VIEW_NAMES = ["accounts:email_otp"]
|
||||||
|
|
||||||
|
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 = ''
|
||||||
|
## The root dn (e.g. dc=kendar,dc=org)
|
||||||
|
LDAP_ROOT_DN = ''
|
||||||
|
## Queries to identify the users, i use groupOfUniqueNames on openldap
|
||||||
|
|
||||||
|
## e.g. memberOf=cn=admins,cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org
|
||||||
|
LDAP_SEARCH_GROUP_FILTER_ADMINS = ''
|
||||||
|
## e.g. memberOf=cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org
|
||||||
|
LDAP_SEARCH_GROUP_FILTER_STAFF = ''
|
||||||
|
## 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 = ''
|
||||||
|
|
Loading…
Reference in a new issue