#!/usr/bin/env python """ This script checks, if for each maintainer (defined in the hostinfo data) a public ssh key is available in the bcfg2 repository. """ import os import sys import yaml import argparse import logging import nagiosplugin class MissingMaintainerKeys(nagiosplugin.Resource): def __init__(self, hostinfo, repo): self.hostinfo = hostinfo self.repo = repo @property def name(self): return "missing_maintainer_keys" def _get_all_hosts(self): hosts = list() hosts_path = os.path.join(self.hostinfo, 'metadata', 'hosts') with open(hosts_path) as hosts_file: hostlist = yaml.load(hosts_file) hosts = hostlist['hosts'] return hosts def _get_all_maintainers(self, hosts): maintainers = set() for host in hosts: data = dict() with open(os.path.join(self.hostinfo, host)) as host_file: data = yaml.load(host_file) if 'maintainers' in data and data['maintainers'] is not None: for maintainer in data['maintainers']: if type(maintainer) is dict: maintainers |= set(maintainer.values()) else: maintainers |= set([maintainer]) return maintainers def probe(self): hosts = self._get_all_hosts() maintainers = self._get_all_maintainers(hosts) yield nagiosplugin.Metric('count', maintainers, context='count') errors = list() for maintainer in maintainers: keyfile = os.path.join(self.repo, 'SSHKeys', maintainer + '.pub') if not os.path.exists(keyfile): errors.append(maintainer) yield nagiosplugin.Metric('missing', errors, context='missing') class MissingMaintainerKeysContext(nagiosplugin.Context): def __init__(self, name, result_cls=nagiosplugin.Result): super(MissingMaintainerKeysContext, self).__init__( name, result_cls=result_cls) def describe(self, metric): if len(metric.value) > 0: return ("missing keys: %s" % ', '.join(metric.value)) return "all keys available" def evaluate(self, metric, resource): if len(metric.value) > 0: return self.result_cls(nagiosplugin.Critical, hint=self.describe(metric), metric=metric) return self.result_cls(nagiosplugin.Ok, hint=self.describe(metric), metric=metric) def performance(self, metric, resource): return nagiosplugin.Performance( label='missing', value=len(metric.value), crit="1", min="0") class MaintainersContext(nagiosplugin.Context): def __init__(self, name, result_cls=nagiosplugin.Result): super(MaintainersContext, self).__init__( name, result_cls=result_cls) def describe(self, metric): if len(metric.value) < 1: return "no maintainer found" if len(metric.value) == 1: return "1 maintainer found" return "%d maintainers found" % len(metric.value) def evaluate(self, metric, resource): if len(metric.value) < 1: return self.result_cls(nagiosplugin.Critical, hint=self.describe(metric), metric=metric) return self.result_cls(nagiosplugin.Ok, hint=self.describe(metric), metric=metric) def performance(self, metric, resource): return nagiosplugin.Performance( label='count', value=len(metric.value), min="0") def print_version(): import version self = os.path.basename(sys.argv[0]) print("%s %s" % (self, version.get_git_version())) sys.exit(nagiosplugin.Unknown.code) @nagiosplugin.guarded def main(): basepath = '/usr/local/share/hostinfo' repopath = '/var/lib/bcfg2/' if 'HOSTINFO_PATH' in os.environ and os.environ['HOSTINFO_PATH'] != '': basepath = os.environ['HOSTINFO_PATH'] parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("-p", "--path", default=basepath, help="set the path to the hostinfo data") parser.add_argument("-r", "--repo", default=repopath, help="set the path to the bcfg2 repo") parser.add_argument("-V", "--version", action="store_true", help="only print the version number and exit") parser.add_argument("-v", "--verbose", action="count", default=0, help="increase output verbosity (use up to 3 times)") parser.add_argument("-t", "--timeout", type=int, default=10, help="abort check execution with a UNKNOWN result " "after so many seconds (use 0 for no timeout)") args = parser.parse_args() if args.version: print_version() if not os.path.exists(args.path): raise Exception("hostinfo data not found in '%s'" % args.path) if not os.path.exists(args.repo): raise Exception("bcfg2 repo not found in '%s'" % args.repo) check = nagiosplugin.Check( MissingMaintainerKeys(args.path, args.repo), MaintainersContext('count'), MissingMaintainerKeysContext('missing')) check.main(verbose=args.verbose, timeout=args.timeout) if __name__ == '__main__': main()