active directory - Use Python script to manage remote LDAP server -


background: working on api centralize user creation , management multiple resources(e.g. google apps, dropbox, etc...). on linux vm, developed api , web interface allows me(and co-admins) authenticate , manage user accounts these services. next thing need integrate our active directory hosted on remote windows server 2008.

i have been trying use python-ldap connect , retrieve/modify information have had issues dir_error operations errors(when trying query users) , naming_violation errors(when trying add users).

*code based on http://www.grotan.com/ldap/python-ldap-samples.html, stackoverflow questions, , python-ldap documentation binding code 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, [])

query users script: (tried without bind suggested article, received "in order perform operation successful bind must completed on 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  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 results in following: (97, [], 1, []) {'info': '000020d6: svcerr: dsid-031007db, problem 5012 (dir_error), data 0\n','desc':'operations error'}

add user script:(using ldaps)

import ldap import ldap.modlist modlist  # open connection l = ldap.initialize("ldaps://serverip:636/")  # bind/authenticate user apropriate rights add objects l.simple_bind_s("myusername@adtest.local","secret")  # dn of our new entry/object dn="cn=test,dc=adtest,dc=local"   # dict build "body" of object attrs = {} attrs['objectclass'] = ['top','organizationalrole','simplesecurityobject'] attrs['cn'] = 'test' attrs['userpassword'] = 'adifferentsecret' attrs['description'] = 'test user'  # convert our dict nice syntax add-function using modlist-module ldif = modlist.addmodlist(attrs)  # add-operation ldapserver l.add_s(dn,ldif)  # disconnect , free resources when done l.unbind_s() 

which results in: ldap.server_down: {'info': 'a tls packet unexpected length received.','desc': "can't contact ldap server"}

*this made me think port might problem, changed initialize line l = ldap.initialize("ldap://serverip:389/") similar other 2 scripts.

now get: ldap.naming_violation: {'info': "00002099: nameerr: dsid-0305109c, problem 2005 (naming_violation), data 0, best match of:\n\t'dc=adtest, dc=local'\n", 'desc': 'naming violation'}

additionally, have messed around adding ou , uid attrs no change in error.

what doing wrong or try differently? thank help/suggestions!

edit: checked server, , port 636 correctly set allow secure ldap traffic, don't know why giving me different errors normal ldap. edit2: tried changing following line in add script dn="cn=test,dc=adtest.local"

and new output(stack trace) have is(i added print statement in show bind taking place before error):
(97, [], 1, [])
traceback (most recent call last):
file "test2.py", line 21, in <module>
l.add_s(dn,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, in result
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'}

working query search!
credit to:
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 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 dn(distinguised name) of entry search should start     base = "cn=users,dc=adtest,dc=local"     #scope has 3 options, subtree searches sub-folder/directories     scope = ldap.scope_subtree     #filter consists of cn(common name) , keyword.     #putting asterisks around our keyword match containing string     f = "cn=" + "*" + keyword + "*"     #determines attributes return. returns if set "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         in range(len(result_set)):             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 1 mistake in code, still couldn't set properties because ldap uses plain-text , not allow private info sent without secure connection. in order add/modify user password info , useraccountcontrol flags(to enable user), switched ldaps using port 636, enabled on server adding active directory certificate services(*requires restart server).
additionally need include 'ldap.set_option(ldap.opt_x_tls_require_cert,0)' line before initialize.

working add user
credit to:
how set lockouttime , password of user of active directory

import ldap import ldap.modlist 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 unicode password set user unicode_pass = unicode('\"'+"userpwd"+'\"', 'iso-8859-1') password_value = unicode_pass.encode('utf-16-le')  #what set users, can find more looking through user's properties on 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 user created , has password(needs meet ad requirements), can 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() 

Comments

Popular posts from this blog

How to run C# code using mono without Xamarin in Android? -

c# - SharpSsh Command Execution -

python - Specify path of savefig with pylab or matplotlib -