28

我想在 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

并使用由此获得的变量。我怎样才能做到这一点?

4

5 回答 5

55

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()
于 2015-03-05T14:52:29.777 回答
4

您可能想使用该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
于 2011-01-24T18:17:00.370 回答
2

这是 python-ldap 的示例生成器。

ldap_server是您从 ldap.initialize() 获得的对象。您可能还需要在调用此函数之前进行绑定,具体取决于您使用的 LDAP 服务器以及您尝试查询的内容。和类似于您在命令行版本中获得的内容base_dnfilter_是返回的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

于 2014-08-28T22:37:23.783 回答
0

您可以使用 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 二进制文件。

于 2011-01-24T18:08:03.490 回答
0

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)) 
    
于 2021-10-26T16:23:56.033 回答