Source code for cbs_utils.network

# -*- coding: utf-8 -*-
try:
    import win32com.client
except ImportError:
    print("Could load the win32 client.")
from typing import Dict, List


[docs]class ActiveDirectory(object): """ Active Directory representation. This object is intended to have all functionality that one would normally want/have from an Active Directory. """ # The values of default groups should be the groups you wish to examine, use the group's # sAMAccountName default_groups = ['Administrators', 'Account Operators', 'Backup Operators', 'Server Operators', 'DnsAdmins', 'Domain Admins', 'Exchange Administrators', 'Exchange Services', 'DHCP Administrators'] default_attrs = ['name', 'member', 'objectClass', 'adspath', 'primaryGroupToken', 'primaryGroupID'] def __init__(self, server: str = None): """ Creates an Active Directory object :param server: Alternative Server to use """ # TYPE: (str)->object self.server = server # if the server is given if self.server: # use this server self.ldap_root = win32com.client.GetObject( 'LDAP://{server}/rootDSE'.format(server=self.server)) else: # else use the default self.ldap_root = win32com.client.GetObject('LDAP://rootDSE') # retrieve the ldap location self.ldap_loc = self.ldap_root.Get('defaultNamingContext') # get the connection object self.objConnection = win32com.client.Dispatch("ADODB.Connection") # open the connection self.objConnection.Open("Provider=ADsDSOObject")
[docs] def get_group_info(self, name, searchRoot: str = None, category: str = "Group", attributes: list = None) -> Dict[str, str]: """ Obtain the group information for the given name :param name: profile name :param searchRoot: where to start looking :param category: what category to look in (by default the Group) :param attributes: additional attributes, examples are 'name', 'member', 'objectClass' :return: A Field : Value dictionary of all found information """ if not searchRoot: searchRoot = self.ldap_loc if not attributes: attributes = self.default_attrs # create the search string strSearch = \ "<LDAP://{search_root}>;(&(objectCategory={category})\ (sAMAccountName={name}));{attrs};subtree".format(search_root=searchRoot, category=category, name=name, attrs=','.join(attributes)) # execute the search objRecordSet = self.objConnection.Execute(strSearch)[0] objRecord = dict() # Normally, we would only expect one object to be retrieved. if objRecordSet.RecordCount == 1: # Set up a dictionary with attribute/value pairs and return the dictionary. for f in objRecordSet.Fields: objRecord[f.Name] = f.Value return objRecord
[docs] def get_group_members(self, strLdap: str, attributes: list = None) -> List[Dict[str, object]]: """ Look up a group's members. :param strLdap: groups adspath attribute. :param attributes: attributes to append to the search query :return: List of dictionaries, each dictionary item has a name and indicator of whether it is a group. """ if not attributes: attributes = self.default_attrs strSearch = "<%s>;;%s" % (strLdap, ','.join(attributes)) objRecordSet = self.objConnection.Execute(strSearch)[0] objRecord = dict() memberList = [] # Normally, we would only expect one object to be retrieved. if objRecordSet.RecordCount == 1: for f in objRecordSet.Fields: objRecord[f.Name] = f.Value # Check to see if the group has any members if objRecord['member'] is not None: # Look up each member and get their LDAP object for mbr in objRecord['member']: objRS = \ self.objConnection.Execute("<LDAP://%s>;;name,objectClass,adspath" % mbr)[0] # Check to see if the member is a group. is_group = True if 'group' in objRS.Fields[1].Value else False # append the name and group indicator to the answers memberList.append({"name": objRS.Fields[0].Value, "is_group": is_group}) # Return the list of results return memberList
[docs] def get_member_info(self, member: str, strLdap: str = None, attributes: List[str] = None) -> Dict[str, str]: """ Returns user info. If there is no list of attributes given, it will use a default list (for testing purposes). """ searchRoot = strLdap if strLdap else self.ldap_loc attrs = attributes if attributes else self.default_attrs strSearch = \ "<LDAP://{search_root}>;(&(objectCategory=user)\ (sAMAccountName={name}));{attrs};subtree".format(search_root=searchRoot, name=member, attrs=','.join(attrs)) # execute the search objRecordSet = self.objConnection.Execute(strSearch)[0] objRecord = dict() # Normally, we would only expect one object to be retrieved. if objRecordSet.RecordCount == 1: # Set up a dictionary with attribute/value pairs and return the dictionary. for f in objRecordSet.Fields: objRecord[f.Name] = f.Value return objRecord
[docs] def get_primary_group(self, token, searchRoot: str = None, header=" "): """ Used to look up Users whose Primary Group is set to one of the groups we're looking up. This is necessary as AD uses that attribute to calculate a group's membership. These type of users do not show up if you query the group's member field directly. searchRoot is the part of the LDAP tree that you want to start searching from. token is the groups primaryGroupToken. """ if not searchRoot: searchRoot = self.ldap_loc strSearch = \ "<LDAP://%s>;(primaryGroupID=%d);name;subtree" % \ (searchRoot, token) objRecordSet = self.objConnection.Execute(strSearch)[0] memberList = [] # Process if accounts are found. if objRecordSet.RecordCount > 0: memberList.append("Primary Group calculated:") objRecordSet.MoveFirst() while not objRecordSet.EOF: memberList.append("%s%s" % (header, objRecordSet.Fields[0].Value)) objRecordSet.MoveNext() # Return the list of results return memberList
if __name__ == '__main__': import sys server = None if len(sys.argv) == 1 else sys.argv[1] ad = ActiveDirectory(server) # for getting groups in the active directory: message = [] for group in ad.default_groups: objGrp = ad.get_group_info(group) if objGrp: message.append("\nMembers of %s:" % objGrp['name']) group_members = ad.get_group_members(objGrp['adspath']) for member in group_members: message.append("is_group: {}, name: {}".format(member['is_group'], member['name'])) message.extend(ad.get_primary_group(objGrp['primaryGroupToken'])) # for requesting user info, the attributes are the standard ones from the list. t = ad.get_member_info(member='<PID>', attributes=["objectGuid", "sAMAccountName", "memberOf", "displayName", "userPrincipalName", "proxyAddresses", "givenName", "sn", "initials", "pwdlastset", "userAccountControl", "mail", "distinguishedName", "objectclass", "employeeID", "employeeNumber", "employeeType", "title", "division", "department", "businessCategory", "l", "telephoneNumber", "physicalDeliveryOfficeName", "manager"]) print(t) print("\n".join(message))