def _paginate_scan_and_process(self, dn, filter, attributes, process_item, external_process, context): """ Retrieve every LDAP user and apply the 'process' on each entry Search is paginated to support more than 1000 entries :param process (function): the function to apply to each LDAP entry returned by the search :return: the list of the user names that have been processed """ cnx = self.get_ldap_connection() # Create the page control to work from page_control = SimplePagedResultsControl(True, size=1000, cookie='') result = [] pages = 0 processed_items=[] # Do searches until we run out of "pages" to get from # the LDAP server. while True: pages += 1 # Send search request try: response = cnx.search_ext(dn, ldap.SCOPE_ONELEVEL, filter, attrlist=attributes, serverctrls=[page_control]) except ldap.LDAPError as e: log.error('LDAP search failed: %s' % e) # Pull the results from the search request try: rtype, rdata, rmsgid, serverctrls = cnx.result3(response) except ldap.LDAPError as e: log.error('Could not pull LDAP results: %s' % e) # Each "rdata" is a tuple of the form (dn, attrs), where dn is # a string containing the DN (distinguished name) of the entry, # and attrs is a dictionary containing the attributes associated # with the entry. The keys of attrs are strings, and the associated # values are lists of strings. for item in rdata: processed_id = process_item(item, external_process, context) processed_items.append(processed_id) # Get cookie for next request result.extend(rdata) controls = [control for control in serverctrls if control.controlType == SimplePagedResultsControl.controlType] if not controls: print('The server ignores RFC 2696 control') break # Ok, we did find the page control, yank the cookie from it and # insert it into the control for our next search. If however there # is no cookie, we are done! page_control.cookie = controls[0].cookie if not controls[0].cookie: break return processed_items
def paged_search(self, base=None, scope=ldap.SCOPE_SUBTREE, page_size=1000, criticality=True, serverctrls=None, **search_args): cookie = '' criticality = criticality initial = True if serverctrls is None: serverctrls = [] else: serverctrls = list(serverctrls) if base is None: base = self._config(self.CFG_BASEDN) if base: page_control = SimplePagedResultsControl(criticality, page_size, cookie) while initial or page_control.cookie: initial = False try: msgid = self.search_ext( base, scope, serverctrls=(serverctrls + list([page_control])), **search_args) except ldap.LDAPError as error: raise error # (rtype, results, msgid, sent_serverctrls) (_, results, _, controls) = self.result3(msgid) for control in controls: if control.controlType == page_control.controlType: page_control.cookie = control.cookie yield results
def paged_search(self, base_dn, scope, search_filter, attr_list): if not self.conn: return None total_result = [] ctrl = SimplePagedResultsControl(True, size=LdapConn.PAGE_SIZE, cookie='') while True: try: result = self.conn.search_ext(base_dn, scope, search_filter, attr_list, serverctrls=[ctrl]) rtype, rdata, rmsgid, ctrls = self.conn.result3(result) except ldap.LDAPError as e: if type(e.message ) == dict and e.message['desc'] == 'No such object': pass else: logging.warning( 'Search failed for base dn(%s), filter(%s) ' 'on server %s error: %s' % (base_dn, search_filter, self.host, e.message)) return None total_result.extend(rdata) page_ctrls = [ c for c in ctrls if c.controlType == SimplePagedResultsControl.controlType ] if not page_ctrls or not page_ctrls[0].cookie: break ctrl.cookie = page_ctrls[0].cookie return total_result