Use Python script to manage remote LDAP server

Background: I am working on an API to centralize the creation and management of users for several resources (e.g. Google Apps, Dropbox, etc.). On a Linux virtual machine, I developed an API and a web interface that allows me (and my employees) to authenticate and manage user accounts for these services. The next thing I need for integration is our Active Directory hosted on a remote Windows Server 2008.

I am trying to use python-ldap to connect and retrieve / modify information, but you had problems with DIR_ERROR operation errors (when trying to query for users) and NAMING_VIOLATION errors (when trying to add users).

* Code based on http://www.grotan.com/ldap/python-ldap-samples.html , stack questions and documentation python-ldap Binding code, which I believe works:

import ldap try: l = ldap.open("serverip") l.protocol_version = ldap.VERSION3 username = " myUserName@adtest.local " password = "secret" result = l.simple_bind(username, password) print result except ldap.LDAPError, e: print e 

which prints: (97, [], 1, [])

The request for users is script: (I tried without binding, as suggested in the article, but got "To complete this operation, successful binding must be completed in the connection.")

 import ldap try: l = ldap.open("serverIp", port=389) l.protocol_version = ldap.VERSION3 username = " myUserName@adtest.local " password = "secret" result = l.simple_bind(username, password) print result except ldap.LDAPError, e: print e # handle error however you like baseDN = "ou=Users, o=adtest.local" searchScope = ldap.SCOPE_SUBTREE retrieveAttributes = None searchFilter = "cn=*myUserName*" try: ldap_result_id = l.search(baseDN, searchScope, searchFilter, retrieveAttributes) result_set = [] while 1: result_type, result_data = l.result(ldap_result_id, 0) if (result_data == []): break else: if result_type == ldap.RES_SEARCH_ENTRY: result_set.append(result_data) print result_set except ldap.LDAPError, e: print e 

which leads to the following: (97, [], 1, []) {'info': '000020D6: SvcErr: DSID-031007DB, problem 5012 (DIR_ERROR), data 0 \ n', 'desc': 'Operation error' }

Add user script :( using ldaps)

 import ldap import ldap.modlist as modlist # Open a connection l = ldap.initialize("ldaps://serverIp:636/") # Bind/authenticate with a user with apropriate rights to add objects l.simple_bind_s(" myUserName@adtest.local ","secret") # The dn of our new entry/object dn="cn=test,dc=adtest,dc=local" # A dict to help build the "body" of the object attrs = {} attrs['objectclass'] = ['top','organizationalRole','simpleSecurityObject'] attrs['cn'] = 'test' attrs['userPassword'] = 'aDifferentSecret' attrs['description'] = 'test user' # Convert our dict to nice syntax for the add-function using modlist-module ldif = modlist.addModlist(attrs) # Do the add-operation to the ldapserver l.add_s(dn,ldif) # Disconnect and free resources when done l.unbind_s() 

The result is: ldap.SERVER_DOWN: {'info': 'Received TLS packet with unexpected length.', 'Desc': "Unable to contact the LDAP server"}

* It made me think that the port might be a problem, so I changed the initialization line to l = ldap.initialize("ldap://serverIp:389/") , similar to the other two scripts.

Now I get: ldap.NAMING_VIOLATION: {'info': "00002099: NameErr: DSID-0305109C, issue 2005 (NAMING_VIOLATION), data 0, best match: \ n \ t'dc = adtest, dc = local '\ n" , 'desc': 'Naming violation'}

In addition, I came across adding uu and uid to attrs, but with no change in error.

What am I doing wrong or what can I do differently? Thanks for any help / suggestions!

edit: I checked my server and port 636 is configured correctly to allow Secure LDAP traffic, so I don’t know why this gave me different errors than regular LDAP. edit2: I tried changing the next line in my add script dn = "cn = test, dc = adtest.local"

