def load_category(self, category, nicks=None): '''Loads the designated key directories @param category: string @param nicks: list of string nick ids to load @return Seeds class object ''' seeds = Seeds(config=self.config) if category == 'sign': catdir = self.config.get_key('sign-keydir') else: keyrings = self.config.get_key('keyring') catdir = os.path.join(keyrings, category) self.logger.debug("SeedHandler: load_category; catdir = %s" % catdir) try: if not nicks: nicks = os.listdir(catdir) for nick in nicks: seed_path = os.path.join(catdir, nick) gkey_path = os.path.join(seed_path, 'gkey.seeds') seed = None try: with open(gkey_path, 'r') as fileseed: seed = load(fileseed) except IOError as error: self.logger.debug("SeedHandler: load_category; IOError loading seed file %s." % gkey_path) self.logger.debug("Error was: %s" % str(error)) if seed: for nick in sorted(seed): key = seed[nick] seeds.add(nick, GKEY(**key)) except OSError as error: self.logger.debug("SeedHandler: load_category; OSError for %s" % catdir) self.logger.debug("Error was: %s" % str(error)) return seeds
def load_category(self, category, nicks=None, refresh=False): '''Loads the designated key directories @param category: string @param nicks: list of string nick ids to load @return Seeds class object ''' seeds = Seeds(config=self.config, _logger=self.logger) if category == 'sign': catdir = self.config.get_key('sign-keydir') else: keyrings = self.config.get_key('keyring') catdir = os.path.join(keyrings, category) self.logger.debug("SeedHandler: load_category; catdir = %s" % catdir) try: if not nicks: nicks = os.listdir(catdir) for nick in nicks: seed_path = os.path.join(catdir, nick) if not os.path.isdir(seed_path): continue gkey_path = os.path.join(seed_path, 'gkey.seeds') seed = None try: with open(gkey_path, 'r') as fileseed: seed = load(fileseed) except IOError as error: self.logger.debug("SeedHandler: load_category; IOError loading seed file %s." % gkey_path) self.logger.debug("Error was: %s" % str(error)) if seed: for nick in sorted(seed): key = seed[nick] # GKEY class change auto-update if not 'uid' in list(key): if not refresh: raise UpdateDbError(category) key['uid'] = [] if not 'keys' in list(key): if not refresh: raise UpdateDbError(category) key['keys'] = key['fingerprint'][:] seeds.add(nick, GKEY(**key)) except OSError as error: self.logger.debug("SeedHandler: load_category; OSError for %s" % catdir) self.logger.exception("Error was: %s" % str(error)) self.seeds = seeds return seeds
class Actions(object): def __init__(self, config, output=None, logger=None): self.config = config self.output = output self.logger = logger self.seeds = None self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}') def ldapsearch(self, args): l = LdapSearch() self.logger.debug("MAIN: _action_ldapsearch; args = %s" % str(args)) self.output("Search... Establishing connection\n") if not l.status: self.output("Aborting Search... Connection failed") return False attr, target, search_field = self.get_args(args) results = l.search(target, search_field) devs = l.result2dict(results, gkey2ldap[attr]) for dev in sorted(devs): self.output(dev, devs[dev]) self.output("============================================") self.output("Total number of developers in results:", len(devs)) self.logger.info("============================================") self.logger.info("Total number of developers in results: %d" % len(devs)) return True def updateseeds(self, args): l = LdapSearch() self.logger.debug("MAIN: _action_updateseeds; args = %s" % str(args)) self.output("Search... Establishing connection") if not l.status: self.output("Aborting update... Connection failed") return False results = l.search('*', UID) info = l.result2dict(results, 'uid') self.logger.debug( "MAIN: _action_updateseeds; got results :) converted to info") filename = self.config['dev-seedfile'] + '.new' if not self.create_seedfile(info, filename): self.logger.error("Developer seed file update failure: " "Original seed file is intact & untouched.") self.output("Backing up existing file...") status = updatefiles(self.config, self.logger) if not status: self.output("Develope seed failed to update!") return False self.output("Developer seed file updated!") return True def create_seedfile(self, devs, filename): self.output("Creating seeds from LDAP data...") self.seeds = Seeds(filename) count = 0 error_count = 0 for dev in sorted(devs): if devs[dev]['gentooStatus'][0] not in ['active']: continue #self.logger.debug("create_seedfile, dev = " # "%s, %s" % (str(dev), str(devs[dev]))) developer_attrs = self.build_gkey(devs[dev]) if developer_attrs: self.seeds.add(dev, developer_attrs) count += 1 else: error_count += 1 self.output("Total number of seeds created:", count) self.output("Seeds created... Saving file: %s" % filename) self.output("Total number of Dev's with GPG errors:", error_count) self.logger.info("Total number of seeds created: %d" % count) self.logger.info("Seeds created... Saving file: %s" % filename) self.logger.info("Total number of Dev's with GPG errors: %d" % error_count) return self.seeds.save() @staticmethod def get_args(args): for attr in ['nick', 'name', 'gpgkey', 'fingerprint', 'status']: if attr: target = getattr(args, attr) search_field = gkey2SEARCH[attr] break return (attr, target, search_field) def build_gkey(self, info): keyinfo = defaultdict() keyid_missing = False # self.logger.debug("Actions: build_gkeylist; info = %s" % str(info)) for attr in gkey2ldap: field = gkey2ldap[attr] if not field: keyinfo[attr] = None continue try: keyinfo[attr], keyid_found, is_good = self._fix_bad_ldap(info, attr, field) except KeyError: self.logger.debug('LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.debug(' MISSING or EMPTY LDAP field ' + '[%s] GPGKey field [%s]' % (field, attr)) if attr in ['keyid', 'longkeyid']: keyid_missing = True else: is_good = False keyinfo[attr] = None if not keyid_found and keyid_missing: keyinfo, is_good = self._check_bad_fingerprint(info, keyinfo) if is_good: if keyinfo['fingerprint']: # fingerprints exist check is_ok = self._check_fingerprint_integrity(info, keyinfo) is_match = self._check_id_fingerprint_match(info, keyinfo) if not is_ok or not is_match: is_good = False if is_good: # drop keyid and longkeyid keyinfo.pop('keyid', None) keyinfo.pop('longkeyid', None) return keyinfo return None def _fix_bad_ldap(self, info, attr, field): '''Fix bad LDAP values @param info: dictionary with raw LDAP attributes and values @param attr: string key for new Gentoo Keys attributes @param field: string key for LDAP attributes ''' is_good = True keyid_found = False values = info[field] # strip errant line feeds values = [y.strip('\n') for y in values] # separate out short/long key id's if values and attr in ['keyid', 'longkeyid']: if len(get_key_ids(attr, values)): keyid_found = True elif values and attr in ['fingerprint']: values = [v.replace(' ', '') for v in values] if 'undefined' in values: self.logger.error('ERROR in LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' %s = "undefined"' % (field)) is_good = False return (values, keyid_found, is_good) def _check_bad_fingerprint(self, info, keyinfo): '''Check and fix bad fingerprints and keyids @param info: dictionary with raw LDAP attributes @param keyinfo: dictionary with new Gentoo Keys attributes ''' is_good = True fingerprint = None try: fingerprint = info[gkey2ldap['fingerprint']] self.logger.debug(' Generate gpgkey, Found LDAP fingerprint field') except KeyError: gpgkey = 'Missing fingerprint from LDAP info' self.logger.debug(' Generate gpgkey, LDAP fingerprint KeyError') if fingerprint: values = [y.strip('\n') for y in fingerprint] values = [v.replace(' ', '') for v in values] # assign it to gpgkey to prevent a possible # "gpgkey" undefined error gpgkey = ['0x' + x[-16:] for x in values] keyinfo['longkeyid'] = gpgkey self.logger.debug(' Generate gpgkey, NEW keyinfo[\'fingerprint\'] = %s' % str(keyinfo['longkeyid'])) else: gpgkey = 'Missing or Bad fingerprint from LDAP info' is_good = False if not keyinfo['longkeyid']: self.logger.error('ERROR in ldap info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' A valid keyid, longkeyid or fingerprint ' 'was not found for %s : gpgkey = %s' % (info['cn'][0], gpgkey)) is_good = False return (keyinfo, is_good) def _check_id_fingerprint_match(self, info, keyinfo): # assume it's good until found an error is found is_good = True for attr in ['keyid', 'longkeyid']: # skip blank id field if not keyinfo[attr]: continue for y in keyinfo[attr]: index = len(y.lstrip('0x')) if y.lstrip('0x').upper() not in \ [x[-index:].upper() for x in keyinfo['fingerprint']]: self.logger.error('ERROR in LDAP info for: %s, %s' %(info['uid'][0], info['cn'][0])) self.logger.error(' ' + str(keyinfo)) self.logger.error(' GPGKey id %s not found in the ' % y.lstrip('0x') + 'listed fingerprint(s)') is_good = False return is_good def _check_fingerprint_integrity(self, info, keyinfo): # assume it's good until found an error is found is_good = True for fingerprint in keyinfo['fingerprint']: # check fingerprint integrity if len(fingerprint) != 40: self.logger.error('ERROR in LDAP info for: %s, %s' %(info['uid'][0], info['cn'][0])) self.logger.error(' GPGKey incorrect fingerprint ' + 'length (%s) for fingerprint: %s' %(len(fingerprint), fingerprint)) is_good = False continue if not self.fingerprint_re.match(fingerprint): self.logger.error('ERROR in LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' GPGKey: Non hexadecimal digits in ' + 'fingerprint for fingerprint: ' + fingerprint) is_good = False return is_good
class Actions(object): def __init__(self, config, output=None, logger=None): self.config = config self.output = output self.logger = logger self.seeds = None self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}') def ldapsearch(self, args): '''Performs a search in LDAP for the input arguments''' l = LdapSearch(logger=self.logger) self.logger.debug("MAIN: _action_ldapsearch; args = %s" % str(args)) self.output('', "Search... Establishing connection\n") if not l.status: self.output('', "Aborting Search... Connection failed") return False attr, target, search_field = self.get_args(args) results = l.search(target, search_field) devs = l.result2dict(results, gkey2ldap[attr]) for dev in sorted(devs): self.output('', dev, devs[dev]) self.output('', "============================================") self.output('', "Total number of developers in results:", len(devs)) self.logger.info("============================================") self.logger.info("Total number of developers in results: %d" % len(devs)) return (True, ['Completed']) def updateseeds(self, args): '''Performs a search for all active developers and generates a new seeds file''' l = LdapSearch(logger=self.logger) self.logger.debug("MAIN: _action_updateseeds; args = %s" % str(args)) self.output('', "Search... Establishing connection") if not l.status: self.output('', "Aborting update... Connection failed") return False results = l.search('*', UID) info = l.result2dict(results, 'uid') self.logger.debug( "MAIN: _action_updateseeds; got results :) converted to info") if args.category: filename = self.config.get_key('seeds', args.category) + '.new' if not self.create_seedfile(info, filename): self.logger.error("Developer seed file update failure: " "Original seed file is intact & untouched.") self.output('', "Backing up existing file...") status = updatefiles(self.config, self.logger, args.category) if not status: self.output('', "Develope seed failed to update!") return False self.output('', "Developer seed file updated!") return (True, ['Completed']) def create_seedfile(self, devs, filename): self.output('', "Creating seeds from LDAP data...") self.seeds = Seeds(filename, self.config, self.logger) count = 0 error_count = 0 for dev in sorted(devs): if devs[dev]['gentooStatus'][0] not in ['active']: continue #self.logger.debug("create_seedfile, dev = " # "%s, %s" % (str(dev), str(devs[dev]))) developer_attrs = self.build_gkey(devs[dev]) if developer_attrs: self.seeds.add(dev, developer_attrs) count += 1 else: error_count += 1 self.output('', "Total number of seeds created........: %s" % count) self.output('', "Seeds created... Saving file.........: %s" % filename) self.output('', "Total number of Dev's with GPG errors: %s" % error_count) self.logger.info("Total number of seeds created........: %d" % count) self.logger.info("Seeds created... Saving file.........: %s" % filename) self.logger.info("Total number of Dev's with GPG errors: %d" % error_count) return self.seeds.save() @staticmethod def get_args(args): for attr in ['nick', 'name', 'fingerprint', 'status']: if attr: target = getattr(args, attr) search_field = gkey2SEARCH[attr] break return (attr, target, search_field) def build_gkey(self, info): keyinfo = defaultdict() keyid_missing = False # self.logger.debug("Actions: build_gkeylist; info = %s" % str(info)) for attr, field in list(gkey2ldap.items()): try: keyinfo[attr], keyid_found, is_good = self._fix_bad_ldap( info, attr, field) except KeyError: self.logger.debug('LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.debug(' MISSING or EMPTY LDAP field ' + '[%s] GPGKey field [%s]' % (field, attr)) if attr in ['fingerprint']: keyid_missing = True else: is_good = False keyinfo[attr] = None if not keyid_found and keyid_missing: keyinfo, is_good = self._check_bad_fingerprint(info, keyinfo) if is_good: if keyinfo['fingerprint']: # fingerprints exist check is_ok = self._check_fingerprint_integrity(info, keyinfo) if not is_ok: is_good = False if is_good: # some developers add lowercase fingerprints keyinfo['fingerprint'] = [ key.upper() for key in keyinfo['fingerprint'] ] keyinfo['keys'] = keyinfo['fingerprint'] keyinfo['uid'] = [ "%s <*****@*****.**>" % (info['cn'][0], info['uid'][0]) ] return keyinfo return None def _fix_bad_ldap(self, info, attr, field): '''Fix bad LDAP values @param info: dictionary with raw LDAP attributes and values @param attr: string key for new Gentoo Keys attributes @param field: string key for LDAP attributes ''' is_good = True keyid_found = False values = info[field] # strip errant line feeds values = [y.strip('\n') for y in values] if values and attr in ['fingerprint']: values = [v.replace(' ', '') for v in values] if 'undefined' in values and attr not in ['keyid', 'longkeyid']: self.logger.error('ERROR in LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' %s = "undefined"' % (field)) is_good = False if values and attr in ['nick', 'name', 'keydir']: values = "".join(values) return (values, keyid_found, is_good) def _check_bad_fingerprint(self, info, keyinfo): '''Check and fix bad fingerprints and keyids @param info: dictionary with raw LDAP attributes @param keyinfo: dictionary with new Gentoo Keys attributes ''' is_good = True fingerprint = None try: fingerprint = info[gkey2ldap['fingerprint']] self.logger.debug( ' Generate gpgkey, Found LDAP fingerprint field') except KeyError: gpgkey = 'Missing fingerprint from LDAP info' self.logger.debug(' Generate gpgkey, LDAP fingerprint KeyError') if fingerprint: values = [y.strip('\n') for y in fingerprint] values = [v.replace(' ', '') for v in values] # assign it to gpgkey to prevent a possible # "gpgkey" undefined error gpgkey = ['0x' + x[-16:] for x in values] keyinfo['longkeyid'] = gpgkey self.logger.debug( ' Generate gpgkey, NEW keyinfo[\'fingerprint\'] = %s' % str(keyinfo['longkeyid'])) else: gpgkey = 'Missing or Bad fingerprint from LDAP info' is_good = False return (keyinfo, is_good) def _check_fingerprint_integrity(self, info, keyinfo): # assume it's good until found an error is found is_good = True for fingerprint in keyinfo['fingerprint']: # check fingerprint integrity if len(fingerprint) != 40: self.logger.error('ERROR in LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' GPGKey incorrect fingerprint ' + 'length (%s) for fingerprint: %s' % (len(fingerprint), fingerprint)) is_good = False continue if not self.fingerprint_re.match(fingerprint): self.logger.error('ERROR in LDAP info for: %s, %s' % (info['uid'][0], info['cn'][0])) self.logger.error(' GPGKey: Non hexadecimal digits in ' + 'fingerprint for fingerprint: ' + fingerprint) is_good = False return is_good