1

I had this working before. Now, after flatting and rebuilding machine, I can't seem to get pyad working.

My script uses adquery to get the members of a domain.

I've installed pyad and pywin32 with the correct versions. I am using Python 3.6.

I keep getting the following error:

pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Active Directory', 'The specified domain either does not exist or could not be contacted.\r\n', None, 0, -2147217865), None)

The script ran before perfectly so I am assuming it is an installation issue.

Here is the function I wrote:

from pyad import adquery, aduser, adbase

def call_adquery(domain, debug):

global numRow
log.info('Domain: {}'.format(domain))
df = pd.DataFrame()
z_obj = adquery.ADQuery()
t = datetime.today().strftime('%m/%d/%Y')
i = 0
if domain == 'satyan':
    wc = "mailNickname='satyan'"
    domain = 'redmond'
else:
    wc = """
    objectClass='user'
    and showInAddressBook='*'
    and manager='*'
    and not mailNickname='b-*'
    """
dn = base_dn = 'OU=UserAccounts,DC={0}, DC=corp,DC=microsoft,DC=com'.format(domain)
att = ['name', 'displayName', 'title', 'company', 'msExchHideFromAddressLists',
       'manager', 'mail', 'mailNickname', 'distinguishedName', 'extensionAttribute4',
       'extensionAttribute2','sn','cn','givenName', 'instanceType','userPrincipalName',
       'objectCategory']
z_obj.execute_query(attributes=att, where_clause=wc, base_dn=dn, type='GC')
for row in z_obj.get_results():
    i += 1
    numRow += 1
    n = pd.Series.from_array(row)
    log.info("{0}, {1}, {2}, {3}".format(numRow, i, domain, row['name']))
    n['domain'] = domain
    n['date'] = t
    df = df.append(n, ignore_index=True)
    if (debug==True) and (i == 10): break
log.info('Count for {0}: {1}'.format(domain, i))
return df
Bharel
  • 23,672
  • 5
  • 40
  • 80

1 Answers1

2

Not sure why I got dinged for asking a question. Maybe that's how stackoverflow works.

I figured out the answer and it wasn't as simple as changing the domain. Andrew I do appreciate you responding as it sent me down the right path.

I spent a ton of time debugging this. I even tried using ldap3 - a different python AD library. That one was buggy but way faster if you had a resultset less than 1000. I was never able to do a page searched of more than 1000 records - the AD limit. Eventually, I went back to pyad and figured out the problem. Pyad is an easier to use module - in my humble opinion.

I learned the difference between and LDAP server and a GC server. The GC server has the ability to serve up most attributes for all domains in the forest. I was able to identify a GC server on the network using powershell:

> $GCs = Get-ADForest
> $GCs.GlobalCatalogs

Once I had that, I set the LDAP server in pyad:

z_obj.default_ldap_server='xxxx.corp.microsoft.com'  

I also removed a few attributes from the query. Not sure if that was a factor.

The end results works just fine without sending username and password to pyad. Here is the code that works:

def call_adquery(domain, debug=False):
    df = pd.DataFrame()
    z_obj = adquery.ADQuery()
    i = 0
    wc = """
    objectClass='person'
    and SAMAccountType='805306368'
    and userAccountControl='512'
    """
    dn = 'OU=UserAccounts,DC={0},DC=corp,DC=microsoft,DC=com'.format(domain)
    att = ['givenName', 'mail', 'manager',
            'Name',
            'displayName','Title','mailNickName',
            'Department','Company',
            'userPrincipalName','sn','cn', 'DistinguishedName',
            'physicalDeliveryOfficeName']
    z_obj.default_ldap_server='<gc from powershell>' 
    z_obj.execute_query(attributes=att, where_clause=wc, base_dn=dn, type='GC')
    df = pd.DataFrame()
    for row in z_obj.get_results():
         i += 1
         if (debug==True) and (i == 10): 
            break
         if len(df)==0:
            df =pd.DataFrame(row, index=[0])
         else:
            df= df.append(row, ignore_index=True)
     return df

My guess is my default active directory server changed and thus caused my fragile code to fail.

Hope this helps someone else.