diff --git a/lib/nagios/plugins/cisco_api_status b/lib/nagios/plugins/cisco_api_status deleted file mode 100755 index b5323bbac4001f87ef9865cc4439ad9d6a4425c2..0000000000000000000000000000000000000000 --- a/lib/nagios/plugins/cisco_api_status +++ /dev/null @@ -1,463 +0,0 @@ -#!/usr/bin/python -# encoding: utf-8 - -# Monitor Cisco API plugins for CheckMK -# Author: thl-cmk[al]outlook[dot]com -# -# -# 15.03.2020: changed getopt to argparse - -import os -import argparse -import ConfigParser -import json -from datetime import datetime -import logging -import sys - - -# check if dir exists, if not try to create it. -# return True if dir exists or creation was ok. -# return False if dir not exists and creation was not ok -def check_dir_and_create(directory): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - directory = os.path.dirname(directory) - if not os.path.exists(directory): - try: - os.makedirs(directory) - except: - return False - return True - - -# expand user dir and add '/' if necessary and create directory if it not exists -def expand_path(path): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - homedir = os.path.expanduser('~') - if path.startswith('~'): - path = homedir + path[1:] - if not path.endswith('/'): - path += '/' - if not check_dir_and_create(path): - return '' - return path - - -def check_eox_status(apistatus, options, cmd_args): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - output = '' - long_output = '' - status = 0 - max_refresh_known = 0 - max_refresh_unknown = 0 - lastrun = apistatus.get('lastrun') - refresh_known = options.get('refresh_known', 31) - refresh_unknown = options.get('refresh_unknown', 7) - crit_new = cmd_args.eox_crit_new - warn_new = cmd_args.eox_warn_new - crit_change = cmd_args.eox_crit_change - warn_change = cmd_args.eox_warn_change - - for entry in lastrun: - last_checked = entry.get('Last_checked') - last_refresh = (datetime.now().date() - datetime.strptime(last_checked, '%Y-%m-%d').date()).days - if entry.get('EOXExternalAnnouncementDate') != 'None found': - if last_refresh > refresh_known: - # check is refresh ok - if max_refresh_known < last_refresh: - max_refresh_known = last_refresh - - EOXExternalAnnouncementDate = entry.get('EOXExternalAnnouncementDate') - ProductBulletinNumber = entry.get('ProductBulletinNumber') - pid = entry.get('pid') - ProductIDDescription = entry.get('ProductIDDescription') - - EoL_dates = ['LastDateOfSupport', 'EndOfSvcAttachDate', 'EndOfSaleDate'] - EoL_dates_desc = {'LastDateOfSupport': 'last date of support', - 'EndOfSvcAttachDate': 'end of service attachment', - 'EndOfSaleDate': 'end of sale', - 'EndOfSecurityVulSupportDate': 'end of service vulnerability support', - 'EndOfSWMaintenanceReleases': 'end of software maintenance releases', - 'EndOfRoutineFailureAnalysisDate': 'end of routine failure analysis', - } - - # check if date is about to change - for key in entry.keys(): - if key in EoL_dates and entry.get(key) != '': - change_days = (datetime.strptime(entry.get(key), '%Y-%m-%d').date() - datetime.now().date()).days - change_text = EoL_dates_desc.get(key, 'key not found') - if ((change_days < crit_change) or (change_days < warn_change)) and (change_days >= 0): - if output == '': - output =' EoX: is about to change.' - long_output += '\nEoX: PID: %s, bulletin ID: %s, %s: %s, product description: %s' % (pid, ProductBulletinNumber, change_text, entry.get(key), ProductIDDescription) - if change_days < crit_change: - status = max(2, status) - output = ' EoX: is about to change(!!)' - long_output += '(!!)' - else: - status = max(1, status) - long_output += '(!)' - if status == 1: - output = ' EoX: is about to change(!)' - - # check if new advisory - if EOXExternalAnnouncementDate != 'requested': - announcement_days = (datetime.now().date() - datetime.strptime(EOXExternalAnnouncementDate, '%Y-%m-%d').date()).days - if (announcement_days < crit_new) or (announcement_days < warn_new): - output = ' EoX: new announcement found.' - long_output += '\nEoX: new announcement found, announcement date: %s, bulletin ID: %s, PID: %s, product description: %s' % (EOXExternalAnnouncementDate, ProductBulletinNumber, pid, ProductIDDescription) - if announcement_days < crit_new: - status = max(2, status) - output += '(!!)' - else: - status = max(1, status) - output += '(!)' - - else: - if last_refresh > refresh_unknown: - if max_refresh_unknown < last_refresh: - max_refresh_unknown = last_refresh - - if (max_refresh_known != 0) or (max_refresh_unknown != 0): - output += ' EoX: no refresh(!)' - long_output = '\nEoX:' - status = max(1, status) - if max_refresh_known != 0: - long_output += ' refresh known: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_known, refresh_known) - if max_refresh_unknown != 0: - long_output += ' refresh unknown: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_unknown, refresh_unknown) - - return output, long_output, status - - -def check_psirt_status(apistatus, options, cmd_args): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - psirt_severity = {'critical': 1, - 'high': 2, - 'medium': 3, - 'low': 4. - } - - output = '' - long_output = '' - max_refresh_known = 0 - max_refresh_unknown = 0 - status = 0 - - last_checked = apistatus.get('Last_checked') - psirt_status = apistatus.get('status', 0) - lastrun = apistatus.get('lastrun', None) - last_refresh = (datetime.now().date() - datetime.strptime(last_checked, '%Y-%m-%d').date()).days - - refresh_found = options.get('refresh_found', 1) - refresh_notfound = options.get('refresh_notfound', 1) - warn_days = cmd_args.psirt_warn_days - crit_days = cmd_args.psirt_crit_days - warn_severity = cmd_args.psirt_warn_severity - crit_severity = cmd_args.psirt_crit_severity - - if (psirt_status == 'found') and (last_refresh > refresh_found): - max_refresh_known = last_refresh - elif (psirt_status == 'notfound') and (last_refresh > refresh_notfound): - max_refresh_unknown = last_refresh - - if lastrun is not None: - for entry in lastrun: - last_updated = entry.get('lastUpdated') - severity_txt = entry.get('sir', 'unkown') - severity = psirt_severity.get(severity_txt.lower(), 0) - last_updated = (datetime.now().date() - datetime.strptime(last_updated, '%Y-%m-%d').date()).days - if last_updated <= warn_days or last_updated <= crit_days: - if output == '': - output = ' PSIRT: new/updated security advisory found.' - long_output += '\nPSIRT: new/updated advisory, last updated: %s, severity: %s, title: %s' % (entry.get('lastUpdated'), severity_txt, entry.get('advisoryTitle')) - if (warn_severity >= severity or warn_severity == 0) and last_updated <= warn_days: - status = max(1, status) - long_output += '(!)' - if status == 1: - output = ' PSIRT: new/updated security advisory found(!)' - elif (crit_severity >= severity or crit_severity == 0) and last_updated <= crit_days: - status = max(2, status) - long_output += '(!!)' - output = ' PSIRT: new/updated security advisory found(!!)' - - if (max_refresh_known != 0) or (max_refresh_unknown != 0): - output += ' PISRT: no refresh(!)' - long_output = '\nPsirt:' - status = max(1, status) - if max_refresh_known != 0: - long_output += ' refresh found: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_known, refresh_found) - if max_refresh_unknown != 0: - long_output += ' refresh not found: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_unknown, refresh_notfound) - - return output, long_output, status - - -def check_sn2info_status(apistatus, options, cmd_args): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - output = '' - long_output = '' - status = 0 - max_refresh_covered = int(0) - max_refresh_notcovered = int(0) - lastrun = apistatus.get('lastrun') - - refresh_covered = options.get('refresh_covered', 31) - refresh_notcovered = options.get('refresh_notcovered', 7) - crit_change = cmd_args.sn2info_crit_change - warn_change = cmd_args.sn2info_warn_change - - for entry in lastrun: - last_checked = entry.get('Last_checked') - last_refresh = (datetime.now().date() - datetime.strptime(last_checked, '%Y-%m-%d').date()).days - if entry.get('is_covered') != 'NO': - if last_refresh > refresh_covered: - if max_refresh_covered < last_refresh: - max_refresh_covered = last_refresh - - serial_number = entry.get('serial_number') - contract_id = entry.get('service_contract_number') - pid = entry.get('pid') - ProductIDDescription = entry.get('ProductIDDescription') - - Contract_dates = ['covered_product_line_end_date', ] - Contract_dates_desc = {'covered_product_line_end_date': 'contract end date', - } - - # check if date is about to change - for key in entry.keys(): - if key in Contract_dates: - change_days = (datetime.strptime(entry.get(key), '%Y-%m-%d').date() - datetime.now().date()).days - change_text = Contract_dates_desc.get(key, 'key not found') - if ((change_days < crit_change) or (change_days < warn_change)) and (change_days >= 0): - if output == '': - output = ' Contract: is about to change.' - long_output += '\nContract: PID: %s, S/N: %s, contract ID: %s, %s: %s, product description: %s' % (pid, serial_number, contract_id, change_text, entry.get(key), ProductIDDescription) - if change_days < crit_change: - status = max(2, status) - long_output += '(!!)' - output = ' Contract: is about to change(!!)' - else: - status = max(1, status) - long_output += '(!)' - if status == 1: - output = ' Contract: is about to change(!)' - else: - if int(last_refresh) > int(refresh_notcovered): - if max_refresh_notcovered < last_refresh: - max_refresh_notcovered = last_refresh - - if (max_refresh_covered != 0) or (max_refresh_notcovered != 0): - output = ' SN2Info (contract): no refresh in time(!)' - long_output = '\nSN2Info (contract):' - status = max(1, status) - if max_refresh_covered != 0: - long_output += ' refresh covered: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_covered, refresh_covered) - if max_refresh_notcovered != 0: - long_output += ' refresh not covered: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_notcovered, refresh_notcovered) - - return output, long_output, status - - -def check_suggestion_status(apistatus, options, cmd_args): - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - output = '' - long_output = '' - status = 0 - max_refresh_known = 0 - max_refresh_unknown = 0 - lastrun = apistatus.get('lastrun') - refresh_known = options.get('refresh_found', 31) - refresh_unknown = options.get('refresh_notfound', 7) - - for entry in lastrun: - last_checked = entry.get('Last_checked') - last_refresh = (datetime.now().date() - datetime.strptime(last_checked, '%Y-%m-%d').date()).days - if entry.get('suggestion') != 'not found': - if last_refresh > refresh_known: - if max_refresh_known < last_refresh: - max_refresh_known = last_refresh - else: - if last_refresh > refresh_unknown: - if max_refresh_unknown < last_refresh: - max_refresh_unknown = last_refresh - - if (max_refresh_known != 0) or (max_refresh_unknown != 0): - output = ' Suggestion: no refresh(!)' - long_output = '\nSuggestion:' - status = max(1, status) - if max_refresh_known != 0: - long_output += ' refresh found: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_known, refresh_known) - if max_refresh_unknown != 0: - long_output += ' refresh not found: last refresh %d days ago, expected <= %d days(!)' % (max_refresh_unknown, refresh_unknown) - - return output, long_output, status - - -def main(): - logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(name)s %(message)s') - # set logg modul name <file>:<module>.<function> - logger = logging.getLogger(__file__ + ':' + __name__ + '.' + sys._getframe().f_code.co_name) - - conf_file = '~/etc/ciscoapi/ciscoapi.conf' - conf_file = os.path.expanduser(conf_file) - ciscoapistatus = '~/var/ciscoapi/status' - - opt_psirt = {} - opt_eox = {} - opt_sn2info = {} - opt_suggestion = {} - - status = 0 - output = '' - long_output = '' - apistatus = {} - - loglevel = 'warning' - - if os.path.isfile(conf_file): - configParser = ConfigParser.RawConfigParser() - configParser.read(conf_file) - if configParser.has_option('global', 'ciscoapistatus'): - ciscoapistatus = configParser.get('global', 'ciscoapistatus') - - if configParser.has_option('eox', 'eox_refresh_known'): - opt_eox.update({'refresh_known': int(configParser.get('eox', 'eox_refresh_known'))}) - if configParser.has_option('eox', 'eox_refresh_unknown'): - opt_eox.update({'refresh_unknown': int(configParser.get('eox', 'eox_refresh_unknown'))}) - - if configParser.has_option('psirt', 'psirt_refresh_found'): - opt_psirt.update({'refresh_found': int(configParser.get('psirt', 'psirt_refresh_found'))}) - if configParser.has_option('psirt', 'psirt_refresh_notfound'): - opt_psirt.update({'refresh_notfound': int(configParser.get('psirt', 'psirt_refresh_notfound'))}) - - if configParser.has_option('sn2info', 'sn2info_refresh_covered'): - opt_sn2info.update({'refresh_covered': int(configParser.get('sn2info', 'sn2info_refresh_covered'))}) - if configParser.has_option('sn2info', 'sn2info_refresh_notcovered'): - opt_sn2info.update({'refresh_notcovered': int(configParser.get('sn2info', 'sn2info_refresh_notcovered'))}) - - if configParser.has_option('suggestion', 'suggestion_refresh_found'): - opt_suggestion.update({'refresh_found': int(configParser.get('suggestion', 'suggestion_refresh_found'))}) - if configParser.has_option('suggestion', 'suggestion_refresh_notfound'): - opt_suggestion.update({'refresh_notfound': int(configParser.get('suggestion', 'suggestion_refresh_notfound'))}) - - if configParser.has_option('global', 'loglevel'): - loglevel = configParser.get('global', 'loglevel') - - numeric_level = getattr(logging, loglevel.upper(), None) - if not isinstance(numeric_level, int): - # set default loglevel if loglevel not valid - logging.getLogger().setLevel(logging.WARNING) - else: - logging.getLogger().setLevel(numeric_level) - - ciscoapistatus = expand_path(ciscoapistatus) - - os.unsetenv("LANG") - - parser = argparse.ArgumentParser() - parser.add_argument('TARGET', type=str, help='Host to check (exact name form CheckMK)') - parser.add_argument('--psirt-crit-days', type=int, default=0, help='set check status to critical if new/updated advisory not older then days, should be less then --psirt-warn-days') - parser.add_argument('--psirt-warn-days', type=int, default=0, help='set check status to warning if new/updated advisory not older then days') - parser.add_argument('--psirt-crit-severity', type=int, default=0, choices=[0, 1, 2, 3, 4], help='if new/updated advisory equal or above severity {All, Critical, High, Medium, Low} set check status to critical') - parser.add_argument('--psirt-warn-severity', type=int, default=0, choices=[0, 1, 2, 3, 4], help='if new/updated advisory equal or above severity {All, Critical, High, Medium, Low} set check status to warning, should be less then --psirt-crit-severity') - parser.add_argument('--psirt-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if PSIRT API is not active') - parser.add_argument('--eox-crit-new', type=int, default=0, help='set check status to critical if new announcement not older then days') - parser.add_argument('--eox-warn-new', type=int, default=0, help='set check status to warning if new announcement not older then days') - parser.add_argument('--eox-crit-change', type=int, default=0, help='set check status to critical if announcement is about to change in lees then days') - parser.add_argument('--eox-warn-change', type=int, default=0, help='set check status to warning if announcement is about to change in lees then days') - parser.add_argument('--eox-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if EoX API is not active') - parser.add_argument('--sn2info-crit-change', type=int, default=0, help='set check status to critical if contract is about to change in lees then days') - parser.add_argument('--sn2info-warn-change', type=int, default=0, help='set check status to warning if contract is about to change in lees then days') - parser.add_argument('--sn2info-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if sn2info API is not active') - parser.add_argument('--suggestion-not-active', type=int, choices=[0, 1, 2], help='set check status to {Ok, Warn, Crit} if suggestion API is not active') - - parser.parse_args() - cmd_args = parser.parse_args() - # print 'cmd_args: {}'.format(cmd_args) - - target = cmd_args.TARGET - not_active = [] - - eox_output = '' - eox_long_output = '' - eox_status = 0 - - sn2info_output = '' - sn2info_long_output = '' - sn2info_status = 0 - - suggestion_output = '' - suggestion_long_output = '' - suggestion_status = 0 - - psirt_output = '' - psirt_long_output = '' - psirt_status = 0 - - if os.path.isfile(ciscoapistatus + target): - output = 'Cisco API active.' - with open(ciscoapistatus + target) as f: - apistatus = json.load(f) - long_output = 'active API(s) found: ' + ', '.join(apistatus.keys()) - for key in apistatus.keys(): - if key == 'eox': - eox_output, eox_long_output, eox_status = check_eox_status(apistatus.get(key), opt_eox, cmd_args) - if key == 'psirt': - psirt_output, psirt_long_output, psirt_status = check_psirt_status(apistatus.get(key), opt_psirt, cmd_args) - if key == 'sn2info': - sn2info_output, sn2info_long_output, sn2info_status = check_sn2info_status(apistatus.get(key), opt_sn2info, cmd_args) - if key == 'suggestion': - suggestion_output, suggestion_long_output, suggestion_status = check_suggestion_status(apistatus.get(key), opt_suggestion, cmd_args) - - long_output += eox_long_output + sn2info_long_output + psirt_long_output + suggestion_long_output + '\n' - - output += eox_output + sn2info_output + psirt_output + suggestion_output - - status = max(eox_status, status) - status = max(sn2info_status, status) - status = max(psirt_status, status) - status = max(suggestion_status, status) - - if status > 0: - output += ' (see long output for details)' - - if cmd_args.psirt_not_active is not None and ('psirt' not in apistatus.keys()): - status = max(status, cmd_args.psirt_not_active) - not_active.append('PSIRT') - - if cmd_args.eox_not_active is not None and ('eox' not in apistatus.keys()): - status = max(status, cmd_args.eox_not_active) - not_active.append('EoX') - - if cmd_args.sn2info_not_active is not None and ('sn2info' not in apistatus.keys()): - status = max(status, cmd_args.sn2info_not_active) - not_active.append('SN2INFO') - - if cmd_args.suggestion_not_active is not None and ('suggestion' not in apistatus.keys()): - status = max(status, cmd_args.suggestion_not_active) - not_active.append('SUGGESTION') - - if len(not_active) > 0: - output += ' Not active API(s): {}'.format(', '.join(not_active)) - else: - output = 'Cisco API not active(!)' - status = max(1, status) - - sys.stdout.write(output + '\n' + long_output) - sys.exit(status) - -main() -