2015-04-01 130 views
1

背景: 我正在开发一个API来集中用户创建和管理多个资源(例如Google Apps,Dropbox等)。 在Linux VM上,我开发了一个API和Web界面,允许我(和我的共同管理员)对这些服务的用户帐户进行身份验证和管理。 我需要整合的下一件事是我们的Active Directory托管在远程Windows Server 2008上。使用Python脚本来管理远程LDAP服务器

我一直在尝试使用python-ldap来连接并检索/修改信息,但在DIR_ERROR操作时遇到了问题错误(试图查询用户时)和NAMING_VIOLATION错误(尝试添加用户时)。

*代码基于http://www.grotan.com/ldap/python-ldap-samples.html,计算器问题,和Python-LDAP文档 绑定代码,我相信作品:

import ldap 
try: 
    l = ldap.open("serverip") 
    l.protocol_version = ldap.VERSION3 

    username = "[email protected]" 
    password = "secret" 

    result = l.simple_bind(username, password) 
    print result 

except ldap.LDAPError, e: 
    print e 

它打印: (97,[],1,[])

查询用户脚本: (按照文章建议尝试不绑定,但收到“为了执行此操作,必须在连接上完成成功的绑定。”)

import ldap 

try: 
    l = ldap.open("serverIp", port=389) 
    l.protocol_version = ldap.VERSION3 
    username = "[email protected]" 
    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 

这导致以下: (97,[],1,[]) { '信息': '000020D6:SvcErr:DSID-031007DB,问题5012(DIR_ERROR),数据0 \ n',”说明 ':' 操作错误 '}

添加用户脚本:(使用LDAPS)

导致: ldap.SERVER_DOWN:{' 信息 ':' 突发长度为TLS接收数据包'''desc':“无法联系LDAP服务器”}

*这让我想到了t这个端口可能是问题所在,所以我将初始化行更改为l = ldap.initialize("ldap://serverIp:389/"),类似于其他两个脚本。

现在,我得到: ldap.NAMING_VIOLATION:{ '信息':“00002099:NameErr:DSID-0305109C,2005年问题(NAMING_VIOLATION),数据0的最佳匹配:\ n \ t'dc = ADTEST,DC =本地'\ n“,'desc':'命名违规'}

此外,我添加ou和uid到attrs,但错误没有改变。

我在做什么错,或者我能做些什么改变? 谢谢任何​​帮助/建议!

编辑:我检查了我的服务器,并且端口636被正确设置为允许安全LDAP流量,所以我不知道为什么这会给我不同的错误,而不是正常的LDAP。 EDIT2:我试图改变下面一行在我添加脚本 DN =“CN =测试,DC = adtest.local”

和新的输出(堆栈跟踪),我已经是(我加print语句中表明绑定实际发生现在的错误之前):
(97,[],1,[])
回溯(最近最后一次通话):
文件 “test2.py”,第21行,在<module>
l。add_s(dn,ldif)
文件“/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,第202行,在add_s中
return self.result(msgid,all = 1, timeout = self.timeout)
文件“/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,第465行,结果
resp_type,resp_data,resp_msgid = self.result2(msgid ,all,timeout)
文件“/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,第469行,结果2
resp_type,resp_data,resp_msgid,resp_ctrls = self.result3( msgid,all,timeout)
文件“/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,第476行,结果3
resp_ctrl_classes = resp_ctrl_classes
文件 “/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,线路483,在result4
ldap_result = self._ldap_call(self._l.result4, msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
文件“/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py”,第106行,在_ldap_call
result = func(* args,** kwargs)
ldap.REFERRAL:{'info':'Referral:\ nldap://adtest.local/cn=test,dc=adtest.local','desc':'Referral'}

回答

4

Working Query search!
感谢:
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("[email protected]", "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() 

我,在我的代码中的一个错误,但由于LDAP使用纯文本,并且不允许没有发送私人信息仍无法设置某些属性安全连接。 为了添加/修改用户密码信息和userAccountControl标志(以启用用户),我通过添加Active Directory证书服务(*要求您重新启动服务器)在服务器上启用了端口636来切换到LDAPS。
此外,您需要在初始化之前包含'ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,0)'行。

工作添加用户
感谢:
how to set lockoutTime and password of a user of Active Directory

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("[email protected]","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's properties on your DC. 
attrs = {} 
attrs['cn'] = 'TestUser' 
attrs['displayName'] = 'TestUser' 
attrs['givenName'] = 'Test' 
attrs['mail'] = '[email protected]' 
attrs['name'] = 'Test User' 
attrs['objectclass'] = ['top','person','organizationalPerson','user'] 
attrs['sAMAccountName'] = 'testuser' 
attrs['sn'] = 'User' 
attrs['unicodepwd'] = password_value 
attrs['userPrincipalName'] = '[email protected]' 

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() 
相关问题