(ldap_client, base_dn, explode_nested_groups)
Main worker function for the script.
Main worker function for the script.
Main worker function for the script .
def ldap_queries(ldap_client, base_dn, explode_nested_groups):
    """Main worker function for the script."""
    users_dictionary = {}
    groups_dictionary = {}
    computers_dictionary = {}
    group_id_to_dn_dictionary = {}

    # LDAP filters
    user_filter = '(objectcategory=user)'
    user_attributes = ['distinguishedName', 'sAMAccountName', 'userAccountControl', 'primaryGroupID', 'comment', 'description', 'homeDirectory', 'displayName', 'mail', 'pwdLastSet', 'lastLogon', 'profilePath', 'lockoutTime', 'scriptPath', 'userPassword']

    group_filter = '(objectcategory=group)'
    group_attributes = ['distinguishedName', 'sAMAccountName', 'member', 'primaryGroupToken']

    computer_filters = '(objectcategory=computer)'
    computer_attributes = ['distinguishedName', 'sAMAccountName', 'primaryGroupID', 'operatingSystem', 'operatingSystemHotfix', 'operatingSystemServicePack', 'operatingSystemVersion', 'servicePrincipalName']

    # LDAP queries
    logging.info('Querying users')
    users = query_ldap_with_paging(ldap_client, base_dn, user_filter, user_attributes, ADUser)
    logging.info('Querying groups')
    groups = query_ldap_with_paging(ldap_client, base_dn, group_filter, group_attributes, ADGroup)
    logging.info('Querying computers')
    computers = query_ldap_with_paging(ldap_client, base_dn, computer_filters, computer_attributes, ADComputer)

    # LDAP dictionaries
    logging.info('Building users dictionary')
    for element in users:
        users_dictionary[element.distinguished_name] = element

    logging.info('Building groups dictionary')
    for element in groups:
        group_id_to_dn_dictionary[element.primary_group_token] = element.distinguished_name
        groups_dictionary[element.distinguished_name] = element

    logging.info('Building computers dictionary')
    for element in computers:
        computers_dictionary[element.distinguished_name] = element

    # Loop through each group. If the membership is a range then query AD to get the full group membership
    logging.info('Exploding large groups')
    for group_key, group_object in groups_dictionary.items():
        if group_object.is_large_group:
            logging.debug('Getting full membership for [%s]', group_key)
            groups_dictionary[group_key].members = get_membership_with_ranges(ldap_client, base_dn, group_key)

    # Build group membership
    logging.info('Building group membership')
    logging.info('There is a total of [%i] groups', len(list(groups_dictionary.keys())))

    current_group_number = 0
    _output_dictionary = []
    for grp in list(groups_dictionary.keys()):
        current_group_number += 1
        _output_dictionary += process_group(users_dictionary, groups_dictionary, computers_dictionary, grp, explode_nested_groups, None, [])

        if current_group_number % 1000 == 0:
            logging.info('Processing group [%i]', current_group_number)

    # TODO: This could create output duplicates. It should be fixed at some point.
    # Add users if they have the group set as their primary ID as the group.
    # Additionally, add extended domain user information to a text file.
    user_information_filename = '{0} Extended Domain User Information.tsv'.format(args.filename_prepend).strip()
    with open(user_information_filename, 'w') as user_information_file:
        logging.info('Writing domain user information to [%s]', user_information_file.name)
        user_information_file.write('SAM Account Name\tStatus\tLocked Out\tUser Password\tDisplay Name\tEmail\tHome Directory\tProfile Path\tLogon Script Path\tPassword Last Set\tLast Logon\tUser Comment\tDescription\n')

        for user_object in list(users_dictionary.values()):
            if user_object.primary_group_id and user_object.primary_group_id in group_id_to_dn_dictionary:
                grp_dn = group_id_to_dn_dictionary[user_object.primary_group_id]

                temp_list_a = []
                temp_list_b = []

                temp_list_a.append(groups_dictionary[grp_dn].sam_account_name)
                temp_list_b.append(groups_dictionary[grp_dn].sam_account_name)
                temp_list_a.append(user_object.sam_account_name)
                temp_list_b.append(user_object.sam_account_name)
                temp_list_a.append(user_object.get_account_flags())
                temp_list_b.append(user_object.get_account_flags())
                temp_list_a.append(user_object.locked_out)
                temp_list_a.append(user_object.user_password)
                temp_list_a.append(user_object.display_name)
                temp_list_a.append(user_object.mail)
                temp_list_a.append(user_object.home_directory)
                temp_list_a.append(user_object.profile_path)
                temp_list_a.append(user_object.logon_script)
                temp_list_a.append(user_object.get_password_last_set_date())
                temp_list_a.append(user_object.get_last_logon_date())
                temp_list_a.append(user_object.comment)
                temp_list_a.append(user_object.description)
                _output_dictionary.append(temp_list_b)

                tmp_element = ""
                for x, binary_string in enumerate(temp_list_a[1:]):
                    binary_string = str(binary_string)
                    if binary_string[:2] == "b'":
                        binary_string = binary_string[2:]
                    if binary_string[-1:] == "'":
                        binary_string = binary_string[:-1]
                    if x == len(temp_list_a[1:])-1 :
                        tmp_element += binary_string + "\n"
                    else:
                        tmp_element += binary_string + "\t"
                
                user_information_file.write(tmp_element) #"\t".join(str(temp_list_a[1:])) + "\n")

    # Write Domain Computer Information
    computer_information_filename = '{0} Extended Domain Computer Information.tsv'.format(args.filename_prepend).strip()
    with open(computer_information_filename, 'w') as computer_information_file:
        logging.info('Writing domain computer information to [%s]', computer_information_file.name)
        computer_information_file.write('SAM Account Name\tOS\tOS Hotfix\tOS Service Pack\tOS VersiontSQL SPNs\tRA SPNS\tShare SPNs\tMail SPNs\tAuth SPNs\tBackup SPNs\tManagement SPNs\tOther SPNs\n')

        # TODO: This could create output duplicates. It should be fixed at some point.
        # Add computers if they have the group set as their primary ID as the group
        for computer_object in list(computers_dictionary.values()):
            if computer_object.primary_group_id:
                grp_dn = group_id_to_dn_dictionary[computer_object.primary_group_id]

                temp_list_a = []
                temp_list_b = []

                temp_list_a.append(groups_dictionary[grp_dn].sam_account_name)
                temp_list_a.append(computer_object.sam_account_name)

                temp_list_b.append(computer_object.sam_account_name)
                temp_list_b.append(computer_object.operating_system)
                temp_list_b.append(computer_object.operating_system_hotfix)
                temp_list_b.append(computer_object.operating_system_service_pack)
                temp_list_b.append(computer_object.operating_system_version)
                [temp_list_b.append(','.join(map(str, item))) for item in parse_spns(computer_object.service_principal_names)]

                tmp_element = ""
                for x, binary_string in enumerate(temp_list_b):
                    binary_string = str(binary_string)
                    if binary_string[:2] == "b'":
                        binary_string = binary_string[2:]
                    if binary_string[-1:] == "'":
                        binary_string = binary_string[:-1]
                    if x == len(temp_list_b)-1 :
                        tmp_element += binary_string + "\n"
                    else:
                        tmp_element += binary_string + "\t"
                computer_information_file.write(tmp_element)
                _output_dictionary.append(temp_list_a)

    # Write Group Memberships
    group_membership_filename = '{0} Domain Group Membership.tsv'.format(args.filename_prepend).strip()
    with open(group_membership_filename, 'w') as group_membership_file:
        logging.info('Writing membership information to [%s]', group_membership_file.name)
        group_membership_file.write('Group Name\tSAM Account Name\tStatus\n')

        for element in _output_dictionary:
            tmp_element = ""
            for x, binary_string in enumerate(element):
                binary_string = str(binary_string)
                if binary_string[:2] == "b'":
                    binary_string = binary_string[2:]
                if binary_string[-1:] == "'":
                    binary_string = binary_string[:-1]
                if x == len(element)-1 :
                    tmp_element += binary_string + "\n"
                else:
                    tmp_element += binary_string + "\t"
                
            group_membership_file.write(tmp_element)
