LDAP
Prerequisites
In order to use a LDAP backend with RDMO you need to install some prerequistes. On Debian/Ubuntu you can install them using:
sudo apt-get install libsasl2-dev libldap2-dev libssl-dev
On the python side, we use django-auth-ldap to connect to the LDAP server. As before, it should be installed inside the virtual environment created for RDMO using:
pip install rdmo[ldap]
LDAP installations can be very different and we only discuss one particular example. We assume that the LDAP service is running on ldap.example.com
. RDMO needs an account to connect to the LDAP. In order to create it, run:
ldapmodify -x -D "cn=admin,dc=ldap,dc=example,dc=com" -W
on the machine running the LDAP service and type in:
dn: uid=rdmo,dc=ldap,dc=example,dc=com
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: rdmo
userPassword: RDMO_LDAP_ACCOUNT_PASSWORD
and end with a blank line followed by ctrl-d
.
Configuration
In order to use LDAP as one of your authentication backends in RDMO, edit config/settings/local.py
and add or uncomment:
import ldap
from django_auth_ldap.config import LDAPSearch
PROFILE_UPDATE = False
PROFILE_DELETE = False
AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com"
AUTH_LDAP_BIND_DN = "uid=rdmo,dc=ldap,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD = "RDMO_LDAP_ACCOUNT_PASSWORD"
AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=ldap,dc=example,dc=com", ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
'email': 'mail'
}
AUTHENTICATION_BACKENDS.insert(
AUTHENTICATION_BACKENDS.index('django.contrib.auth.backends.ModelBackend'),
'django_auth_ldap.backend.LDAPBackend'
)
The connection can be tested using:
ldapsearch -v -x -H 'ldap://ldap.example.com' -D "uid=rdmo,dc=ldap,dc=example,dc=com" -w RDMO_LDAP_ACCOUNT_PASSWORD -b "dc=ldap,dc=example,dc=com" -s sub 'uid=user'
The setting PROFILE_UPDATE = False
and PROFILE_DELETE = False
tell RDMO to disable the update and deletion form for the user profile so that users can neither update their credentials nor delete their profile anymore.
The other settings are needed by django-auth-ldap
and are described in the django-auth-ldap documentation.
For an LDAP connection to an Active Directory, the configuration differs slightly:
import ldap
from django_auth_ldap.config import LDAPSearch
PROFILE_UPDATE = False
PROFILE_DELETE = False
AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com"
AUTH_LDAP_BIND_DN = "cn=RDMO_LDAP_ACCOUNT_CN,dc=ldap,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD = "RDMO_LDAP_ACCOUNT_PASSWORD"
AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=ldap,dc=example,dc=com", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)")
AUTH_LDAP_CONNECTION_OPTIONS = {ldap.OPT_REFERRALS: 0}
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
'email': 'mail'
}
AUTHENTICATION_BACKENDS.insert(
AUTHENTICATION_BACKENDS.index('django.contrib.auth.backends.ModelBackend'),
'django_auth_ldap.backend.LDAPBackend'
)
Again, your particular setup might differ.
Groups
You can also map LDAP groups to Django groups, in particular to restrict the access to Catalogs and Views. This can be done by adding the following settings:
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
"dc=ldap,dc=test,dc=rdmo,dc=org", ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)"
)
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr="cn")
AUTH_LDAP_MIRROR_GROUPS = ['special']
where cn
is the name of the particular group in the LDAP and AUTH_LDAP_MIRROR_GROUPS
denotes the groups which are actually mirrored from the LDAP.
Signals
django-auth-ldap offers a Django signal to perform follow up actions after the creation of the user model (but before saving it). See: https://django-auth-ldap.readthedocs.io/en/latest/reference.html#django_auth_ldap.backend.populate_user.
We can use this to put every LDAP user in the ldap
group (but not users from other authentication methods). Just put the following code in the models.py
(which is read by the server automatcally) of the local theme app in your rdmo-app
:
from django.contrib.auth.models import Group, User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django_auth_ldap.backend import populate_user
@receiver(populate_user)
def handle_populate_ldap_user(sender, user, ldap_user, **kwargs):
user.is_ldap = True
@receiver(post_save, sender=User)
def handle_post_save_ldap_user(sender, instance, **kwargs):
if getattr(instance, 'is_ldap', None):
group, created = Group.objects.get_or_create(name='ldap')
instance.groups.add(group)