
The ldap3 module can be used to query LDAP. pip install can be used to ensure you have the ldap3 module installed.
pip install ldap3
In this example, a connection will be made to LDAP as john.doe searching for an entry matching common name (cn) jane.doe. This is basically based off of ldapsearch so you may want to check out my article FreeKB - LDAP - List LDAP Users Groups Organizational Unit using the ldapsearch command.
#!/usr/bin/python3
import ldap3
username = "john.doe"
password = "itsasecret"
ldap_uri = "ldaps://ldap.example.com:636"
base = "DC=ldap,DC=example,DC=com"
search_filter = "(&(cn=jane.doe))"
attrs = ["*"]
server = ldap3.Server(ldap_uri)
with ldap3.Connection(server, auto_bind=True, user=username, password=password) as conn:
conn.search(base, search_filter, attributes=attrs)
print(conn.entries)
Or like this, which is nice, as then you can use error handling to catch exceptions.
#!/usr/bin/python3
import ldap3
import sys
username = "john.doe"
password = "itsasecret"
ldap_uri = "ldaps://ldap.example.com:636"
base = "DC=ldap,DC=example,DC=com"
search_filter = "(&(cn=jane.doe))"
attrs = ["*"]
server = ldap3.Server(ldap_uri)
try:
conn = ldap3.Connection(server, auto_bind=True, user=username, password=password)
except Exception as exception:
print(f"got the following exception => {exception}")
sys.exit(1)
conn.search(base, search_filter, attributes=attrs)
print(conn.entries)
If the connection is successful and the search returns has a match, something like this should be returned.
[DN: CN=john.doe,OU=Accounts.Users,DC=ldap,DC=example,DC=com - STATUS: Read - READ TIME: 2024-08-08T00:52:16.966216
accountExpires: 9999-12-31 23:59:59.999999+00:00
badPasswordTime: 2024-07-31 01:12:11.456739+00:00
badPwdCount: 0
cn: jane.doe
codePage: 0
countryCode: 0
dSCorePropagationData: 2024-06-28 19:43:43+00:00
department: Sales
displayName: Jane Doe
distinguishedName: CN=jane.doe,OU=Accounts.Users,DC=ldap,DC=example,DC=com
employeeID: 123456
givenName: Jane
instanceType: 4
lastLogon: 2024-07-31 01:12:17.347954+00:00
lastLogonTimestamp: 2024-08-06 01:31:37.250376+00:00
lockoutTime: 1601-01-01 00:00:00+00:00
logonCount: 3
mail: jane.does@example.com
memberOf: CN=Sales,OU=Groups,DC=ldap,DC=example,DC=com
name: jane.doe
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=example,DC=com
objectClass: top
person
organizationalPerson
user
objectGUID: {daeaf2bb-7474-412a-945f-c9cb7de1a4ca}
pwdLastSet: 2021-08-13 03:27:06.956690+00:00
sAMAccountName: jane.doe
sAMAccountType: 805306368
sn: Doe
title: Sales
uSNChanged: 26601863
uSNCreated: 105055
userAccountControl: 512
userParameters: CtxCfgPresent
userPrincipalName: jane.doe@example.com
whenChanged: 2024-08-06 01:31:37+00:00
whenCreated: 2021-03-25 19:02:02+00:00
]
And here is a bit of a more mature example where attrs is used to only return the distinguishedName and memberOf lists.
#!/usr/bin/python3
import ldap3
import json
username = "john.doe"
password = "itsasecret"
ldap_uri = "ldaps://ldap.example.com:636"
base = "DC=ldap,DC=example,DC=com"
search_filter = "(&(cn=jane.doe))"
attrs = ["distinguishedName", "memberOf"]
with ldap3.Connection(server, auto_bind=True, user=username, password=password) as conn:
conn.search(search_base, search_filter, attributes=attrs)
if len(conn.entries) == 0:
print(f"found 0 entries in LDAP {ldap_uri} matching {search_filter }")
else:
for entry in conn.entries:
parsed_json = json.loads(entry.entry_to_json())
print(f"parsed_json['dn'] = {parsed_json['dn']}")
for member_of in parsed_json['attributes']['memberOf']:
print(f"member_of = {member_of}")
Did you find this article helpful?
If so, consider buying me a coffee over at