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 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()
def load_seeds(self, seeds=None ,seedfile=None): if not seeds and not seedfile: self.logger.error("ACTIONS: load_seeds; no filename to load: " "setting = %s. Please use the -s option to indicate: which seed " "file to use." % seedfile) return None if seeds: filepath = self.config.get_key(seeds + "-seedfile") elif seedfile: filepath = os.path.join(self.config.get_key('seedsdir'), '%s.seeds' % seedfile) self.logger.debug("ACTIONS: load_seeds; seeds filepath to load: " "%s" % filepath) seeds = Seeds() seeds.load(filepath) 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
def load_seeds(self, seedfile=None, filepath=None): '''Load seed file @param seeds: string of the short name seed file @param seedfile: string filepath of the file to load @return Seeds class instance of the file loaded ''' if not seedfile and not filepath: self.logger.error("SeedHandler: load_seeds; no filename to load: " "setting = %s. Please use the -S or -F option to indicate: which seed " "file to use." % seedfile) return False if seedfile: filepath = self.config.get_key('seeds', seedfile) elif not filepath: self.logger.error("SeedHandler: load_seeds; No filepath to load") self.logger.debug("SeedHandler: load_seeds; seeds filepath to load: " "%s" % filepath) seeds = Seeds(config=self.config) seeds.load(filepath) return seeds
def load_seeds(self, seedfile=None, filepath=None, refresh=False): '''Load seed file @param seeds: string of the short name seed file @param seedfile: string filepath of the file to load @return Seeds class instance of the file loaded ''' if not seedfile and not filepath: self.logger.error("SeedHandler: load_seeds; no filename to load: " "setting = %s. Please use the -S or -F option to indicate: which seed " "file to use." % seedfile) return False if seedfile: filepath = self.config.get_key('seeds', seedfile) elif not filepath: self.logger.error("SeedHandler: load_seeds; No filepath to load") self.logger.debug("SeedHandler: load_seeds; seeds filepath to load: " "%s" % filepath) seeds = Seeds(config=self.config, _logger=self.logger) seeds.load(filepath, refresh=refresh) self.seeds = seeds return seeds
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()
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
def set_keyseedfile(self, trap_errors=True, refresh=False): if not self.keydir: self.logger.debug("GkeysGPG.set_keyseedfile(); self.keydir error") self.seedfile = Seeds(pjoin(self.keydir, 'gkey.seeds'), self.config, self.logger) self.seedfile.load(trap_errors=trap_errors, refresh=refresh)
class GkeysGPG(GPG): '''Gentoo-keys primary gpg class''' def __init__(self, config, basedir, logger): '''class init function @param config: GKeysConfig config instance to use @param keydir: string, the path to the keydir to be used for all operations. ''' GPG.__init__(self, config, logger) self.config = config self.basedir = basedir self.logger = logger self.keydir = None self.server = None def set_keyserver(self, server=None): '''Set the keyserver and add the --keyserver option to the gpg defaults ''' if self.server and not server: return self.server = server or self.config['keyserver'] self.config.options['gpg_defaults'] = self.config.defaults['gpg_defaults'][:] self.logger.debug("keyserver: %s" % (self.server)) server_value = ['--keyserver', self.server] self.config.options['gpg_defaults'].extend(server_value) self.logger.debug("self.config.options['gpg_defaults']: %s" % (self.config.options['gpg_defaults'])) return def set_keyring(self, keyring, task, importkey=False, reset=True): '''Sets the keyring to use as well as related task options ''' self.logger.debug("keydir: %s, keyring: %s" % (self.keydir, keyring)) if reset: self.config.options['tasks'][task] = self.config.defaults['tasks'][task][:] # --keyring file | Note that this adds a keyring to the current list. # If the intent is to use the specified keyring alone, # use --keyring along with --no-default-keyring. if importkey: task_value = ['--import-options', 'import-clean'] self.config.options['tasks'][task].extend(task_value) parent_dir = abspath(pjoin(keyring, pardir)) ensure_dirs(parent_dir, mode=int(self.config.get_key('permissions', 'directories'),0)) task_value = ['--no-default-keyring', '--keyring', keyring] self.config.options['tasks'][task].extend(task_value) self.logger.debug("set_keyring: New task options: %s" %str(self.config.options['tasks'][task])) return def set_keydir(self, keydir, task, fingerprint=True, reset=True): self.logger.debug("basedir: %s, keydir: %s" % (self.basedir, keydir)) self.keydir = pjoin(self.basedir, keydir) self.task = task if reset: self.config.options['tasks'][task] = self.config.defaults['tasks'][task][:] task_value = [] if fingerprint: task_value.append('--fingerprint') task_value.extend(['--homedir', self.keydir]) self.config.options['tasks'][task].extend(task_value) self.logger.debug("set_keydir: New task options: %s" %str(self.config.options['tasks'][task])) return def add_to_keyring(self, gkey, keydir, keyring): '''Add the specified key to the specified keyring @param gkey: GKEY namedtuple with (name, keyid/longkeyid, keydir, fingerprint) @param keydir: path with the specified keydir @param keyring: string with the specified keyring ''' self.set_keydir(keydir, 'import', reset=True) self.set_keyring(keyring, 'import', importkey=True, reset=False) results = [] self.logger.debug("LIB: import_to_keyring; name: " + gkey.name) self.logger.debug("** Calling runGPG with Running: gpg %s --import' for: %s" % (' '.join(self.config.get_key('tasks', 'import')), gkey.name)) pubring_path = pjoin(self.keydir, gkey.keydir, 'pubring.gpg') result = self.runGPG(task='import', inputfile=pubring_path) self.logger.info('GPG return code: ' + str(result.returncode)) results.append(result) print(result.stderr_out) return results def add_key(self, gkey): '''Add the specified key to the specified keydir @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) ''' self.config.defaults['gpg_defaults'].append('--no-permission-warning') self.set_keyserver() self.set_keydir(gkey.keydir, 'recv-keys', reset=True) self.set_keyring('pubring.gpg', 'recv-keys', reset=False) self.logger.debug("LIB: add_key; ensure dirs: " + self.keydir) mode = int(self.config.get_key('permissions', 'directories'),0) ensure_dirs(str(self.keydir), mode=mode) self.set_keyseedfile(trap_errors=True) results = [] for fingerprint in gkey.keys: self.logger.debug("LIB: add_key; adding fingerprint " + fingerprint) self.logger.debug("** Calling runGPG with Running 'gpg %s --recv-keys %s' for: %s" % (' '.join(self.config.get_key('tasks', 'recv-keys')), fingerprint, gkey.name)) result = self.runGPG(task='recv-keys', inputfile=fingerprint) self.logger.info('GPG return code: ' + str(result.returncode)) if result.fingerprint in gkey.keys: result.failed = False message = "Fingerprints match... Import successful: " message += "%s, fingerprint: %s" % (gkey.nick, fingerprint) message += "\n result len: %s, %s" % (len(result.fingerprint), result.fingerprint) message += "\n gkey len: %s, %s" % (len(gkey.fingerprint[0]), gkey.fingerprint[0]) self.logger.info(message) else: result.failed = True message = "Fingerprints do not match... Import failed for " message += "%s, fingerprint: %s" % (gkey.nick, fingerprint) message += "\n result: %s" % (result.fingerprint) message += "\n gkey..: %s" % (str(gkey.fingerprint)) self.logger.error(message) # Save the gkey seed to the installed db success = self.update_gkey(gkey, save=True) if not success: return [] results.append(result) return results def del_key(self, gkey, key): '''Delete the specified key @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) @param key: Fingerprint of the primary key to delete ''' self.set_keydir(gkey.keydir, 'del-key', reset=True) self.set_keyring('pubring.gpg', 'del-key', reset=False) self.set_keyseedfile(refresh=True) self.logger.debug("LIB: del_key, gkey: %s" % str(gkey)) self.logger.debug("LIB: del_key, key: %s" % key) self.logger.debug("** Calling runGPG with: 'gpg %s --delete-keys' for: %s" % (' '.join(self.config.get_key('tasks', 'delete-keys')), str(gkey))) result = self.runGPG(task='delete-keys', inputfile=key) self.logger.info('GPG return code: ' + str(result.returncode)) self.update_gkey(gkey, save=True) return (False, []) def del_keydir(self, gkey): '''Delete the specified keydir @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) ''' rm_candidate = os.path.join(self.basedir, gkey.keydir) success = False messages = [] try: rmtree(rm_candidate) messages.append("Done removing %s key." % gkey.nick) success = True except OSError: messages.append("%s directory does not exist or is a symbolic link." % rm_candidate) return (success, messages) def refresh_key(self, gkey): '''Refresh the specified key in the specified keydir @param key: tuple of (name, nick, keydir, fingerprint) @param keydir: the keydir to add the key to ''' self.config.defaults['gpg_defaults'].append('--no-permission-warning') self.set_keyserver() self.set_keydir(gkey.keydir, 'refresh-keys', reset=True) self.set_keyring('pubring.gpg', 'refresh-keys', reset=False) self.set_keyseedfile(refresh=True) self.logger.debug("LIB: refresh_key, gkey: %s" % str(gkey)) self.logger.debug("** Calling runGPG with Running 'gpg %s --refresh-keys' for: %s" % (' '.join(self.config.get_key('tasks', 'refresh-keys')), str(gkey))) result = self.runGPG(task='refresh-keys', inputfile='') self.logger.info('GPG return code: ' + str(result.returncode)) self.update_gkey(gkey, save=True) return result def update_gkey(self, gkey, save=False): '''Update the specified key in the specified keydir @param key: tuple of (name, nick, keydir, fingerprint) @param keydir: the keydir to add the key to ''' # Update the gkey seed and save it to the installed db lresults = [] for fpr in gkey.keys: lresults.append(self.list_keys(gkey.keydir, fpr, colons=True)) self.seedfile.update(gkey.update(lresults)) if save and not self.seedfile.save(): self.logger.error("GkeysGPG.update_gkey(); failed to save seed: " + gkey.nick) return False return True def list_keys(self, keydir, fingerprint=None, colons=False): '''List all keys in the specified keydir or all keys in all keydir if keydir=None @param keydir: the keydir to list the keys for @param colons: bool to enable colon listing ''' if not keydir: self.logger.debug("LIB: list_keys(), invalid keydir parameter: %s" % str(keydir)) return [] if fingerprint: task = 'list-key' target = fingerprint self.set_keydir(keydir, task, fingerprint=True) else: task = 'list-keys' target = '' self.set_keydir(keydir, task, fingerprint=False) self.config.options['tasks'][task].extend(['--keyid-format', 'long', '--fingerprint']) if colons: task_value = ['--with-colons'] self.config.options['tasks'][task].extend(task_value) self.logger.debug("** Calling runGPG with Running 'gpg %s --%s %s'" % (' '.join(self.config['tasks'][task]), task, target) ) result = self.runGPG(task=task, inputfile=target) self.logger.info('GPG return code: ' + str(result.returncode)) return result def check_keys(self, keydir, keyid, result=None): '''Check specified or all keys based on the seed type @param keydir: the keydir to list the keys for @param keyid: the keyid to check @param result: optional pyGPG.output.GPGResult object @returns: GKEY_CHECK instance ''' if not result: result = self.list_keys(keydir, fingerprint=keyid, colons=True) checker = KeyChecks(self.logger, qualified_id_check=True) return checker.validity_checks(keydir, keyid, result) def speccheck(self, keydir, keyid, result=None): '''Check specified or all keys based on the seed type specifications are met. @param keydir: the keydir to list the keys for @param keyid: the keyid to check @param result: optional pyGPG.output.GPGResult object @returns: SpecCheck instance ''' if not result: result = self.list_keys(keydir, fingerprint=keyid, colons=True) checker = KeyChecks(self.logger, qualified_id_check=True) specchecks = checker.spec_check(keydir, keyid, result) return specchecks def list_keydirs(self): '''List all available keydirs ''' return [] def verify_key(self, gkey): '''Verify the specified key from the specified keydir @param gkey: GKEY namedtuple with (name, keyid/longkeyid, fingerprint) ''' pass def verify_text(self, gkey, text, filepath=None): '''Verify a text block in memory @param gkey: GKEY instance of the gpg key used to verify it @param text: string of the of the text to verify @param filepath: optional string with the path or url of the signed file ''' self.set_keydir(gkey.keydir, 'verify', fingerprint=False, reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --verify %s'" % (' '.join(self.config['tasks']['verify']), filepath)) results = self.runGPG(task='verify', inputfile=filepath, inputtxt=text) self._log_result('verification', gkey, results) return results def verify_file(self, gkey, signature, filepath): '''Verify the file specified at filepath or url @param gkey: GKEY instance of the gpg key used to verify it @param signature: string with the signature file @param filepath: string with the path or url of the signed file ''' if signature: self.set_keydir(gkey.keydir, 'verify', reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --verify %s and %s'" % (' '.join(self.config['tasks']['verify']), signature, filepath)) results = self.runGPG(task='verify', inputfile=[signature,filepath]) else: self.set_keydir(gkey.keydir, 'decrypt', reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --decrypt %s'" % (' '.join(self.config['tasks']['decrypt']), filepath)) results = self.runGPG(task='decrypt', inputfile=filepath) self._log_result('verification', gkey, results) return results def set_keyseedfile(self, trap_errors=True, refresh=False): if not self.keydir: self.logger.debug("GkeysGPG.set_keyseedfile(); self.keydir error") self.seedfile = Seeds(pjoin(self.keydir, 'gkey.seeds'), self.config, self.logger) self.seedfile.load(trap_errors=trap_errors, refresh=refresh) def sign_file(self, gkey, mode, fingerprint, filepath): '''Verify the file specified at filepath or url @param gkey: GKEY instance @param mode: string of the signing task to use @param fingerprint: string of the fingerprint to sign with @param filepath: string with the path of the file to sign ''' self.set_keydir(gkey.keydir, mode, reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --%s %s %s'" % (' '.join(self.config['tasks'][mode]), mode, fingerprint, filepath)) results = self.runGPG(task=mode, inputfile=filepath) self._log_result('signing', gkey, results) return results def _log_result(self, mode, gkey, results): if results.verified[0]: self.logger.info("GPG %s succeeded. Name: %s / Key: %s" % (mode, gkey.name, gkey.keyid[0])) self.logger.info("\tSignature result:" + str(results.verified)) else: self.logger.debug("GPG %s failed. Name: %s / Key: %s" % (mode, gkey.name, gkey.keyid[0])) self.logger.debug("\t Signature result:"+ str(results.verified)) self.logger.debug("LIB: verify; stderr_out:" + str(results.stderr_out))
class GkeysGPG(GPG): '''Gentoo-keys primary gpg class''' def __init__(self, config, basedir, logger): '''class init function @param config: GKeysConfig config instance to use @param keydir: string, the path to the keydir to be used for all operations. ''' GPG.__init__(self, config, logger) self.config = config self.basedir = basedir self.logger = logger self.keydir = None self.server = None def set_keyserver(self, server=None): '''Set the keyserver and add the --keyserver option to the gpg defaults ''' if self.server and not server: return self.server = server or self.config['keyserver'] self.config.options['gpg_defaults'] = self.config.defaults['gpg_defaults'][:] self.logger.debug("keyserver: %s" % (self.server)) server_value = ['--keyserver', self.server] self.config.options['gpg_defaults'].extend(server_value) self.logger.debug("self.config.options['gpg_defaults']: %s" % (self.config.options['gpg_defaults'])) return def set_keyring(self, keyring, task, importkey=False, reset=True): '''Sets the keyring to use as well as related task options ''' self.logger.debug("keydir: %s, keyring: %s" % (self.keydir, keyring)) if reset: self.config.options['tasks'][task] = self.config.defaults['tasks'][task][:] # --keyring file | Note that this adds a keyring to the current list. # If the intent is to use the specified keyring alone, # use --keyring along with --no-default-keyring. if importkey: task_value = ['--import-options', 'import-clean'] self.config.options['tasks'][task].extend(task_value) parent_dir = abspath(pjoin(keyring, pardir)) ensure_dirs(parent_dir, mode=int(self.config.get_key('permissions', 'directories'),0)) task_value = ['--no-default-keyring', '--keyring', keyring] self.config.options['tasks'][task].extend(task_value) self.logger.debug("set_keyring: New task options: %s" %str(self.config.options['tasks'][task])) return def set_keydir(self, keydir, task, fingerprint=True, reset=True): self.logger.debug("basedir: %s, keydir: %s" % (self.basedir, keydir)) self.keydir = pjoin(self.basedir, keydir) self.task = task if reset: self.config.options['tasks'][task] = self.config.defaults['tasks'][task][:] task_value = [] if fingerprint: task_value.append('--fingerprint') task_value.extend(['--homedir', self.keydir]) self.config.options['tasks'][task].extend(task_value) self.logger.debug("set_keydir: New task options: %s" %str(self.config.options['tasks'][task])) return def add_to_keyring(self, gkey, keydir, keyring): '''Add the specified key to the specified keyring @param gkey: GKEY namedtuple with (name, keyid/longkeyid, keydir, fingerprint) @param keydir: path with the specified keydir @param keyring: string with the specified keyring ''' self.set_keydir(keydir, 'import', reset=True) self.set_keyring(keyring, 'import', importkey=True, reset=False) results = [] self.logger.debug("LIB: import_to_keyring; name: " + gkey.name) self.logger.debug("** Calling runGPG with Running: gpg %s --import' for: %s" % (' '.join(self.config.get_key('tasks', 'import')), gkey.name)) pubring_path = pjoin(self.keydir, gkey.keydir, 'pubring.gpg') result = self.runGPG(task='import', inputfile=pubring_path) self.logger.info('GPG return code: ' + str(result.returncode)) results.append(result) print(result.stderr_out) return results def add_key(self, gkey): '''Add the specified key to the specified keydir @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) ''' self.config.defaults['gpg_defaults'].append('--no-permission-warning') self.set_keyserver() self.set_keydir(gkey.keydir, 'recv-keys', reset=True) self.set_keyring('pubring.gpg', 'recv-keys', reset=False) self.logger.debug("LIB: add_key; ensure dirs: " + self.keydir) mode = int(self.config.get_key('permissions', 'directories'),0) ensure_dirs(str(self.keydir), mode=mode) self.set_keyseedfile(trap_errors=True) results = [] for fingerprint in gkey.keys: self.logger.debug("LIB: add_key; adding fingerprint " + fingerprint) self.logger.debug("** Calling runGPG with Running 'gpg %s --recv-keys %s' for: %s" % (' '.join(self.config.get_key('tasks', 'recv-keys')), fingerprint, gkey.name)) result = self.runGPG(task='recv-keys', inputfile=fingerprint) self.logger.info('GPG return code: ' + str(result.returncode)) if result.fingerprint in gkey.keys: result.failed = False message = "Fingerprints match... Import successful: " message += "%s, fingerprint: %s" % (gkey.nick, fingerprint) message += "\n result len: %s, %s" % (len(result.fingerprint), result.fingerprint) message += "\n gkey len: %s, %s" % (len(gkey.fingerprint[0]), gkey.fingerprint[0]) self.logger.info(message) else: result.failed = True message = "Fingerprints do not match... Import failed for " message += "%s, fingerprint: %s" % (gkey.nick, fingerprint) message += "\n result: %s" % (result.fingerprint) message += "\n gkey..: %s" % (str(gkey.fingerprint)) self.logger.error(message) # Save the gkey seed to the installed db success = self.update_gkey(gkey, save=True) if not success: return [] results.append(result) return results def del_key(self, gkey, key): '''Delete the specified key @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) @param key: Fingerprint of the primary key to delete ''' self.set_keydir(gkey.keydir, 'del-key', reset=True) self.set_keyring('pubring.gpg', 'del-key', reset=False) self.set_keyseedfile(refresh=True) self.logger.debug("LIB: del_key, gkey: %s" % str(gkey)) self.logger.debug("LIB: del_key, key: %s" % key) self.logger.debug("** Calling runGPG with: 'gpg %s --delete-keys' for: %s" % (' '.join(self.config.get_key('tasks', 'delete-keys')), str(gkey))) result = self.runGPG(task='delete-keys', inputfile=key) self.logger.info('GPG return code: ' + str(result.returncode)) self.update_gkey(gkey, save=True) return (False, []) def del_keydir(self, gkey): '''Delete the specified keydir @param gkey: GKEY namedtuple with (name, nick, keydir, fingerprint) ''' rm_candidate = os.path.join(self.basedir, gkey.keydir) success = False messages = [] try: rmtree(rm_candidate) messages.append("Done removing %s key." % gkey.nick) success = True except OSError: messages.append("%s directory does not exist or is a symbolic link." % rm_candidate) return (success, messages) def refresh_key(self, gkey): '''Refresh the specified key in the specified keydir @param key: tuple of (name, nick, keydir, fingerprint) @param keydir: the keydir to add the key to ''' self.config.defaults['gpg_defaults'].append('--no-permission-warning') self.set_keyserver() self.set_keydir(gkey.keydir, 'refresh-keys', reset=True) self.set_keyring('pubring.gpg', 'refresh-keys', reset=False) self.set_keyseedfile(refresh=True) self.logger.debug("LIB: refresh_key, gkey: %s" % str(gkey)) self.logger.debug("** Calling runGPG with Running 'gpg %s --refresh-keys' for: %s" % (' '.join(self.config.get_key('tasks', 'refresh-keys')), str(gkey))) result = self.runGPG(task='refresh-keys', inputfile='') self.logger.info('GPG return code: ' + str(result.returncode)) self.update_gkey(gkey, save=True) return result def update_gkey(self, gkey, save=False): '''Update the specified key in the specified keydir @param key: tuple of (name, nick, keydir, fingerprint) @param keydir: the keydir to add the key to ''' # Update the gkey seed and save it to the installed db lresults = [] for fpr in gkey.keys: lresults.append(self.list_keys(gkey.keydir, fpr, colons=True)) self.seedfile.update(gkey.update(lresults)) if save and not self.seedfile.save(): self.logger.error("GkeysGPG.update_gkey(); failed to save seed: " + gkey.nick) return False return True def list_keys(self, keydir, fingerprint=None, colons=False): '''List all keys in the specified keydir or all keys in all keydir if keydir=None @param keydir: the keydir to list the keys for @param colons: bool to enable colon listing ''' if not keydir: self.logger.debug("LIB: list_keys(), invalid keydir parameter: %s" % str(keydir)) return [] if fingerprint: task = 'list-key' target = fingerprint self.set_keydir(keydir, task, fingerprint=True) else: task = 'list-keys' target = '' self.set_keydir(keydir, task, fingerprint=False) self.config.options['tasks'][task].extend(['--keyid-format', 'long', '--fingerprint']) if colons: task_value = ['--with-colons'] self.config.options['tasks'][task].extend(task_value) self.logger.debug("** Calling runGPG with Running 'gpg %s --%s %s'" % (' '.join(self.config['tasks'][task]), task, target) ) result = self.runGPG(task=task, inputfile=target) self.logger.info('GPG return code: ' + str(result.returncode)) return result def check_keys(self, keydir, keyid, result=None): '''Check specified or all keys based on the seed type @param keydir: the keydir to list the keys for @param keyid: the keyid to check @param result: optional pyGPG.output.GPGResult object @returns: GKEY_CHECK instance ''' if not result: result = self.list_keys(keydir, fingerprint=keyid, colons=True) checker = KeyChecks(self.logger, qualified_id_check=True) return checker.validity_checks(keydir, keyid, result) def speccheck(self, keydir, keyid, result=None): '''Check specified or all keys based on the seed type specifications are met. @param keydir: the keydir to list the keys for @param keyid: the keyid to check @param result: optional pyGPG.output.GPGResult object @returns: SpecCheck instance ''' if not result: result = self.list_keys(keydir, fingerprint=keyid, colons=True) checker = KeyChecks(self.logger, qualified_id_check=True) specchecks = checker.spec_check(keydir, keyid, result) return specchecks def list_keydirs(self): '''List all available keydirs ''' return [] def verify_key(self, gkey): '''Verify the specified key from the specified keydir @param gkey: GKEY namedtuple with (name, keyid/longkeyid, fingerprint) ''' pass def verify_text(self, text): '''Verify a text block in memory ''' pass def verify_file(self, gkey, signature, filepath): '''Verify the file specified at filepath or url @param gkey: GKEY instance of the gpg key used to verify it @param signature: string with the signature file @param filepath: string with the path or url of the signed file ''' if signature: self.set_keydir(gkey.keydir, 'verify', reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --verify %s and %s'" % (' '.join(self.config['tasks']['verify']), signature, filepath)) results = self.runGPG(task='verify', inputfile=[signature,filepath]) else: self.set_keydir(gkey.keydir, 'decrypt', reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --decrypt %s'" % (' '.join(self.config['tasks']['decrypt']), filepath)) results = self.runGPG(task='decrypt', inputfile=filepath) keyid = gkey.keyid[0] if results.verified[0]: self.logger.info("GPG verification succeeded. Name: %s / Key: %s" % (gkey.name, keyid)) self.logger.info("\tSignature result:" + str(results.verified)) else: self.logger.debug("GPG verification failed. Name: %s / Key: %s" % (gkey.name, keyid)) self.logger.debug("\t Signature result:"+ str(results.verified)) self.logger.debug("LIB: verify; stderr_out:" + str(results.stderr_out)) return results def set_keyseedfile(self, trap_errors=True, refresh=False): if not self.keydir: self.logger.debug("GkeysGPG.set_keyseedfile(); self.keydir error") self.seedfile = Seeds(pjoin(self.keydir, 'gkey.seeds'), self.config, self.logger) self.seedfile.load(trap_errors=trap_errors, refresh=refresh) def sign_file(self, gkey, mode, fingerprint, filepath): '''Verify the file specified at filepath or url @param gkey: GKEY instance @param mode: string of the signing task to use @param fingerprint: string of the fingerprint to sign with @param filepath: string with the path of the file to sign ''' keyid = gkey.keyid[0] self.set_keydir(gkey.keydir, mode, reset=True) self.logger.debug("** Calling runGPG with Running 'gpg %s --%s %s %s'" % (' '.join(self.config['tasks'][mode]), mode, fingerprint, filepath)) results = self.runGPG(task=mode, inputfile=filepath) if results.verified[0]: self.logger.info("GPG signing succeeded. Name: %s / Key: %s" % (str(gkey.name), str(keyid))) self.logger.info("\tSignature result:" + str(results.verified)) else: self.logger.debug("GPG signing failed. Name: %s / Key: %s" % (str(gkey.name), str(keyid))) self.logger.debug("\t Signature result:"+ str(results.verified)) self.logger.debug("LIB: sign; stderr_out:" + str(results.stderr_out)) return results
def set_keyseedfile(self, trap_errors): if not self.keydir: logger.debug("GkeysGPG.set_keyseedfile(); self.keydir error") self.seedfile = Seeds(pjoin(self.keydir, 'gkey.seeds'), self.config) self.seedfile.load(trap_errors=trap_errors)