Beispiel #1
0
    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)))
Beispiel #2
0
    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)
Beispiel #3
0
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
Beispiel #4
0
    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
Beispiel #5
0
    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)
Beispiel #6
0
    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
Beispiel #7
0
 def _college_group_names(self):
     return filter(College.is_valid_college_name, self._groups)
Beispiel #8
0
 def _team_group_names(self):
     return filter(Team.valid_team_name, self._groups)