Python ldap query active directory
wordpress meta
title: 'Python-ldap Query MS Active Directory'
date: '2012-11-06T23:06:39-06:00'
status: publish
permalink: /python-ldap-query-active-directory
author: admin
excerpt: ''
type: post
id: 72
category:
- 'Active Directory'
- KVM
- Python
tag: []
post_format: []
title: 'Python-ldap Query MS Active Directory'
date: '2012-11-06T23:06:39-06:00'
status: publish
permalink: /python-ldap-query-active-directory
author: admin
excerpt: ''
type: post
id: 72
category:
- 'Active Directory'
- KVM
- Python
tag: []
post_format: []
I use Python to pull Active Directory information sometimes. In my case mainly to report or view information but also to create files in a LDIF or PowerShell format. These can be manually run on the Domain Controller later. For instance find all users in a Distribution List or Group and create a rule or ldif entry that can manually be executed line by line. Off course there is also ways with PowerShell and vbscript to do this, but I prefer Python for text manipulation and it is not too cumbersome for me to batch run these files manually later.
I noticed on Ubuntu 12.10 that my query failed with the following error:
ldap.LDAP_CONTROL_PAGE_OID,True,(page_size,'')
AttributeError: '<span style="color: #ff0000;">module' object has no attribute 'LDAP_CONTROL_PAGE_OID</span>'
I found a comment from the developers saying that with python-ldap 2.4
"there have been changes in the API for LDAPv3 extended controls. Please see Demo/page_control.py (and Demo/paged_search_ext_s.py) how to use the simple paged control with 2.4."
I found the source here: http://python-ldap.cvs.sourceforge.net/viewvc/python-ldap/python-ldap/Demo/page_control.py?view=log
I made a new script and tested as shown below:
** Note the following first:
- This is a "paged" query meaning you should not have issues if LDAP return a limted number of results. More detail here: http://support.microsoft.com/kb/315071
- You need to install python-ldap of course. apt-get install python-ldap should work on apt systems.
- Check comment about using 512 as userAccountControl.
DistributionList = "CN=IT Infrastructure,CN=Distribution Lists,CN=Users,DC=domain,DC=com"
url = "ldap://usdc101"
base = "dc=domain,dc=com"
# search_flt = r'(objectClass=*)'
## I used userAccountControl=512 but that would most certainly exclude some
## user accounts in your domain. For instance "66048 Enabled, Password Doesn't Expire"
## values listed here: http://www.netvision.com/ad_useraccountcontrol.php
search_flt = r'(&(objectCategory=user) (userAccountControl=512) )'
page_size = 10
import ldap,pprint
from ldap.controls import SimplePagedResultsControl
searchreq_attrlist=["displayName","cn","distinguishedName","mail","memberOf"]
ldap.set_option(ldap.OPT_REFERRALS, 0)
l = ldap.initialize(url,trace_level=0)
l.protocol_version = 3
l.simple_bind_s("ADaccount@domain.com", "passsword")
req_ctrl = SimplePagedResultsControl(True,size=page_size,cookie='')
known_ldap_resp_ctrls = {
SimplePagedResultsControl.controlType:SimplePagedResultsControl,
}
# Send search request
msgid = l.search_ext(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=[req_ctrl]
)
pages = 0
i = 0
print "listing users in the list:" + DistributionList
while True:
pages += 1
rtype, rdata, rmsgid, serverctrls = l.result3(msgid,resp_ctrl_classes=known_ldap_resp_ctrls)
for dn, entry in rdata:
## Lets check if the user is a member of the AD List / Group
try:
membership = entry['memberOf']
except:
membership = 'none'
if DistributionList in membership:
i += 1
print " \"%d\" | \"%s\" " % (i , dn)
pctrls = [
c
for c in serverctrls
if c.controlType == SimplePagedResultsControl.controlType
]
if pctrls:
if pctrls[0].cookie:
# Copy cookie from response control to request control
req_ctrl.cookie = pctrls[0].cookie
msgid = l.search_ext(
base,
ldap.SCOPE_SUBTREE,
search_flt,
attrlist=searchreq_attrlist,
serverctrls=[req_ctrl]
)
else:
break
else:
print "Warning: Server ignores RFC 2696 control."
break
l.unbind_s()