Subversion Repositories vnag

Rev

Rev 4 | Blame | Last modification | View Log | RSS feed

  1. <?php /* <ViaThinkSoftSignature>
  2. boKKZRVCLt6Pij9GtZwVtVRcuFrDhyTKij4SbspGGs+24F0eeo10iC1wBP05mJ7tL
  3. WS8JfFSlv7vQDBcdd6sMF+vYQNldSznrK47dbZzQXFxuq26jd6BuuH41aP2pWHv57
  4. XVCpYf5EPR0gFkyXzrtN/iFSr0kJKWk5iSz/iniucplPitxmXR0EN1qkKmcZgTon7
  5. hKIjq3kb8RY6U4BFcXujRq7M/SlRvub2erQiWxPv3wKi+CQPRcCvq33/g7bPOTSpY
  6. 1WFCt+3zkCfQUomU27Y7/GSW1V+7T8DjAWUhR4rxO5nXyTx3vxqmv9UjfkKpTUVc/
  7. TjhyS0mZ78rYX2HYW3+NBQQMMWfGlLKvuhHdJFU2dB9+YvW4Krm/N7xTcwKos3Aho
  8. vSlnVHDf48KSXN/gPMKC7U3mOH8RB2oyiLJBX42CE+N30Ui+3TyxAj2/YMAjzDPYP
  9. 8b+yRhntXzvGX3wayFPcjBHBBWrchJ6JnERCewVW+/3vDKgjwHhnul4Y/lme79jNA
  10. 1Oj0ZX6rCGow+7z3he7/0ec92Rr8NOE8p7mrQn9iofTZcfFo2i5RDy+6raUvSi/Fp
  11. 2DP2HqwOGp2uHrFemzo9NepjH2DgnK5zMMRR1Q2hMksAsviWMWTUv0fkYZZSsi1LA
  12. aROWE4CRaEhBuvt0bRIrJGZUbBWvxOE67CVYXHF20YvyKoI5IUN/ZOI2iCLMr+ss2
  13. wrB5tW4ovYwsjV5nDAK1bg1hsdOKx5xv7PchfhUkAn1J3DoekDl9qECt3LKdKG2hl
  14. ZwB/HrnuByxgab30wLUFsELT9v/pKJW6/2TFkWEfYw43MQzpsmKs/h0qTKW691GkW
  15. htPhMbMpSCxgDGloU4z7EcMdnvTEM4ol1GyDn7NZlYhgEHfw+X/5CZNTYH5DJvt8J
  16. K+aQaZFiZDHa8GaI7NyGERRk34C90lL7pgFEhaNGCFl+Z+YGegxwMjKbFo1xH0YNk
  17. CMPYX9GGZIEMTTNEySCyuZsDvXpXK5CbQ8ywuZ9/B0avnUWrBBPLh9RchB07S6kA/
  18. EcH71AxGafK8wDMrPzymdFVsHpwNp6FEvP/EpBHGv0x4/gYpPomUOxmy7uEE1dzdB
  19. talRGPLAt8a/RXXG3ECsjgo3zDzmc8VYx6m4BPXvLsDX1b9NjN34AtBObE+iLLC3A
  20. wMd4oQSnOwfDDYNdKg08s43j5m+SQ+HRGQqgGb9A6IcwxuHR9bTidXBgNORbbdjXf
  21. 9I1QW1Za0l5khdpDF/smNPMIwidcg2xBi7faHY/aOpzWTcTviox1ujPJmwaLr0I0l
  22. DYFlTNaQ0wM+UBE501Lwss8gscs4duuSlBHQLA+ddOKWSd92/KK/JW3uf67rOaqfy
  23. A==
  24. </ViaThinkSoftSignature> */ ?>
  25. <?php
  26.  
  27. /*
  28.  * VNag - Nagios Framework for PHP
  29.  * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
  30.  * Licensed under the terms of the Apache 2.0 license
  31.  *
  32.  * Revision 2018-07-16
  33.  */
  34.  
  35. declare(ticks=1);
  36.  
  37. class X509ExpireCheck extends VNag {
  38.         protected $argFiles = null;
  39.  
  40.         public function __construct() {
  41.                 parent::__construct();
  42.  
  43.                 $this->registerExpectedStandardArguments('Vhtwcv');
  44.  
  45.                 $this->getHelpManager()->setPluginName('check_x509_expire');
  46.                 $this->getHelpManager()->setVersion('1.0');
  47.                 $this->getHelpManager()->setShortDescription('This plugin checks X.509 (PEM) files and warns if certificates are about to expire.');
  48.                 $this->getHelpManager()->setCopyright('Copyright (C) 2011-$CURYEAR$ Daniel Marschall, ViaThinkSoft.');
  49.                 $this->getHelpManager()->setSyntax('$SCRIPTNAME$ [-v] -w <warnSeconds>s -c <critSeconds>s -f "[#]<mask>" [-f "[#]<mask>" [...]]');
  50.                 $this->getHelpManager()->setFootNotes('If you encounter bugs, please contact ViaThinkSoft at www.viathinksoft.com');
  51.  
  52.                 // Individual (non-standard) arguments:
  53.                 $this->addExpectedArgument($this->argFiles = new VNagArgument('f', 'file', VNagArgument::VALUE_REQUIRED, 'mask', 'The files to be checked. This argument can be used multiple times. Wilcards may be used but MUST be passed as string only (not resolved by the Shell). There are two possible checking modes: If you put a # in front of the file mask, only the oldest file of each group will be checked (use this mode e.g. if you have a directory which contains old backups of certificates beside the current working certificate). Otherwise, all files of the file group are checked.'));
  54.  
  55.                 // In this context, when the user writes "-w 60s" then they probably mean "-w @60s". Make sure that the user doesn't do it wrong
  56.                 $this->warningSingleValueRangeBehaviors[0]  = self::SINGLEVALUE_RANGE_VAL_LT_X_BAD;
  57.                 $this->criticalSingleValueRangeBehaviors[0] = self::SINGLEVALUE_RANGE_VAL_LT_X_BAD;
  58.         }
  59.  
  60.         private static function humanFriendlyTimeLeft($secs) {
  61.                 $out = array();
  62.  
  63.                 if ($expired = $secs < 0) $secs *= -1;
  64.  
  65.                 $years = floor($secs / 60 / 60 / 24 / 365);
  66.                 if ($years > 0) $out[] = $years == 1 ? "$years year" : "$years years";
  67.  
  68.                 $days = floor($secs / 60 / 60 / 24) % 365;
  69.                 if ($days > 0) $out[] = $days == 1 ? "$days day" : "$days days";
  70.  
  71.                 $hours = floor($secs / 60 / 60) % 24;
  72.                 if ($hours > 0) $out[] = $hours == 1 ? "$hours hour" : "$hours hours";
  73.  
  74.                 $minutes = floor($secs / 60) % 60;
  75.                 if ($minutes > 0) $out[] = $minutes == 1 ? "$minutes minute" : "$minutes minutes";
  76.  
  77.                 $seconds = $secs % 60;
  78.                 if ($seconds > 0) $out[] = $seconds == 1 ? "$seconds second" : "$seconds seconds";
  79.  
  80.                 return ($expired ? 'EXPIRED SINCE ' : '').implode(", ", $out).($expired ? '' : ' left');
  81.         }
  82.  
  83.         private static function timeLeft($pemFile) {
  84.                 $out = array();
  85.  
  86.                 // TODO: Call PHP's openssl functions instead
  87.                 exec("openssl x509 -in ".escapeshellarg($pemFile)." -noout -text | grep \"Not After\" | cut -d ':' -f 2-", $out, $code); // TODO: check $code
  88.                 if ($code != 0) {
  89.                         throw new VNagException("Error calling openssl!");
  90.                 }
  91.  
  92.                 $tim = strtotime($out[0]);
  93.                 return $tim - time();
  94.         }
  95.  
  96.         protected function cbRun($optional_args=array()) {
  97.                 $this->argFiles->require();
  98.  
  99.                 $countFilesTotal = 0;
  100.                 $countFilesCrit = 0;
  101.                 $countFilesWarn = 0;
  102.  
  103.                 $fileGroupMasks = $this->argFiles->getValue();
  104.                 if (!is_array($fileGroupMasks)) $fileGroupMasks = array($fileGroupMasks);
  105.                 foreach ($fileGroupMasks as $fileGroupMask) {
  106.                         if (substr($fileGroupMask, 0, 1) === '#') {
  107.                                 $fileGroupMask = substr($fileGroupMask, 1); // remove #
  108.  
  109.                                 // Mode 1: Only the youngest file of each group is checked.
  110.                                 // You can use this mode e.g. if you have a folder with downloaded files
  111.                                 // and you want to check if a downloading-script is still downloading
  112.                                 // new files regularly.
  113.  
  114.                                 $files = glob($fileGroupMask);
  115.                                 if (count($files) == 0) continue;
  116.  
  117.                                 $minTimeLeft = null;
  118.                                 foreach ($files as $file) {
  119.                                         $minTimeLeft = is_null($minTimeLeft) ? filemtime($file) : min($minTimeLeft, self::timeLeft($file));
  120.                                 }
  121.  
  122.                                 $countFilesTotal++;
  123.                                 if ($this->checkAgainstCriticalRange($minTimeLeft.'s', false, true)) {
  124.                                         $countFilesCrit++;
  125.                                         $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (Critical)\n", VNag::VERBOSITY_SUMMARY);
  126.                                 } else if ($this->checkAgainstWarningRange($minTimeLeft.'s', false, true)) {
  127.                                         $countFilesWarn++;
  128.                                         $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
  129.                                 } else {
  130.                                         if (($this->getArgumentHandler()->getArgumentObj('w')->available()) || ($this->getArgumentHandler()->getArgumentObj('c')->available())) {
  131.                                                 $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (OK)\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
  132.                                         } else {
  133.                                                 $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
  134.                                         }
  135.                                 }
  136.                         } else {
  137.                                 // Mode 2: All files of each group are checked.
  138.  
  139.                                 $files = glob($fileGroupMask);
  140.                                 if (count($files) == 0) continue;
  141.  
  142.                                 foreach ($files as $file) {
  143.                                         $timeLeft = self::timeLeft($file);
  144.                                         $countFilesTotal++;
  145.                                         if ($this->checkAgainstCriticalRange($timeLeft.'s', false, true)) {
  146.                                                 $countFilesCrit++;
  147.                                                 $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Critical)\n", VNag::VERBOSITY_SUMMARY);
  148.                                         } else if ($this->checkAgainstWarningRange($timeLeft.'s', false, true)) {
  149.                                                 $countFilesWarn++;
  150.                                                 $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
  151.                                         } else {
  152.                                                 if (($this->getArgumentHandler()->getArgumentObj('w')->available()) || ($this->getArgumentHandler()->getArgumentObj('c')->available())) {
  153.                                                         $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (OK)\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
  154.                                                 } else {
  155.                                                         $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
  156.                                                 }
  157.                                         }
  158.                                 }
  159.                         }
  160.                 }
  161.  
  162.                 $msg = array();
  163.                 $msg[] = "Checked $countFilesTotal certificates";
  164.                 if ($this->getArgumentHandler()->getArgumentObj('w')->available()) $msg[] = "$countFilesWarn are in warning time range";
  165.                 if ($this->getArgumentHandler()->getArgumentObj('c')->available()) $msg[] = "$countFilesCrit are in critical time range";
  166.                 $msg = implode(", ", $msg);
  167.  
  168.                 $this->setHeadLine($msg);
  169.         }
  170. }
  171.