Python Forum
LDAP code to query for host not returning data
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
LDAP code to query for host not returning data
#1
I’m having an issue where the python-ldap module is returning no results, even though I am able to get results through other methods. I use the same parameters as ldapsearch, but the python code turns up nothing. This happens with a large number of hostnames that I search for.

Specifically, I am able to get valid LDAP data returned for a hostname with the following:

Output:
$ [2014][AD-user@host-joined-to-AD:~]$ ldapsearch -x -H ldaps://ldap-host-here.ds.subdomain.net:636 -D "[email protected]” -w ‘password-here' -b "DC=ds,DC=subdomain,DC=net" "(&(objectclass=computer)(cn=hostname-here))” |less
I also see a computer account for this system when logging into a Windows system on the domain and searching for the hostname via dsa, so I know the computer account is in AD/LDAP.

The following are my LDAP related modules. Note that I know the ldap module version is a little old, but as I’m running RHEL 7.5, it’s the newest I can make it without causing other dependencies to break, i.e. I had to install this via RPM.

Output:
$ pip freeze | grep ldap ldap3==2.5.1 python-ldap==2.4.15
I run my code, and it shows nothing in the results:

Output:
$ ./to-post.py Initializing LDAP connection object with uri ldaps://ldap-host-here.ds.subdomain.net:636 Binding with username username-here… LDAP results - []
The code is below. Any thoughts on why I’m not getting anything returned, even though the computer account exists?
#!/usr/bin/python

import ldap

#####################################
# IN: cfg, hostname, domain string
# OUT: True or False (if in AD or not)
def CheckIfHostInAD(cfg, hostname, env):

    domain = "tld-value-here"
    username = 'username-here'
    password = 'password-here'
    uri = "ldaps://ldap-host-here." + domain + ":636"

    (subdomain, tld) = domain.split('.')
    ## Create instance of LDAP class. No connection has been made yet.
    print("Initializing LDAP connection object with uri " + uri )
    l = ldap.initialize(uri)   #####!!!
    results = []
    OU_setting = ""

    try:
        # When we connect, make sure to connect using LDAPv3
        l.protocol_version = ldap.VERSION3
        #set connection
        l.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
        l.set_option(ldap.OPT_X_TLS_NEWCTX, 0)

        print("Binding with username " + username + "...")
        bind = l.simple_bind_s(username, password)

        # When we search, the base is the level at which we want to start searching
        OU_setting = ""
        base = OU_setting + "DC=ds,DC=" + subdomain + ",DC=net"

        # When we search, filter results down to ones that have an objectClass of "computer"
        criteria = "(&(objectclass=computer)(cn=" + hostname + "))"

        attributes = ['name']

        print("Getting hostnames in " + domain
                +  ", base " + str(base) + ", criteria " + str(criteria) )
        # Ok! Search and store the result in the variable "result"
        ldap_dump = l.search_s(base, ldap.SCOPE_SUBTREE, criteria, attributes)
        print("Found " + len(ldap_dump) + " hostnames in " + domain)

        # Print the results to the console
        for data_dict in [entry for dn, entry in ldap_dump if isinstance(entry, dict)]:
            results.append(data_dict["name"][0])

    except Exception as e:
        print("error - " + e)
    # Now that we're done (failed or not), release the connection
    finally:
        l.unbind()
        print("LDAP results - " + str(results))
        return results


cfg = ""
hostname = “short-hostname-here”
env = ""
result = CheckIfHostInAD(cfg, hostname, env)
quit()
As I noted earlier, I'd prefer not to upgrade the python-ldap module if not needed. In other words, unless there's something in a newer version where a bug resulting in no data being returned, I'd prefer not to upgrade.

Are there verbose settings for python-ldap I can set to see more of what's happening?
Reply
#2
I changed the initialization to a more verbose loglevel:

l = ldap.initialize(uri, trace_level=4, trace_file=sys.stderr)
added this to try block:

l.set_option(ldap.OPT_REFERRALS, 0)
I also added one more attribute, so I know I'm getting data specifically from AD/LDAP:

