Example #1
0
def check_ssl_certificates():
    issue_name = 'expiring-certificate'
    ports = get_setting('port')
    if isinstance(ports, int):
        ports = [ports]
    elif isinstance(ports, dict):
        ports = list(ports.keys())

    problem_hosts = []
    for port in ports:
        certificate_file = get_port_setting(port, 'ssl:certificate')
        if not get_port_setting(port, 'ssl:enabled', bool(certificate_file)):
            continue
        try:
            subprocess.check_output(
                ('openssl', 'x509', '-in', certificate_file, '-checkend',
                 str(60 * 60 * 24 * 7)),
                stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            hostname = 'server-port-{}'.format(port)
            problem_hosts.append(hostname)
            if open_issue(hostname, issue_name):
                log.info('Opened {} issue for {}', issue_name, hostname)
    for doc in close_issue({'$not': {'$in': list(problem_hosts)}}, issue_name):
        log.info('Closed {} issue for {}', issue_name, doc['hostname'])
Example #2
0
def open_handler(args):
    with logbook.StreamHandler(sys.stdout, bubble=True):
        for host in args.host:
            for issue in args.issue_name:
                if open_issue(host, issue):
                    log.info('Manually opened {} issue for {}', issue, host)
                else:
                    print('Open {} issue for {} already exists.'.format(
                        issue, host))
Example #3
0
def check_pending_patches():
    issue_name = 'pending-patches'
    db = get_db()
    problem_hosts = set()
    for patch in db.patches.find({'pending_hosts': {'$not': {'$size': 0}}}):
        for hostname in patch['pending_hosts']:
            if open_issue(hostname, issue_name):
                log.info('Opened {} issue for {}', issue_name, hostname)
            problem_hosts.add(hostname)
    for doc in close_issue({'$not': {'$in': list(problem_hosts)}}, issue_name):
        log.info('Closed {} issue for {}', issue_name, doc['hostname'])
Example #4
0
def check_pending_patches():
    issue_name = 'pending-patches'
    db = get_db()
    problem_hosts = set()
    for patch in db.patches.find({'pending_hosts': {'$not': {'$size': 0}}}):
        for hostname in patch['pending_hosts']:
            if not client_exists(hostname):
                db.patches.update({'_id': patch['_id']},
                                  {'$pull': {'pending_hosts': hostname}})
                log.info('Removed deleted client {} from pending patch {}',
                         hostname, patch['_id'])
                continue
            if open_issue(hostname, issue_name):
                log.info('Opened {} issue for {}', issue_name, hostname)
            problem_hosts.add(hostname)
    for doc in close_issue({'$not': {'$in': list(problem_hosts)}}, issue_name):
        log.info('Closed {} issue for {}', issue_name, doc['hostname'])
Example #5
0
 def wrapper(*args, **kwargs):
     issue_name = 'deprecated-port'
     try:
         hostname = json.loads(request.form['data'])['hostname']
         ok = True
     except:
         log.error('Failed to parse request data')
         ok = False
         hostname = request.remote_addr
     if app.config['deprecated_port']:
         log.warn('Host {} connected to deprecated port', hostname)
         if ok:
             if open_issue(hostname, issue_name):
                 log.info('Opened {} issue for {}', issue_name, hostname)
     else:
         if ok:
             doc = close_issue(hostname, issue_name)
             if doc:
                 log.info('Closed {} issue for {}', issue_name, hostname)
     return f(*args, **kwargs)
Example #6
0
def audit_handler(args):
    def d(dt):
        return dt.strftime('%m/%d %H:%M')

    in_a_terminal = os.isatty(sys.stderr.fileno())
    if args.update_recent is None:
        args.update_recent = not in_a_terminal
    if args.display_recent is None:
        args.display_recent = in_a_terminal

    if args.full:
        args.ignore_grace_period = args.display_recent = \
            args.ignore_snoozed = args.ignore_filters = True

    db = get_db()

    for check_name, check in problem_checks().items():
        if 'spec' not in check:
            continue
        problems = [d for d in db.clients.find(check['spec'])]
        for problem in problems:
            if open_issue(problem['hostname'],
                          check_name,
                          as_of=problem['plugins']['submitted_at']):
                log.info('Opened {} issue for {} as of {}', check_name,
                         problem['hostname'],
                         problem['plugins']['submitted_at'])
        problem_hosts = [d['hostname'] for d in problems]
        for doc in close_issue({'$not': {'$in': problem_hosts}}, check_name):
            log.info('Closed {} issue for {}', check_name, doc['hostname'])

    check_pending_patches()
    check_ssl_certificates()

    issues = get_open_issues(include_suspended=args.ignore_suspended)

    default_alert_frequency = datetime.timedelta(hours=1)

    for key1, value1 in issues.items():
        key1_printed = False
        email_list = ''
        for key2, issue in value1.items():
            check = problem_checks().get(issue['name']) or {}
            filter = None if args.ignore_filters else check.get('filter', None)
            alert_frequency = check.get('alert-frequency',
                                        default_alert_frequency)
            # Not exactly on the hour, to avoid race conditions when running
            # hourly.
            if 0 == alert_frequency.total_seconds() % 3600:
                alert_frequency -= datetime.timedelta(minutes=1)
            alert_threshold = now - alert_frequency
            grace_period = check.get('grace-period', datetime.timedelta(0))
            filter_ok = not (filter and filter(issue))
            alert_ok = (args.display_recent or 'alerted_at' not in issue
                        or issue['alerted_at'] < alert_threshold)
            grace_ok = (args.ignore_grace_period or
                        business_hours(issue['opened_at'], now) > grace_period)
            snooze_ok = (args.ignore_snoozed or 'unsnooze_at' not in issue
                         or issue['unsnooze_at'] < now)
            if issue.get('unsnooze_at', now) > now:
                snoozed = ' [snoozed until {}]'.format(d(issue['unsnooze_at']))
            else:
                snoozed = ''
            client = db.clients.find_one({'hostname': key1},
                                         projection=['submitted_at'])
            if filter_ok and alert_ok and grace_ok and snooze_ok:
                if not key1_printed:
                    if client:
                        last_reported = d(client['submitted_at'])
                        print('{} [last reported at {}]'.format(
                            key1, last_reported))
                    else:
                        # This is a global issue, not a per-client issue
                        print(key1)
                    key1_printed = True
                print('  {} since {}{}'.format(key2, d(issue['opened_at']),
                                               snoozed))
                email_list += '{} since {}\n'.format(key2,
                                                     d(issue['opened_at']))
                if not in_a_terminal:
                    log.warn('{} {} since {}', key1, key2, issue['opened_at'])
                if args.update_recent:
                    db.issues.update({'_id': issue['_id']},
                                     {'$set': {
                                         'alerted_at': now
                                     }})
        if client and args.email and email_list:
            email = get_client_parameter(key1, 'user_email')
            if not email:
                log.warn("Can't send email for {} since user_email not set",
                         key1)
                continue
            subject = 'Please address issues on {}'.format(key1)
            body = dedent("""\
                The following issues have been identified on the PenguinDome
                (device management) client "{}", for which you are the listed
                owner. Please rectify these issues at your earliest
                convenience.\n\n""".format(key1))
            body += email_list
            smtp = smtplib.SMTP()
            smtp.connect()
            msg = dedent("""\
                From: PenguinDome
                To: {to}
                Subject: {subject}\n\n""").format(to=email, subject=subject)
            msg += body
            smtp.sendmail('PenguinDome', [email], msg)
            smtp.quit()