Importing LDAP users into django database
Asked Answered
R

3

9

I want to import the users of a ActiveDirectory database into Django. To this end I'm trying to use the django_auth_ldap module.

Here is what I tried already :

in my settings.py :

AUTH_LDAP_SERVER_URI = "ldap://example.fr"

AUTH_LDAP_BIND_DN = 'cn=a_user,dc=example,dc=fr'
AUTH_LDAP_BIND_PASSWORD=''
AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=users,dc=example,dc=fr', ldap.SCOPE_SUBTREE, '(uid=%(user)s)')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch('ou=groups,dc=example,dc=fr', ldap.SCOPE_SUBTREE, '(objectClass=groupOfNames)')

AUTH_LDAP_GROUP_TYPE = ActiveDirectoryGroupType()

#Populate the Django user from the LDAP directory
AUTH_LDAP_USER_ATTR_MAP = {
    'first_name': 'sAMAccountName',
    'last_name': 'displayName',
    'email': 'mail'
}


AUTHENTICATION_BACKENDS = (
    'django_auth_ldap.backend.LDAPBackend',
    'django.contrib.auth.backends.ModelBackend',
)

Then I call python manage.py syncdb with no result. No warning, no error, nothing updataed in the auth_user table. Is there something obvious I forgot to do ?

Revolt answered 28/7, 2011 at 14:47 Comment(0)
F
7

Looking at the documentation for django_auth_ldap it appears that the module doesn't actually walk through LDAP users and load them into the database. Instead, it authenticates a user against LDAP, and then adds or updates them in auth_users with the information it gets from LDAP when the user logs in.

If you want to pre-populate the database with all of the users in Active Directory then it looks like you'll need to write a script that queries AD directly and insert the users.

Something like this should get you started:

import ldap

l = ldap.initialize('ldap://your_ldap_server') # or ldaps://
l.simple_bind_s("cn=a_user,dc=example,dc=fr")
users = l.search_ext_s("memberOf=YourUserGroup",\
                         ldap.SCOPE_SUBTREE, \
                         "(sAMAccountName=a_user)", \
                         attrlist=["sAMAccountName", "displayName","mail"])

# users is now an array of members who match your search criteria.
# *Each* user will look something like this:
# [["Firstname"],["LastName"],["[email protected]"]]
# Note that each field is in an array, even if there is only one value.
# If you only want the first value from each, you can transform the results:
# users = [[field[0] for field in user] for user in users]

# That will transform each row into something like this:
# ["Firstname", "Lastname", "[email protected]"]

# TODO -- add to the database.

I have left the database update to you, since I don't have any information about your setup.

If you need more information about LDAP queries, check out the LDAP questions here on Stackoverflow -- and I also found this article to be a help.

Fricke answered 28/7, 2011 at 14:57 Comment(6)
Thanks for your answer. DO you have an example of such a script ? I can't find anything approaching, and I'm completely new to LDAP. I just need to use it for this project, but I'm not the one handling it. I don't know where to start as I'm also a newbie in Django ...Revolt
@Revolt - I don't have a complete one, but I can get you started ... :-)Fricke
I tried this piece of code in django shell. It gives me something after the command simple_bind, but after the line "users = .." It says : TypeError: an integer is required What's wrong ?Revolt
@Revolt - apologies, I'd left off the scope of the search (which is an integer ... see python-ldap.org/doc/html/ldap.html#ldap.LDAPObject.search). I've updated my code example.Fricke
Ok, now it tells me that a successful bind is needed. But it didn't throw me any error when I did the bind, it returned (97, []) (for whatever user I'm testing)Revolt
@Revolt - Looks like you are over your limit ... try following the answer of this question #482495 (found it by Googling "ldap error 97").Fricke
S
2

I'd say that you really don't want to use the django_auth_ldap here, since that just creates users on demand as they log in (as others have noted). Instead, you can just use the raw python_ldap module to do a raw LDAP query:

username = "..."
password  = "..."
scope = ldap.SCOPE_SUBTREE
base = "ou=...,dc=...,dc=..."
filter="..."
retrieve_attributes=['cn','uid','displayName']

l = ldap.open("your.ldap.server")    
l.protocol_version = ldap.VERSION3
l.simple_bind(username, password)
results = l.search_s(base, scope, filter, retrieve_attributes)

And then iterate over the results to stuff them into your model.

Stenotype answered 28/7, 2011 at 16:23 Comment(4)
Ok, so I tried to type this block of code in django shell and I get an error SERVER_DOW: {'desc': "Can't connect LDAP server"} So I guess there is something wrong in the connection parameters but I never used LDAP before so I'm not completely sure of what I'm doing here ..Revolt
After which statement do you get the error? ldap.open(...)?Inconstant
After ldap.open(...) I get LDAPError: (0, 'Error')Revolt
I'm not sure off hand what the issue would be here (that error isn't too helpful). Are you able to connect to the LDAP server from that machine outside of Python? If not, there may be a firewall or something in the way. Otherwise you might get more information by checking out the error info like except ldap.LDAPError, e: print e.message['info']Inconstant
L
2

I needed to do something similar, and found the LDAPBackend.populate_user(user_name) API useful.

from django_auth_ldap.backend import LDAPBackend
user = LDAPBackend().populate_user('user_name')

Given each call is going to issue LDAP queries and a bunch of DB select/ updated/ insert queries, this is more suited to getting or creating occasional users (for masquerading as them/ check how the app looks for them) rather than bulk creating them.

Loxodromic answered 18/2, 2019 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.