def build_dn_list(self, rdns, base, data, FixedRDN): fix = rdns[0] var = rdns[1:] if len(rdns) > 1 else [] dns = [fix] # Check if we've have to use a fixed RDN. if FixedRDN: return["%s,%s" % (FixedRDN, base)] # Bail out if fix part is not in data if not fix in data: raise DNGeneratorError(C.make_error("ATTRIBUTE_NOT_FOUND", attribute=fix)) # Append possible variations of RDN attributes if var: for rdn in permutations(var + [None] * (len(var) - 1), len(var)): dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn))))) dns = list(set(dns)) # Assemble DN of RDN combinations dn_list = [] for t in [tuple(d.split(",")) for d in dns]: ndn = [] for k in t: ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0]))) dn_list.append("+".join(ndn) + "," + base) return sorted(dn_list, key=len)
def execute(self, connection, filterargs=()): """ Executes the search on the given connection (an LDAPObject). filterargs is an object that will be used for expansion of the filter string. The python-ldap library returns utf8-encoded strings. For the sake of sanity, this method will decode all result strings and return them as Unicode. """ try: filterstr = self.filterstr % filterargs results = connection.search_s(self.base_dn.encode('utf-8'), self.scope, filterstr.encode('utf-8')) # There's been a report of an LDAP server returning extraneous # entries with DNs of None. This will filter them out. results = filter(lambda r: r[0] is not None, results) results = _DeepStringCoder('utf-8').decode(results) result_dns = [result[0] for result in results] logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" % (self.base_dn, self.scope, filterstr, len(result_dns), "; ".join(result_dns))) except self.ldap.LDAPError, e: results = [] logger.error(u"search_s('%s', %d, '%s') raised %s" % (self.base_dn, self.scope, filterstr, pprint.pformat(e)))
def dn_groups(conn: ldap.ldapobject.SimpleLDAPObject, dn: str, domain: str) -> List[str]: """ Request group names from active directory by user DN 2020-04-15 :param conn: established connection to domain controller :type conn: ldap.ldapobject.SimpleLDAPObject :param dn: an active directory user DN :type dn: str :param domain: full name of active directory domain :type domain: str :return: list of group names whose user with DN is member of (SUCCESS), empty list otherwise :rtype: List[str] """ if not conn: return [] ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.')) search_filter: str = '(|(&(objectClass=group)(member=%s)))' % ldap.filter.escape_filter_chars( dn) try: results: List[str] = list( filter( lambda x: x[0] is not None, conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter, ['sAMAccountName']))) return [item[1]['sAMAccountName'][0].decode() for item in results] except ldap.OPERATIONS_ERROR: return []
def user_dn(conn: ldap.ldapobject.SimpleLDAPObject, username: str, domain: str) -> str: """ Requests user DN from active directory by username :param conn: established connection to domain controller :type conn: ldap.ldapobject.SimpleLDAPObject :param username: an active directory username :type username: str :return: DN for username if success, empty string otherwise :param domain: full name of active directory domain :type domain: str :rtype: str """ if not conn: return '' ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.')) search_filter: str = '(|(&(objectClass=person)(sAMAccountName=%s)))' % ad_clear_username( username) try: results: List[str] = list( filter( lambda x: x[0] is not None, conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter, ['']))) if not len(results): return '' return results[0][0] except ldap.OPERATIONS_ERROR: return ''
def parse_ldap_base(ldap_conf): """Parse LDAP base from ldap.conf(5).""" # pylint: disable-msg=W0141 ldap_conf = open(ldap_conf, 'rb') pattern = re.compile(r'''^\s*[bB][aA][sS][eE]\s+(.+)\s*$''') matches = [pattern.search(x) for x in ldap_conf.readlines()] base = filter(None, matches)[0].group(1) return base
def _process_results(self, results): """ Returns a sanitized copy of raw LDAP results. This scrubs out references, decodes utf8, etc. """ results = filter(lambda r: r[0] is not None, results) results = _DeepStringCoder('utf-8').decode(results) result_dns = [result[0] for result in results] logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" % (self.base_dn, self.scope, self.filterstr, len(result_dns), "; ".join(result_dns))) return results
def dn_groups(conn: ldap.ldapobject.SimpleLDAPObject, dn: str, domain: str) -> List[str]: """ Request group names from active directory by user DN :param conn: established connection to domain controller :type conn: ldap.ldapobject.SimpleLDAPObject :param dn: an active directory user DN :type dn: str :param domain: full name of active directory domain :type domain: str :return: list of group names whose user with DN is member of (SUCCESS), empty list otherwise :rtype: List[str] """ if not conn: logger.error( f'django_adtool.ad.ad_tools dn_groups failed. "conn" is null. dn={dn}, domain={domain}' ) return [] ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.')) search_filter: str = '(|(&(objectClass=group)(member=%s)))' % ldap.filter.escape_filter_chars( dn) try: results: LdapSearchResult = list( filter( lambda x: x[0] is not None, conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter, ['sAMAccountName']))) if not results: logger.error( f'{__package__} dn_group failed. results is empty, dn={dn}, domain={domain}' ) return [item[1]['sAMAccountName'][0].decode() for item in results] except ldap.OPERATIONS_ERROR as e: logger.error( f'{__package__} dn_group failed: {str(e)}, dn={dn}, domain={domain}' ) return []
def build_dn_list(self, rdns, base, data): fix = rdns[0] var = rdns[1:] if len(rdns) > 1 else [] dns = [fix] # Bail out if fix part is not in data if not fix in data: raise DNGeneratorError("fix attribute '%s' is not in the entry" % fix) # Append possible variations of RDN attributes if var: for rdn in permutations(var + [None] * (len(var) - 1), len(var)): dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn))))) dns = list(set(dns)) # Assemble DN of RDN combinations dn_list = [] for t in [tuple(d.split(",")) for d in dns]: ndn = [] for k in t: ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0]))) dn_list.append("+".join(ndn) + "," + base) return sorted(dn_list, key=len)
def _college_group_names(self): return filter(College.is_valid_college_name, self._groups)
def _team_group_names(self): return filter(Team.valid_team_name, self._groups)
def getBootParams(self, address): #syslog.syslog(syslog.LOG_DEBUG, "Searching for {address}".format(address=address)) with self.ldap.get_handle() as conn: res = conn.search_s( self.ldap.get_base(), ldap.SCOPE_SUBTREE, ldap.filter.filter_format("(&(macAddress=%s)(objectClass=FAIobject))", [address]), ['FAIstate', 'gotoBootKernel', 'gotoKernelParameters', 'gotoLdapServer', 'cn', 'ipHostNumber']) if res is not None: count = len(res) if count > 1: syslog.syslog("[fai] ignoring %s - LDAP search is not unique (%d entries match)" % (address, res.count())) return None if count == 1: dn, attributes = res[0] hostname = attributes.get('cn', [''])[0] status = attributes.get('FAIstate', [''])[0] if not status: if self.default_init == 'fallback': syslog.syslog(syslog.LOG_DEBUG, "[fai] No FAI Status for {hostname} - continue PXE boot".format(hostname=hostname)) return None else: status = self.default_init syslog.syslog(syslog.LOG_DEBUG, "[fai] Found {hostname}, FAI Status is '{status}'".format(hostname=hostname, status=status)) kernel = attributes.get('gotoBootKernel', [''])[0] ldap_server = attributes.get('gotoLdapServer', [''])[0] cmdline = attributes.get('gotoKernelParameters', [''])[0] if not kernel or not ldap_server or not cmdline: # Check group membership member_res = conn.search_s( self.ldap.get_base(), ldap.SCOPE_SUBTREE, ldap.filter.filter_format("(&(member=%s)(objectClass=gosaGroupOfNames)(gosaGroupObjects=[W]))", [dn]), ['FAIstate', 'gotoBootKernel', 'gotoKernelParameters', 'gotoLdapServer', 'cn', 'ipHostNumber']) if member_res is not None: group_count = len(member_res) if group_count > 1: syslog.syslog(syslog.LOG_ERR, "[fai] Found more than one group for host {hostname}!") return None if group_count == 1: group_dn, group_attributes = member_res[0] if not kernel: kernel = group_attributes.get('gotoBootKernel', [''])[0] if not ldap_server: ldap_server = group_attributes.get('gotoLdapServer', [''])[0] if not cmdline: cmdline = group_attributes.get('gotoKernelParameters', [''])[0] if group_count == 0: syslog.syslog(syslog.LOG_INFO, "[fai] {hostname} - no group membership found - aborting".format(hostname=hostname)) if not kernel or not ldap_server: line = "[fai] {hostname} - missing attribute(s) -".format(hostname=hostname) if not kernel: line = line + " gotoBootKernel" if not ldap_server: line = line + " gotoLdapServer" syslog.syslog(syslog.LOG_ERR, line) return None # Strip ldap parameter and all multiple and trailing spaces cmdline = re.sub(r'ldap(=[^\s]*[\s]*|[\s]*$|\s+)', '', cmdline) cmdline = re.sub(r'\s[\s]+', '', cmdline.strip()) # Get kernel and initrd from TFTP root kernel='vmlinuz-install' initrd='initrd.img-install' # - guess filename for kernel if not os.access(self.tftp_root + os.sep + kernel, os.F_OK): syslog.syslog(syslog.LOG_ERR, "[fai] {hostname} - specified kernel {kernel} does not exist!".format(hostname=hostname, kernel=kernel)) return None # - try to find the initrd path = self.tftp_root + os.sep + initrd if os.access(path, os.F_OK): cmdline = cmdline + " initrd={initrd}".format(initrd=initrd) cmdline = cmdline.strip() # Add NFS options cmdline = cmdline + " nfsroot=" + self.nfs_root cmdline = cmdline.strip() # Add FAI options if status in ['install', 'install-init']: cmdline = cmdline + " FAI_ACTION=install FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=self.fai_flags) \ + " devfs=nomount root=/dev/nfs boot=live union={union}".format(union=self.union) elif status.startswith('error:') or status.startswith('installing:'): faierror = "" if status.startswith("installing:"): faierror = "inst-" faierror = faierror + status.split(":", 1)[1] cmdline = cmdline + " FAI_ACTION=install FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=self.fai_flags) \ + " devfs=nomount root=/dev/nfs boot=live union={union} faierror:{faierror}".format(union=self.union, faierror=faierror) elif status in ['softupdate', 'localboot']: kernel = 'localboot' elif status == 'sysinfo': sysflags = ','.join(filter(lambda x: x.strip() != "reboot", self.fai_flags.split(','))) cmdline = cmdline + " FAI_ACTION=sysinfo FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=sysflags) \ + " devfs=nomount root=/dev/nfs boot=live union={union}".format(union=self.union) else: # Unknown status syslog.syslog(syslog.LOG_ERR, "[fai] {hostname} - unknown FAIstate: {status}".format(hostname=hostname, status=status)) return None return self.make_pxe_entry(kernel, cmdline, label="FAI - powered by FTS") return None