sk8*_*eat 1 python active-directory python-ldap
背景:我正在开发一个API来集中用户创建和管理多个资源(例如Google Apps,Dropbox等).在Linux VM上,我开发了一个API和Web界面,允许我(和我的共同管理员)对这些服务的用户帐户进行身份验证和管理.我需要集成的下一件事是我们的Active Directory,它托管在远程Windows Server 2008上.
我一直在尝试使用python-ldap来连接和检索/修改信息,但是遇到了DIR_ERROR操作错误(当试图查询用户时)和NAMING_VIOLATION错误(尝试添加用户时)的问题.
*基于http://www.grotan.com/ldap/python-ldap-samples.html,stackoverflow问题和python-ldap文档的代码我相信的绑定代码:
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
Run Code Online (Sandbox Code Playgroud)
打印:(97,[],1,[])
查询用户脚本:(根据文章的建议尝试不绑定,但收到"为了执行此操作,必须在连接上完成成功绑定.")
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
Run Code Online (Sandbox Code Playgroud)
结果如下:(97,[],1,[]){'info':'000020D6:SvcErr:DSID-031007DB,问题5012(DIR_ERROR),数据0 \n','desc':'操作错误"}
添加用户脚本:(使用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()
Run Code Online (Sandbox Code Playgroud)
其结果是:ldap.SERVER_DOWN:{'info':'收到了一个意外长度的TLS数据包.','desc':"无法联系LDAP服务器"}
*这让我觉得端口可能是问题,因此我将初始化行更改为l = ldap.initialize("ldap://serverIp:389/")类似于其他两个脚本.
现在我得到:ldap.NAMING_VIOLATION:{'info':"00002099:NameErr:DSID-0305109C,问题2005(NAMING_VIOLATION),数据0,最佳匹配:\n\t'dc = adtest,dc = local'\n ",'desc':'命名违规'}
另外,我已经搞砸了将ou和uid添加到attrs但没有改变错误.
我做错了什么或者我可以尝试做些什么?感谢您的任何帮助/建议!
编辑:我检查了我的服务器,端口636被正确设置为允许安全LDAP流量,所以我不知道为什么这给了我不同于普通LDAP的错误.edit2:我尝试在添加脚本中更改以下行dn ="cn = test,dc = adtest.local"
和我有的新输出(堆栈跟踪)是(我添加了print语句以显示绑定实际发生在错误之前):(
97,[],1,[])
Traceback(最近一次调用last ):
文件"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,a dd_extop)
文件"/usr/local/lib/python2.7/dist-packages/ldap/ldapobject.py",第106行,在_ldap_call中
结果= func(*args,**kwargs)
ldap.REFERRAL:{'info' :'推荐人:\nldap://adtest.local/cn=test,dc=adtest.local','desc':'推荐'}
工作查询搜索!
相信: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()
Run Code Online (Sandbox Code Playgroud)
我修复了我的代码中的一个错误,但仍然无法设置某些属性,因为LDAP使用纯文本,并且不允许在没有安全连接的情况下发送私人信息.为了添加/修改用户密码信息和userAccountControl标志(以启用用户),我使用端口636切换到LDAPS,我通过添加Active Directory证书服务(*要求您重新启动服务器)在服务器上启用了该端口.
此外,您需要在初始化之前包含'ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,0)'行.
工作添加用户
信用:
如何设置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("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's 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()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3217 次 |
| 最近记录: |