attributes = ['operatingSystem','name']
I then re-ran the code, and got the following. So, AD is definitely returning the data I want, just I'm not accessing it correctly. Any thoughts on how to access it?

Output:
*** <ldap.ldapobject.SimpleLDAPObject instance at 0x1115e3950> ldaps://ldap-host-here:636 - SimpleLDAPObject.simple_bind (('username@domain', 'password-here', None, None), {}) => result: 1 *** <ldap.ldapobject.SimpleLDAPObject instance at 0x1115e3950> ldaps://ldap-host-here:636 - SimpleLDAPObject.result4 ((1, 1, -1, 0, 0, 0), {}) => result: (97, [], 1, []) CheckIfHostInAD - Getting hostnames in dtveng.net, base DC=ds,DC=dtveng,DC=net, criteria (&(objectclass=computer)(cn=d010220021199)) *** <ldap.ldapobject.SimpleLDAPObject instance at 0x1115e3950> ldaps://ldap-host-here:636 - SimpleLDAPObject.search_ext (('blah=ds,blah=blah,DC=net', 2, '(&(objectclass=computer)(cn=hostname-here))', ('operatingSystem', 'name'), 0, None, None, -1, 0), {}) => result: 2 *** <ldap.ldapobject.SimpleLDAPObject instance at 0x1115e3950> ldaps://ldap-host-here:636 - SimpleLDAPObject.result4 ((2, 1, -1, 0, 0, 0), {}) => result: (101, [(u'CN=CN-here,OU=blah,OU=blah2,OU=blah3,OU=blah4,DC=blah5,DC=blah6,DC=blah7', {u'name': ['hostname-here'], u'operatingSystem': ['Red Hat Enterprise Linux']}), (None, [u'ldaps://ldap-host-here/CN=Configuration,DC=blah,DC=blah,DC=blah'])], 2, []) *** <ldap.ldapobject.SimpleLDAPObject instance at 0x1115e3950> ldaps://ldap-host-here:636 - SimpleLDAPObject.unbind_ext ((None, None), {}) => result: None
Reply
#3
I was able to parse and get the information I need by parsing ldap_dump as follows:

    
    while l:
            result_type, result_data = l.result(ldap_dump, 0)
            if (result_data == [] ):
                break
            else:
                if result_type == ldap.RES_SEARCH_ENTRY:
                    Log("info",  inspect.getframeinfo(inspect.currentframe()).function, "result - " + str(result_data) )
                    results.append(str(result_data))
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Returning Column and Row Data From Spreadsheet knight2000 0 434 Oct-22-2023, 07:07 AM
Last Post: knight2000
  Connecting to LDAP through Python ranjansanyal2007 0 408 Oct-09-2023, 05:21 PM
Last Post: ranjansanyal2007
  Code is returning the incorrect values. syntax error 007sonic 6 1,206 Jun-19-2023, 03:35 AM
Last Post: 007sonic
  Is the following code returning a generator expression? quazirfan 8 1,619 Apr-11-2023, 11:44 PM
Last Post: quazirfan
  Basic SQL query using Py: Inserting or querying sqlite3 database not returning data marlonbown 3 1,361 Nov-08-2022, 07:16 PM
Last Post: marlonbown
  Setup host for consistent data transfer to client via TCP Gustav97 0 693 Jun-27-2022, 07:33 PM
Last Post: Gustav97
  Same Data Showing Several Times With Beautifulsoup Query eddywinch82 2 1,237 May-29-2022, 11:46 PM
Last Post: eddywinch82
  Regex Expression With Code Query In Pandas eddywinch82 8 2,332 Apr-13-2022, 09:12 AM
Last Post: snippsat
  Ldap Search for finding user Groups ilknurg 1 1,755 Mar-11-2022, 12:10 PM
Last Post: DeaD_EyE
  where to host my python script tomtom 1 1,259 Feb-09-2022, 06:45 AM
Last Post: ndc85430

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020