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 ?

Josh Scholl
  • 143
  • 15
Johanna
  • 1,343
  • 4
  • 25
  • 44

3 Answers3

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"],["some@email.address"]]
# 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", "some@email.address"]

# 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.

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • 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 ... – Johanna Jul 28 '11 at 15:04
  • @Johanna - I don't have a complete one, but I can get you started ... :-) – Sean Vieira Jul 28 '11 at 16:19
  • 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 ? – Johanna Jul 29 '11 at 12:28
  • @Johanna - apologies, I'd left off the scope of the search (which is an integer ... see http://www.python-ldap.org/doc/html/ldap.html#ldap.LDAPObject.search). I've updated my code example. – Sean Vieira Jul 29 '11 at 23:48
  • 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) – Johanna Aug 01 '11 at 08:24
  • @Johanna - Looks like you are over your limit ... try following the answer of this question http://stackoverflow.com/questions/481995/what-does-the-ldap-response-tuple-97-mean (found it by Googling "ldap error 97"). – Sean Vieira Aug 01 '11 at 16:51
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.

Kippr
  • 76
  • 5
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.

Michael C. O'Connor
  • 9,742
  • 3
  • 37
  • 49
  • 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 .. – Johanna Jul 29 '11 at 08:12
  • After which statement do you get the error? `ldap.open(...)`? – Michael C. O'Connor Jul 29 '11 at 20:47
  • After ldap.open(...) I get LDAPError: (0, 'Error') – Johanna Aug 01 '11 at 08:27
  • 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']` – Michael C. O'Connor Aug 03 '11 at 03:06