def ldap_queries ( ldap_client , base_dn , explode_nested_groups ) : users_dictionary = { } groups_dictionary = { } computers_dictionary = { } group_id_to_dn_dictionary = { } # LDAP filters user_filter = '(objectcategory=user)' user_attributes = [ 'distinguishedName' , 'sAMAccountName' , 'userAccountControl' , 'primaryGroupID' , 'comment' , 'description' , 'homeDirectory' , 'displayName' , 'mail' , 'pwdLastSet' , 'lastLogon' , 'profilePath' , 'lockoutTime' , 'scriptPath' , 'userPassword' ] group_filter = '(objectcategory=group)' group_attributes = [ 'distinguishedName' , 'sAMAccountName' , 'member' , 'primaryGroupToken' ] computer_filters = '(objectcategory=computer)' computer_attributes = [ 'distinguishedName' , 'sAMAccountName' , 'primaryGroupID' , 'operatingSystem' , 'operatingSystemHotfix' , 'operatingSystemServicePack' , 'operatingSystemVersion' , 'servicePrincipalName' ] # LDAP queries logging . info ( 'Querying users' ) users = query_ldap_with_paging ( ldap_client , base_dn , user_filter , user_attributes , ADUser ) logging . info ( 'Querying groups' ) groups = query_ldap_with_paging ( ldap_client , base_dn , group_filter , group_attributes , ADGroup ) logging . info ( 'Querying computers' ) computers = query_ldap_with_paging ( ldap_client , base_dn , computer_filters , computer_attributes , ADComputer ) # LDAP dictionaries logging . info ( 'Building users dictionary' ) for element in users : users_dictionary [ element . distinguished_name ] = element logging . info ( 'Building groups dictionary' ) for element in groups : group_id_to_dn_dictionary [ element . primary_group_token ] = element . distinguished_name groups_dictionary [ element . distinguished_name ] = element logging . info ( 'Building computers dictionary' ) for element in computers : computers_dictionary [ element . distinguished_name ] = element # Loop through each group. If the membership is a range then query AD to get the full group membership logging . info ( 'Exploding large groups' ) for group_key , group_object in groups_dictionary . items ( ) : if group_object . is_large_group : logging . debug ( 'Getting full membership for [%s]' , group_key ) groups_dictionary [ group_key ] . members = get_membership_with_ranges ( ldap_client , base_dn , group_key ) # Build group membership logging . info ( 'Building group membership' ) logging . info ( 'There is a total of [%i] groups' , len ( list ( groups_dictionary . keys ( ) ) ) ) current_group_number = 0 _output_dictionary = [ ] for grp in list ( groups_dictionary . keys ( ) ) : current_group_number += 1 _output_dictionary += process_group ( users_dictionary , groups_dictionary , computers_dictionary , grp , explode_nested_groups , None , [ ] ) if current_group_number % 1000 == 0 : logging . info ( 'Processing group [%i]' , current_group_number ) # TODO: This could create output duplicates. It should be fixed at some point. # Add users if they have the group set as their primary ID as the group. # Additionally, add extended domain user information to a text file. user_information_filename = '{0} Extended Domain User Information.tsv' . format ( args . filename_prepend ) . strip ( ) with open ( user_information_filename , 'w' ) as user_information_file : logging . info ( 'Writing domain user information to [%s]' , user_information_file . name ) user_information_file . write ( 'SAM Account Name\tStatus\tLocked Out\tUser Password\tDisplay Name\tEmail\tHome Directory\tProfile Path\tLogon Script Path\tPassword Last Set\tLast Logon\tUser Comment\tDescription\n' ) for user_object in list ( users_dictionary . values ( ) ) : if user_object . primary_group_id and user_object . primary_group_id in group_id_to_dn_dictionary : grp_dn = group_id_to_dn_dictionary [ user_object . primary_group_id ] temp_list_a = [ ] temp_list_b = [ ] temp_list_a . append ( groups_dictionary [ grp_dn ] . sam_account_name ) temp_list_b . append ( groups_dictionary [ grp_dn ] . sam_account_name ) temp_list_a . append ( user_object . sam_account_name ) temp_list_b . append ( user_object . sam_account_name ) temp_list_a . append ( user_object . get_account_flags ( ) ) temp_list_b . append ( user_object . get_account_flags ( ) ) temp_list_a . append ( user_object . locked_out ) temp_list_a . append ( user_object . user_password ) temp_list_a . append ( user_object . display_name ) temp_list_a . append ( user_object . mail ) temp_list_a . append ( user_object . home_directory ) temp_list_a . append ( user_object . profile_path ) temp_list_a . append ( user_object . logon_script ) temp_list_a . append ( user_object . get_password_last_set_date ( ) ) temp_list_a . append ( user_object . get_last_logon_date ( ) ) temp_list_a . append ( user_object . comment ) temp_list_a . append ( user_object . description ) _output_dictionary . append ( temp_list_b ) tmp_element = "" for x , binary_string in enumerate ( temp_list_a [ 1 : ] ) : binary_string = str ( binary_string ) if binary_string [ : 2 ] == "b'" : binary_string = binary_string [ 2 : ] if binary_string [ - 1 : ] == "'" : binary_string = binary_string [ : - 1 ] if x == len ( temp_list_a [ 1 : ] ) - 1 : tmp_element += binary_string + "\n" else : tmp_element += binary_string + "\t" user_information_file . write ( tmp_element ) #"\t".join(str(temp_list_a[1:])) + "\n") # Write Domain Computer Information computer_information_filename = '{0} Extended Domain Computer Information.tsv' . format ( args . filename_prepend ) . strip ( ) with open ( computer_information_filename , 'w' ) as computer_information_file : logging . info ( 'Writing domain computer information to [%s]' , computer_information_file . name ) computer_information_file . write ( 'SAM Account Name\tOS\tOS Hotfix\tOS Service Pack\tOS VersiontSQL SPNs\tRA SPNS\tShare SPNs\tMail SPNs\tAuth SPNs\tBackup SPNs\tManagement SPNs\tOther SPNs\n' ) # TODO: This could create output duplicates. It should be fixed at some point. # Add computers if they have the group set as their primary ID as the group for computer_object in list ( computers_dictionary . values ( ) ) : if computer_object . primary_group_id : grp_dn = group_id_to_dn_dictionary [ computer_object . primary_group_id ] temp_list_a = [ ] temp_list_b = [ ] temp_list_a . append ( groups_dictionary [ grp_dn ] . sam_account_name ) temp_list_a . append ( computer_object . sam_account_name ) temp_list_b . append ( computer_object . sam_account_name ) temp_list_b . append ( computer_object . operating_system ) temp_list_b . append ( computer_object . operating_system_hotfix ) temp_list_b . append ( computer_object . operating_system_service_pack ) temp_list_b . append ( computer_object . operating_system_version ) [ temp_list_b . append ( ',' . join ( map ( str , item ) ) ) for item in parse_spns ( computer_object . service_principal_names ) ] tmp_element = "" for x , binary_string in enumerate ( temp_list_b ) : binary_string = str ( binary_string ) if binary_string [ : 2 ] == "b'" : binary_string = binary_string [ 2 : ] if binary_string [ - 1 : ] == "'" : binary_string = binary_string [ : - 1 ] if x == len ( temp_list_b ) - 1 : tmp_element += binary_string + "\n" else : tmp_element += binary_string + "\t" computer_information_file . write ( tmp_element ) _output_dictionary . append ( temp_list_a ) # Write Group Memberships group_membership_filename = '{0} Domain Group Membership.tsv' . format ( args . filename_prepend ) . strip ( ) with open ( group_membership_filename , 'w' ) as group_membership_file : logging . info ( 'Writing membership information to [%s]' , group_membership_file . name ) group_membership_file . write ( 'Group Name\tSAM Account Name\tStatus\n' ) for element in _output_dictionary : tmp_element = "" for x , binary_string in enumerate ( element ) : binary_string = str ( binary_string ) if binary_string [ : 2 ] == "b'" : binary_string = binary_string [ 2 : ] if binary_string [ - 1 : ] == "'" : binary_string = binary_string [ : - 1 ] if x == len ( element ) - 1 : tmp_element += binary_string + "\n" else : tmp_element += binary_string + "\t" group_membership_file . write ( tmp_element )