def main(args): (opts, args) = parseargs(args) myuid = os.geteuid() if myuid and not opts.useronly: print >>sys.stderr, "Please run as root or with --useronly option" sys.exit(1) my = yum.YumBase() my.preconf.init_plugins=False if hasattr(my, 'setCacheDir'): my.setCacheDir() my.conf.cache = True needing_restart = set() boot_time = utils.get_boot_time() for pid in return_running_pids(uid=myuid): try: pid_start = utils.get_process_time(int(pid), boot_time)['start_time'] except (OSError, IOError), e: continue found_match = False for fn in get_open_files(pid): if found_match: break just_fn = fn.replace('(deleted)', '') just_fn = just_fn.strip() bogon = False # if the file is in a pkg which has been updated since we started the pid - then it needs to be restarted for pkg in my.rpmdb.searchFiles(just_fn): if float(pkg.installtime) > float(pid_start): needing_restart.add(pid) found_match = True continue if just_fn in pkg.ghostlist: bogon = True break if bogon: continue # if the file is deleted if fn.find('(deleted)') != -1: # and it is from /*bin/* then it needs to be restarted if yum.misc.re_primary_filename(just_fn): needing_restart.add(pid) found_match = True continue # if the file is from an old ver of an installed pkg - then assume it was just updated but the # new pkg doesn't have the same file names. Fabulous huh?! my.conf.cache = False for oldpkg in my.pkgSack.searchFiles(just_fn): # ghostfiles are always bogons if just_fn in oldpkg.ghostlist: continue if my.rpmdb.installed(oldpkg.name): needing_restart.add(pid) found_match = True break
def main(args): (opts, args) = parseargs(args) myuid = os.geteuid() if myuid and not opts.useronly: print >>sys.stderr, "Please run as root or with --useronly option" sys.exit(1) my = yum.YumBase() my.preconf.init_plugins=False if hasattr(my, 'setCacheDir'): my.setCacheDir() my.conf.cache = True needing_restart = [] boot_time = utils.get_boot_time() for pid in return_running_pids(uid=myuid): try: pid_start = utils.get_process_time(int(pid), boot_time)['start_time'] except (OSError, IOError), e: continue found_match = False for fn in get_open_files(pid): if found_match: break just_fn = fn.replace('(deleted)', '') just_fn = just_fn.strip() bogon = False # if the file is in a pkg which has been updated since we started the pid - then it needs to be restarted for pkg in my.rpmdb.searchFiles(just_fn): if float(pkg.installtime) > float(pid_start): needing_restart.append([pid, just_fn, pkg.name]) found_match = True continue if just_fn in pkg.ghostlist: bogon = True break if bogon: continue # if the file is deleted if fn.find('(deleted)') != -1: # and it is from /*bin/* then it needs to be restarted if yum.misc.re_primary_filename(just_fn): needing_restart.append([pid, just_fn, pkg.name]) found_match = True continue # if the file is from an old ver of an installed pkg - then assume it was just updated but the # new pkg doesn't have the same file names. Fabulous huh?! my.conf.cache = False for oldpkg in my.pkgSack.searchFiles(just_fn): # ghostfiles are always bogons if just_fn in oldpkg.ghostlist: continue if my.rpmdb.installed(oldpkg.name): needing_restart.append([pid, just_fn, pkg.name]) found_match = True break
def main(args): (opts, args) = parseargs(args) myuid = os.geteuid() if myuid and not opts.useronly: print >> sys.stderr, "Please run as root or with --useronly option" sys.exit(1) my = yum.YumBase() my.preconf.init_plugins = False if hasattr(my, 'setCacheDir'): my.setCacheDir() my.conf.cache = True boot_time = utils.get_boot_time() if opts.reboothint: needing_reboot = set() for pkg in my.rpmdb.searchNames(REBOOTPKGS): if float(pkg.installtime) > float(boot_time): needing_reboot.add(pkg) if needing_reboot: print 'Core libraries or services have been updated:' for pkg in needing_reboot: print ' %s ->' % pkg.name, pkg.printVer() print print 'Reboot is required to ensure that your system benefits', print 'from these updates.' print print 'More information:' print 'https://access.redhat.com/solutions/27943' return 1 else: print 'No core libraries or services have been updated.' print 'Reboot is probably not necessary.' return 0 needing_restart = set() for pid in return_running_pids(uid=myuid): try: pid_start = utils.get_process_time(int(pid), boot_time)['start_time'] except (OSError, IOError), e: continue found_match = False for fn in get_open_files(pid): if found_match: break just_fn = fn.replace('(deleted)', '') just_fn = just_fn.strip() bogon = False # if the file is in a pkg which has been updated since we started the pid - then it needs to be restarted for pkg in my.rpmdb.searchFiles(just_fn): if float(pkg.installtime) > float(pid_start): needing_restart.add(pid) found_match = True continue if just_fn in pkg.ghostlist: bogon = True break if bogon: continue # if the file is deleted if fn.find('(deleted)') != -1: # and it is from /*bin/* then it needs to be restarted if yum.misc.re_primary_filename(just_fn): needing_restart.add(pid) found_match = True continue # if the file is from an old ver of an installed pkg - then assume it was just updated but the # new pkg doesn't have the same file names. Fabulous huh?! my.conf.cache = False for oldpkg in my.pkgSack.searchFiles( just_fn): # ghostfiles are always bogons if just_fn in oldpkg.ghostlist: continue if my.rpmdb.installed(oldpkg.name): needing_restart.add(pid) found_match = True break
def main(args): (opts, args) = parseargs(args) myuid = os.geteuid() if myuid and not opts.useronly: print >>sys.stderr, "Please run as root or with --useronly option" sys.exit(1) my = yum.YumBase() my.preconf.init_plugins=False if hasattr(my, 'setCacheDir'): my.setCacheDir() my.conf.cache = True boot_time = utils.get_boot_time() if opts.reboothint: needing_reboot = set() for pkg in my.rpmdb.searchNames(REBOOTPKGS): if float(pkg.installtime) > float(boot_time): needing_reboot.add(pkg) if needing_reboot: print 'Core libraries or services have been updated:' for pkg in needing_reboot: print ' %s ->' % pkg.name, pkg.printVer() print print 'Reboot is required to ensure that your system benefits', print 'from these updates.' print print 'More information:' print 'https://access.redhat.com/solutions/27943' return 1 else: print 'No core libraries or services have been updated.' print 'Reboot is probably not necessary.' return 0 needing_restart = set() for pid in return_running_pids(uid=myuid): try: pid_start = utils.get_process_time(int(pid), boot_time)['start_time'] except (OSError, IOError), e: continue found_match = False for fn in get_open_files(pid): if found_match: break just_fn = fn.replace('(deleted)', '') just_fn = just_fn.strip() bogon = False # if the file is in a pkg which has been updated since we started the pid - then it needs to be restarted for pkg in my.rpmdb.searchFiles(just_fn): if float(pkg.installtime) > float(pid_start): needing_restart.add(pid) found_match = True continue if just_fn in pkg.ghostlist: bogon = True break if bogon: continue # if the file is deleted if fn.find('(deleted)') != -1: # and it is from /*bin/* then it needs to be restarted if yum.misc.re_primary_filename(just_fn): needing_restart.add(pid) found_match = True continue # if the file is from an old ver of an installed pkg - then assume it was just updated but the # new pkg doesn't have the same file names. Fabulous huh?! my.conf.cache = False for oldpkg in my.pkgSack.searchFiles(just_fn): # ghostfiles are always bogons if just_fn in oldpkg.ghostlist: continue if my.rpmdb.installed(oldpkg.name): needing_restart.add(pid) found_match = True break
def main(vardir, factfile, defurl, deffixes=(), chsevs=(), rebootpkgs=()): tries = 1 success = False local_defs = os.path.join(vardir, 'oval-definitions.xml') while tries < 4: logger.info('Downloading %s (try %s)' % (defurl, tries)) try: r = requests.get(defurl, stream=True) with open(local_defs, 'w') as fh: for chunk in r.iter_content(chunk_size=8092): if chunk: fh.write(chunk) fh.close() success = True break except Exception as ex: logger.info('Error downloading: %s' % ex) logger.info('Sleeping for 1 minute') tries += 1 time.sleep(60) if not success: logger.info('Was not able to download %s, giving up' % defurl) # We exit with code 0 and will let nagios file age monitoring to alert # when an oscap report hasn't run in a bit sys.exit(0) if len(deffixes): try: root = etree.parse(local_defs).getroot() for (ovalid, fix) in deffixes.items(): matchelt = root.find('.//*[@id="%s"]' % ovalid) if matchelt is not None: child = matchelt.getchildren()[0] child.text = fix logger.info('Fixed definition %s=%s' % (ovalid, fix)) else: logger.info('Did not find anything matching %s' % ovalid) # This will probably give us false-negatives for results, so # exit now and let nagios alert us. sys.exit(0) fh = open(local_defs, 'w') fh.write(etree.tostring(root, pretty_print=True)) fh.close() except Exception as ex: logger.info('Error mangling %s' % local_defs) logger.info('Exception: %s' % ex) sys.exit(0) # Next we run oscap oval eval resfile = os.path.join(vardir, 'oval-results.xml') repfile = os.path.join(vardir, 'oval-report.html') args = ['oscap', 'oval', 'eval', '--results', resfile, '--report', repfile, local_defs] logger.info('Running: %s' % ' '.join(args)) (output, error) = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() error = error.strip() if error: logger.info('Error running oscap eval: %s' % error) # We exit with code 0 and will let nagios file age monitoring to alert # when an oscap report hasn't run in a bit sys.exit(0) logger.info('Parsing %s' % resfile) from pprint import pprint try: doc = etree.parse(resfile).getroot() res = doc.find('res:results', ns) defs = doc.find('def:oval_definitions', ns) oval = { 'rhsa': {}, 'cve' : {}, 'severity': { 'cve': {} , 'rhsa': {} }, } for sddelt in res.findall('res:system/res:definitions/res:definition[@result="true"]', ns): defid = sddelt.get('definition_id') defelt = defs.find('def:definitions/def:definition[@id="%s"]' % defid, ns) metaelt = defelt.find('def:metadata', ns) title = metaelt.find('def:title', ns).text if metaelt.find('def:advisory/def:severity', ns) != None: severity = metaelt.find('def:advisory/def:severity', ns).text.lower() else: severity = 'unknown' for refelt in metaelt.findall('def:reference', ns): refid = refelt.get('ref_id') refurl = refelt.get('ref_url') for chid, new_severity in chsevs.items(): if refid.find(chid) == 0: logger.info('Changed severity on %s: %s => %s' % (refid, severity, new_severity)) severity = new_severity.lower() break source = refelt.get('source').lower() if refid not in oval[source]: logger.info('Found %s Reference : %s' % (title, refid)) oval[source][refid] = refurl # Count RHSA CVE references if refid.startswith('CVE'): if severity not in oval['severity']['cve']: oval['severity']['cve'][severity] = { 'count': 0, 'titles': [], } oval['severity']['cve'][severity]['count'] += 1 oval['severity']['cve'][severity]['titles'].append(refid) elif refid.startswith('RHSA'): if severity not in oval['severity']['rhsa']: oval['severity']['rhsa'][severity] = { 'count': 0, 'titles': [], } oval['severity']['rhsa'][severity]['count'] += 1 oval['severity']['rhsa'][severity]['titles'].append(refid) except Exception as ex: logger.info('Was not able to parse %s' % resfile) logger.info('Error returned: %s' % ex) # We exit with code 0 and will let nagios file age monitoring to alert # when an oscap report hasn't run in a bit sys.exit(0) facts = { 'openscap': { 'oval': oval, } } if rebootpkgs: # Some magic taken from yum-utils needs-restarting # I miss you Seth. import yum sys.path.insert(0,'/usr/share/yum-cli') import utils my = yum.YumBase() my.preconf.init_plugins = False if hasattr(my, 'setCacheDir'): my.conf.cache = True boot_time = utils.get_boot_time() stale_pkgs = [] for pkg in my.rpmdb.searchNames(rebootpkgs): if float(pkg.installtime) > float(boot_time): logger.info('Core package %s updated, system needs reboot.' % pkg) stale_pkgs.append(str(pkg)) if len(stale_pkgs): facts['openscap']['oval']['needs_reboot'] = True facts['openscap']['oval']['reboot_pkgs'] = stale_pkgs try: logger.info('Writing %s' % factfile) fout = open(factfile, 'w') yaml.safe_dump(facts, fout, default_flow_style=False, explicit_start=True) fout.close() # set perms on that file to 0600 just in case it's not already os.chmod(factfile, 0o600) except Exception as ex: # The only critical error logger.critical('Was not able to write to %s' % factfile) sys.exit(1)