Subversion Repositories vnag

Rev

Rev 4 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4 Rev 52
1
<?php /* <ViaThinkSoftSignature>
1
<?php /* <ViaThinkSoftSignature>
2
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
23
w==
23
A==
24
</ViaThinkSoftSignature> */ ?>
24
</ViaThinkSoftSignature> */ ?>
25
<?php
25
<?php
26
 
26
 
27
/*
27
/*
28
 * VNag - Nagios Framework for PHP
28
 * VNag - Nagios Framework for PHP
29
 * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
29
 * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
30
 * Licensed under the terms of the Apache 2.0 license
30
 * Licensed under the terms of the Apache 2.0 license
31
 *
31
 *
32
 * Revision 2018-07-16
32
 * Revision 2018-07-16
33
 */
33
 */
34
 
34
 
35
declare(ticks=1);
35
declare(ticks=1);
36
 
36
 
37
class X509ExpireCheck extends VNag {
37
class X509ExpireCheck extends VNag {
38
        protected $argFiles = null;
38
        protected $argFiles = null;
39
 
39
 
40
        public function __construct() {
40
        public function __construct() {
41
                parent::__construct();
41
                parent::__construct();
42
 
42
 
43
                $this->registerExpectedStandardArguments('Vhtwcv');
43
                $this->registerExpectedStandardArguments('Vhtwcv');
44
 
44
 
45
                $this->getHelpManager()->setPluginName('check_x509_expire');
45
                $this->getHelpManager()->setPluginName('check_x509_expire');
46
                $this->getHelpManager()->setVersion('1.0');
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.');
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.');
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>" [...]]');
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');
50
                $this->getHelpManager()->setFootNotes('If you encounter bugs, please contact ViaThinkSoft at www.viathinksoft.com');
51
 
51
 
52
                // Individual (non-standard) arguments:
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.'));
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
 
54
 
55
                // In this context, when the user writes "-w 60s" then he actually means "-w @~:60s" or "-w 60s:~", so these commands allow this notation:
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;
56
                $this->warningSingleValueRangeBehaviors[0]  = self::SINGLEVALUE_RANGE_VAL_LT_X_BAD;
57
                $this->criticalSingleValueRangeBehaviors[0] = self::SINGLEVALUE_RANGE_VAL_LT_X_BAD;
57
                $this->criticalSingleValueRangeBehaviors[0] = self::SINGLEVALUE_RANGE_VAL_LT_X_BAD;
58
        }
58
        }
59
 
59
 
60
        private static function humanFriendlyTimeLeft($secs) {
60
        private static function humanFriendlyTimeLeft($secs) {
61
                $out = array();
61
                $out = array();
62
 
62
 
63
                if ($expired = $secs < 0) $secs *= -1;
63
                if ($expired = $secs < 0) $secs *= -1;
64
 
64
 
65
                $years = floor($secs / 60 / 60 / 24 / 365);
65
                $years = floor($secs / 60 / 60 / 24 / 365);
66
                if ($years > 0) $out[] = $years == 1 ? "$years year" : "$years years";
66
                if ($years > 0) $out[] = $years == 1 ? "$years year" : "$years years";
67
 
67
 
68
                $days = floor($secs / 60 / 60 / 24) % 365;
68
                $days = floor($secs / 60 / 60 / 24) % 365;
69
                if ($days > 0) $out[] = $days == 1 ? "$days day" : "$days days";
69
                if ($days > 0) $out[] = $days == 1 ? "$days day" : "$days days";
70
 
70
 
71
                $hours = floor($secs / 60 / 60) % 24;
71
                $hours = floor($secs / 60 / 60) % 24;
72
                if ($hours > 0) $out[] = $hours == 1 ? "$hours hour" : "$hours hours";
72
                if ($hours > 0) $out[] = $hours == 1 ? "$hours hour" : "$hours hours";
73
 
73
 
74
                $minutes = floor($secs / 60) % 60;
74
                $minutes = floor($secs / 60) % 60;
75
                if ($minutes > 0) $out[] = $minutes == 1 ? "$minutes minute" : "$minutes minutes";
75
                if ($minutes > 0) $out[] = $minutes == 1 ? "$minutes minute" : "$minutes minutes";
76
 
76
 
77
                $seconds = $secs % 60;
77
                $seconds = $secs % 60;
78
                if ($seconds > 0) $out[] = $seconds == 1 ? "$seconds second" : "$seconds seconds";
78
                if ($seconds > 0) $out[] = $seconds == 1 ? "$seconds second" : "$seconds seconds";
79
 
79
 
80
                return ($expired ? 'EXPIRED SINCE ' : '').implode(", ", $out).($expired ? '' : ' left');
80
                return ($expired ? 'EXPIRED SINCE ' : '').implode(", ", $out).($expired ? '' : ' left');
81
        }
81
        }
82
 
82
 
83
        private static function timeLeft($pemFile) {
83
        private static function timeLeft($pemFile) {
84
                $out = array();
84
                $out = array();
85
 
85
 
86
                // TODO: Call PHP's openssl functions instead
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
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) {
88
                if ($code != 0) {
89
                        throw new VNagException("Error calling openssl!");
89
                        throw new VNagException("Error calling openssl!");
90
                }
90
                }
91
 
91
 
92
                $tim = strtotime($out[0]);
92
                $tim = strtotime($out[0]);
93
                return $tim - time();
93
                return $tim - time();
94
        }
94
        }
95
 
95
 
96
        protected function cbRun($optional_args=array()) {
96
        protected function cbRun($optional_args=array()) {
97
                $this->argFiles->require();
97
                $this->argFiles->require();
98
 
98
 
99
                $countFilesTotal = 0;
99
                $countFilesTotal = 0;
100
                $countFilesCrit = 0;
100
                $countFilesCrit = 0;
101
                $countFilesWarn = 0;
101
                $countFilesWarn = 0;
102
 
102
 
103
                $fileGroupMasks = $this->argFiles->getValue();
103
                $fileGroupMasks = $this->argFiles->getValue();
104
                if (!is_array($fileGroupMasks)) $fileGroupMasks = array($fileGroupMasks);
104
                if (!is_array($fileGroupMasks)) $fileGroupMasks = array($fileGroupMasks);
105
                foreach ($fileGroupMasks as $fileGroupMask) {
105
                foreach ($fileGroupMasks as $fileGroupMask) {
106
                        if (substr($fileGroupMask, 0, 1) === '#') {
106
                        if (substr($fileGroupMask, 0, 1) === '#') {
107
                                $fileGroupMask = substr($fileGroupMask, 1); // remove #
107
                                $fileGroupMask = substr($fileGroupMask, 1); // remove #
108
 
108
 
109
                                // Mode 1: Only the youngest file of each group is checked.
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
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
111
                                // and you want to check if a downloading-script is still downloading
112
                                // new files regularly.
112
                                // new files regularly.
113
 
113
 
114
                                $files = glob($fileGroupMask);
114
                                $files = glob($fileGroupMask);
115
                                if (count($files) == 0) continue;
115
                                if (count($files) == 0) continue;
116
 
116
 
117
                                $minTimeLeft = null;
117
                                $minTimeLeft = null;
118
                                foreach ($files as $file) {
118
                                foreach ($files as $file) {
119
                                        $minTimeLeft = is_null($minTimeLeft) ? filemtime($file) : min($minTimeLeft, self::timeLeft($file));
119
                                        $minTimeLeft = is_null($minTimeLeft) ? filemtime($file) : min($minTimeLeft, self::timeLeft($file));
120
                                }
120
                                }
121
 
121
 
122
                                $countFilesTotal++;
122
                                $countFilesTotal++;
123
                                if ($this->checkAgainstCriticalRange($minTimeLeft.'s', false, true)) {
123
                                if ($this->checkAgainstCriticalRange($minTimeLeft.'s', false, true)) {
124
                                        $countFilesCrit++;
124
                                        $countFilesCrit++;
125
                                        $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (Critical)\n", VNag::VERBOSITY_SUMMARY);
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)) {
126
                                } else if ($this->checkAgainstWarningRange($minTimeLeft.'s', false, true)) {
127
                                        $countFilesWarn++;
127
                                        $countFilesWarn++;
128
                                        $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
128
                                        $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
129
                                } else {
129
                                } else {
130
                                        if (($this->getArgumentHandler()->getArgumentObj('w')->available()) || ($this->getArgumentHandler()->getArgumentObj('c')->available())) {
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);
131
                                                $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)." (OK)\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
132
                                        } else {
132
                                        } else {
133
                                                $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
133
                                                $this->addVerboseMessage("File group '$fileGroupMask' oldest file: ".self::humanFriendlyTimeLeft($minTimeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
134
                                        }
134
                                        }
135
                                }
135
                                }
136
                        } else {
136
                        } else {
137
                                // Mode 2: All files of each group are checked.
137
                                // Mode 2: All files of each group are checked.
138
 
138
 
139
                                $files = glob($fileGroupMask);
139
                                $files = glob($fileGroupMask);
140
                                if (count($files) == 0) continue;
140
                                if (count($files) == 0) continue;
141
 
141
 
142
                                foreach ($files as $file) {
142
                                foreach ($files as $file) {
143
                                        $timeLeft = self::timeLeft($file);
143
                                        $timeLeft = self::timeLeft($file);
144
                                        $countFilesTotal++;
144
                                        $countFilesTotal++;
145
                                        if ($this->checkAgainstCriticalRange($timeLeft.'s', false, true)) {
145
                                        if ($this->checkAgainstCriticalRange($timeLeft.'s', false, true)) {
146
                                                $countFilesCrit++;
146
                                                $countFilesCrit++;
147
                                                $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Critical)\n", VNag::VERBOSITY_SUMMARY);
147
                                                $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Critical)\n", VNag::VERBOSITY_SUMMARY);
148
                                        } else if ($this->checkAgainstWarningRange($timeLeft.'s', false, true)) {
148
                                        } else if ($this->checkAgainstWarningRange($timeLeft.'s', false, true)) {
149
                                                $countFilesWarn++;
149
                                                $countFilesWarn++;
150
                                                $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
150
                                                $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (Warning)\n", VNag::VERBOSITY_SUMMARY);
151
                                        } else {
151
                                        } else {
152
                                                if (($this->getArgumentHandler()->getArgumentObj('w')->available()) || ($this->getArgumentHandler()->getArgumentObj('c')->available())) {
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);
153
                                                        $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)." (OK)\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
154
                                                } else {
154
                                                } else {
155
                                                        $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
155
                                                        $this->addVerboseMessage("File $file: ".self::humanFriendlyTimeLeft($timeLeft)."\n", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
156
                                                }
156
                                                }
157
                                        }
157
                                        }
158
                                }
158
                                }
159
                        }
159
                        }
160
                }
160
                }
161
 
161
 
162
                $msg = array();
162
                $msg = array();
163
                $msg[] = "Checked $countFilesTotal certificates";
163
                $msg[] = "Checked $countFilesTotal certificates";
164
                if ($this->getArgumentHandler()->getArgumentObj('w')->available()) $msg[] = "$countFilesWarn are in warning time range";
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";
165
                if ($this->getArgumentHandler()->getArgumentObj('c')->available()) $msg[] = "$countFilesCrit are in critical time range";
166
                $msg = implode(", ", $msg);
166
                $msg = implode(", ", $msg);
167
 
167
 
168
                $this->setHeadLine($msg);
168
                $this->setHeadLine($msg);
169
        }
169
        }
170
}
170
}
171
 
171