我想在 ldap 中执行以下查询
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))" gidnumber
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(gidNumber=1234)(objectClass=posixGroup))" cn
并使用由此获得的变量。我怎样才能做到这一点?
我想在 ldap 中执行以下查询
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))" gidnumber
ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(gidNumber=1234)(objectClass=posixGroup))" cn
并使用由此获得的变量。我怎样才能做到这一点?
While the accepted answer does in fact show a proper way to bind to an LDAP server I do feel it didn't answer the question holistically. Here is what I ended up implementing to grab the mail and department of a user. This somewhat blends the required attributes from the original question.
l = ldap.initialize('ldap://ldap.myserver.com:389')
binddn = "cn=myUserName,ou=GenericID,dc=my,dc=company,dc=com"
pw = "myPassword"
basedn = "ou=UserUnits,dc=my,dc=company,dc=com"
searchFilter = "(&(gidNumber=123456)(objectClass=posixAccount))"
searchAttribute = ["mail","department"]
#this will scope the entire subtree under UserUnits
searchScope = ldap.SCOPE_SUBTREE
#Bind to the server
try:
l.protocol_version = ldap.VERSION3
l.simple_bind_s(binddn, pw)
except ldap.INVALID_CREDENTIALS:
print "Your username or password is incorrect."
sys.exit(0)
except ldap.LDAPError, e:
if type(e.message) == dict and e.message.has_key('desc'):
print e.message['desc']
else:
print e
sys.exit(0)
try:
ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)
result_set = []
while 1:
result_type, result_data = l.result(ldap_result_id, 0)
if (result_data == []):
break
else:
## if you are expecting multiple results you can append them
## otherwise you can just wait until the initial result and break out
if result_type == ldap.RES_SEARCH_ENTRY:
result_set.append(result_data)
print result_set
except ldap.LDAPError, e:
print e
l.unbind_s()
您可能想使用该ldap
模块。代码看起来像:
import ldap
l = ldap.initialize('ldap://ldapserver')
username = "uid=%s,ou=People,dc=mydotcom,dc=com" % username
password = "my password"
try:
l.protocol_version = ldap.VERSION3
l.simple_bind_s(username, password)
valid = True
except Exception, error:
print error
这是 python-ldap 的示例生成器。
这ldap_server
是您从 ldap.initialize() 获得的对象。您可能还需要在调用此函数之前进行绑定,具体取决于您使用的 LDAP 服务器以及您尝试查询的内容。和类似于您在命令行版本中获得的内容base_dn
。filter_
是返回的limit
最大记录数。
def _ldap_list(ldap_server, base_dn, filter_, limit=0):
""" Generator: get a list of search results from LDAP asynchronously. """
ldap_attributes = ["*"] # List of attributes that you want to fetch.
result_id = ldap_server.search(base_dn, ldap.SCOPE_SUBTREE, filter_, ldap_attributes)
records = 0
while 1:
records += 1
if limit != 0 and records > limit:
break
try:
result_type, result_data = ldap_server.result(result_id, 0)
except ldap.NO_SUCH_OBJECT:
raise DirectoryError("Distinguished name (%s) does not exist." % base_dn)
if result_type == ldap.RES_SEARCH_ENTRY:
dn = result_data[0][0]
data = result_data[0][1]
yield dn, data
else:
break
Please keep in mind that interpolating user-provided values into your LDAP query is dangerous! It's a form of injection that allows a malicious user to change the meaning of the query. See: http://www.python-ldap.org/doc/html/ldap-filter.html
您可以使用 commands 模块和 getoutput 来解析 ldap 查询的结果:
from commands import getoutput
result = getoutput('ldapsearch -h hostname -b dc=ernet,dc=in -x "(&(uid=w2lame)(objectClass=posixAccount))"')
print result
您必须在系统中安装 ldapsearch 二进制文件。
I cobbled this together this morning while skimming through the documentation of the ldap
module. It can fulfil the requirements of the OP changing the filter and the other settings to his liking.
The documentation of the ldap
module is pretty good if you understand the context (that's what took me a while). And the module is surprinsingly easy to use. We have a similar script written in bash using ldapserach
that is at least 3 or 4 times longer and more complex to read.
This code accepts a partial search string (email, name, uid or part of it) and returns the results in LDIF format. The idea is to make it very simple to use for a very specific task and if possible without using flags so that my less skilled co-workers can find the relevant info quickly.
Note that this is written for an LDAP server that runs on a machine that is not accessible from outside our internal network and which is secured with 2FA authentication. It can, thus, safely accept anonymous queries. But adding user and password should be trivial.
#! /usr/bin/python3
### usearch
### searches in the LDAP database for part of a name, uid or email and returns mail, uid, and full name
import ldap
import argparse
import sys
import ldif
l = ldap.initialize('ldaps://your.fancy.server.url', bytes_mode=False)
basedn = "dc=foo,dc=bar,dc=baz"
## ARGPARSE stuff!!!
parser=argparse.ArgumentParser(
description ='searches the LDAP server',
usage='usearch PARTIAL_MATCH (email, name, username)',
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('istr', help='searches stuffz')
parser.print_help
args = parser.parse_args(None if sys.argv[1:] else ['-h'])
str1 = args.istr
sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)
attributes = ["mail","uid","cn"]
scope = ldap.SCOPE_SUBTREE
r = l.search_s(basedn,scope,sfilter,attributes)
ldif_writer=ldif.LDIFWriter(sys.stdout)
for dn, entry in r:
ldif_writer.unparse(dn,entry)
And as I was at it, here a version with the ldap3 module. The argparse
part is copy-pasted. This time the output is "human readable", instead of LDIF:
#! /usr/bin/python3
## usearch3
## LDAP3 version
import ldap3
import argparse
import sys
server = ldap3.Server('ldaps://foo.bar.baz')
conn = ldap3.Connection(server)
conn.bind()
basedn = 'dc=foobar,dc=dorq,dc=baz'
attribs = ['mail','uid','cn']
parser=argparse.ArgumentParser(
description ='searches the LDAP server and returns user, full name and email. Accepts any partial entry',
usage='usearch3 PARTIAL_MATCH (email, name, username)',
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('istr', help='searches stuffz')
parser.print_help
args = parser.parse_args(None if sys.argv[1:] else ['-h'])
str1 = args.istr
sfilter = "(|(sn=*{}*)(mail=*{}*)(uid=*{}*))".format(str1,str1,str1)
conn.search(basedn,sfilter)
conn.search(basedn,sfilter,attributes = attribs)
leng = len(conn.entries)
for i in range(leng):
user = conn.entries[i].uid
fullname = conn.entries[i].cn
email = conn.entries[i].mail
print("user:\t{}\nname:\t{}\nemail:\t{}\n\n".format(user,fullname,email))