Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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)