and I have a new output (stack trace) (I added a print expression in to show that the binding is actually happening now before the error):
(97, [], 1, [])
Traceback (last last call):
File "test2.py", line 21, in <module>
l.add_s (dp, LDIF)
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 202, in add_s
return self.result (msgid, all = 1, timeout = self.timeout)
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 465, resulting
resp_type, resp_data, resp_msgid = self.result2 (msgid, all, timeout)
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 469, in result2
resp_type, resp_data, resp_msgid, resp_ctrls = self.result3 (msgid, all, timeout)
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 476, in result3
resp_ctrl_classes = resp_ctrl_classes
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 483, in result4
ldap_result = self._ldap_call (self._l.result4, msgid, all, timeout, add_ctrls, add_intermediates, add_extop)
File "/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py", line 106, in _ldap_call
result = func (* args, ** kwargs)
ldap.REFERRAL: {'info': 'Referral: \ nldap: //adtest.local/cn=test,dc=adtest.local', 'desc': 'Referral'}

+1
source share
1 answer

Search for a job request!
Credit for:
http://www.linuxjournal.com/article/6988?page=0.0

 import ldap def main(): keyword = "user_query" try: l = ldap.open(serverIp) l.simple_bind_s(" myUserName@adtest.local ", "password") print "successfully bound to server.\n" print "Searching..\n" my_search(l,keyword) except ldap.LDAPError, e: print "Couldn't connect. %s " % e def my_search(l, keyword): #Base is for the DN(Distinguised Name) of the entry where the search should start base = "cn=Users,dc=adtest,dc=local" #Scope has three options, SUBTREE searches all sub-folder/directories scope = ldap.SCOPE_SUBTREE #filter consists of a cn(common name) and keyword. #putting asterisks around our keyword will match anything containing the string f = "cn=" + "*" + keyword + "*" #determines which attributes to return. Returns all if set to "None" retrieve_attributes = None count = 0 result_set = [] timeout = 0 result = l.search_s(base, scope, f, retrieve_attributes) print result[0][1].keys() try: result_id = l.search(base, scope, f, retrieve_attributes) while 1: result_type, result_data = l.result(result_id, timeout) if(result_data == []): break else: if result_type == ldap.RES_SEARCH_ENTRY: result_set.append(result_data) if len(result_set) == 0: print "No Results" return for i in range(len(result_set)): for entry in result_set[i]: try: name = entry[1]['cn'][0] count += 1 print str(count)+" "+name except: pass except ldap.LDAPError, e: print e if __name__=='__main__': main() 

I fixed one error in my code, but could not set certain properties, because LDAP uses plain text and does not allow sending private information without a secure connection. To add / change user password information and userAccountControl flags (to enable the user), I switched to LDAPS using port 636, which I enabled on the server, adding Active Directory Certificate Services (* server restart is required). <sh> In addition, before initialization, you must include the string 'ldap.set_option (ldap.OPT_X_TLS_REQUIRE_CERT, 0)'.

Work Add user
Credit for:
how to set lockoutTime and Active Directory user password

 import ldap import ldap.modlist as modlist ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,0) l = ldap.initialize("ldaps://10.99.0.214:636") l.set_option(ldap.OPT_PROTOCOL_VERSION, 3) l.set_option(ldap.OPT_NETWORK_TIMEOUT, 10.0) t = l.simple_bind_s(" myUserName@adtest.local ","password") dn="cn=TestUser,cn=Users,dc=adtest,dc=local" #make a unicode password to set for user unicode_pass = unicode('\"'+"userPwd"+'\"', 'iso-8859-1') password_value = unicode_pass.encode('utf-16-le') #What I set for my users, you can find more by looking through a user properties on your DC. attrs = {} attrs['cn'] = 'TestUser' attrs['displayName'] = 'TestUser' attrs['givenName'] = 'Test' attrs['mail'] = ' testuser@company.com ' attrs['name'] = 'Test User' attrs['objectclass'] = ['top','person','organizationalPerson','user'] attrs['sAMAccountName'] = 'testuser' attrs['sn'] = 'User' attrs['unicodepwd'] = password_value attrs['userPrincipalName'] = ' testuser@adtest.local ' ldif = modlist.addModlist(attrs) l.add_s(dn,ldif) #Now that the user is created and has a password(needs to meet AD requirements), they can be enabled #For full userAccountControl flag list: #http://support.microsoft.com/en-us/kb/305144 mod_acct = [(ldap.MOD_REPLACE, 'userAccountControl', '66048')] try: l.modify_s(dn, mod_acct) except ldap.LDAPError, e: print e l.unbind_s() 
+4
source

All Articles