Skip to content
Snippets Groups Projects
Commit 9bf05053 authored by hahn's avatar hahn
Browse files

add ssl check in apmonitor client

parent da210d43
Branches
No related tags found
No related merge requests found
......@@ -23,6 +23,7 @@ define("RESULT_ERROR", 3);
* 2014-10-24 0.5 axel.hahn@iml.unibe.ch<br>
* 2015-04-08 0.9 axel.hahn@iml.unibe.ch added sochket test: checkPortTcp<br>
* 2018-06-29 0.24 axel.hahn@iml.unibe.ch add file and directory checks<br>
* 2018-07-17 0.42 axel.hahn@iml.unibe.ch add port on mysqli check<br>
* --------------------------------------------------------------------------------<br>
* @version 0.9
* @author Axel Hahn
......@@ -47,6 +48,10 @@ class appmonitorcheck {
* @var array
*/
private $_aData = array();
// protected $_units = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
protected $_units = array( 'B', 'KB', 'MB', 'GB', 'TB');
// ----------------------------------------------------------------------
// CONSTRUCTOR
......@@ -195,46 +200,216 @@ class appmonitorcheck {
// CHECK FUNCTIONS (private)
// ----------------------------------------------------------------------
/**
* helper function: read certificate data
* called in checkCert()
* @param string $sUrl url to connect
* @return array
*/
protected function _certGetInfos($sUrl) {
$iTimeout=10;
$aUrldata=parse_url($sUrl);
$sHost = isset($aUrldata['host']) ? $aUrldata['host'] : false;
$iPort = isset($aUrldata['port']) ? $aUrldata['port'] : ((isset($aUrldata['scheme']) && $aUrldata['scheme'] === 'https') ? 443 : false);
$get = stream_context_create(array("ssl" => array("capture_peer_cert" => TRUE)));
if(!$get){
return array('_error' => 'Error: Cannot create stream_context');
}
$errno=-1;
$errstr="stream_socket_client failed.";
$read = stream_socket_client("ssl://$sHost:$iPort", $errno, $errstr, $iTimeout, STREAM_CLIENT_CONNECT, $get);
if(!$read){
return array('_error' => "Error $errno: $errstr; cannot create stream_context to ssl://$sHost:$iPort");
}
$cert = stream_context_get_params($read);
if(!$cert){
return array('_error' => "Error: socket was connected to ssl://$sHost:$iPort - but I cannot read certificate infos with stream_context_get_params ");
}
$certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
return $certinfo;
}
/**
* check SSL certificate
* @param array $aParams
* array(
* "url" optional: url to connect check; default: own protocol + server
* "warning" optional: count of days to warn; default=30
* )
* @return boolean
*/
public function checkCert($aParams) {
$sUrl = isset($aParams["url"])
? $aParams["url"]
: 'http'. ($_SERVER['HTTPS'] ? 's' : '') . '://' . $_SERVER['SERVER_NAME'] .':' . $_SERVER['SERVER_PORT']
;
$iWarn = isset($aParams["warning"]) ? (int)($aParams["warning"]) : 30;
$sMessage="url $sUrl ... ";
$certinfo=$this->_certGetInfos($sUrl);
if(isset($certinfo['_error'])){
$this->_setReturn(RESULT_ERROR, $certinfo['_error'] . $sMessage);
return true;
}
$sDNS=isset($certinfo['extensions']['subjectAltName']) ? $certinfo['extensions']['subjectAltName'] : false;
$sHost=parse_url($url,PHP_URL_HOST);
if(strstr($sDNS, 'DNS:'.$sHost)===false){
$aReturn['errors'][]="Domainname $sHost ist nicht als DNS ALias im Zertifikat enthalten.";
$this->_setReturn(RESULT_ERROR, 'Wrong certificate: '.$sHost.' is not listed as DNS alias in ['.$sDNS.'] ' . $sMessage);
return true;
}
$iDaysleft = round(($certinfo['validTo_time_t'] - date('U')) / 60 / 60 / 24);
$sMessage.= 'Issuer: '. $sIssuer=$certinfo['issuer']['O']
. ' valid from: '. date("Y-m-d H:i", $certinfo['validFrom_time_t'])
. ' to '.date("Y-m-d H:i", $certinfo['validTo_time_t']).' '
. ( $iDaysleft ? "($iDaysleft days left)" : "expired since ".(-$iDaysleft)." days.")
;
if ($iDaysleft<0) {
$this->_setReturn(RESULT_ERROR, 'Expired ' . $sMessage);
return true;
}
if ($iDaysleft<=$iWarn) {
$this->_setReturn(RESULT_WARNING, 'Expires soon ' . $sMessage);
return true;
}
// echo '<pre>';
$this->_setReturn(RESULT_OK, 'OK, is valid ' . $sMessage);
return true;
}
/**
* get human readable space value
* @param type $size
* @return string
*/
protected function _getHrSize($size){
$power = $size > 0 ? floor(log($size, 1024)) : 0;
return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $this->_units[$power];
}
/**
* get a space in a real value if an integer has added MB|GB|...
* @param type $sValue
* @return integer
*/
protected function _getSize($sValue){
if(is_int($sValue)){
return $sValue;
}
$power=0;
foreach($this->_units as $sUnit){
if (preg_match('/^[0-9\.]*'.$sUnit.'/', $sValue)){
$i=preg_replace('/([0-9\.]*).*/', '$1', $sValue);
$iReal=$i*pow(1024, $power);
// die("FOUND: $sValue with unit ${sUnit} - 1024^$power * $i = $iReal");
return $iReal;
}
$power++;
}
header('HTTP/1.0 503 Service Unavailable');
die("ERROR in space value parameter - there is no size unit in [$sValue] - allowed size units are " . implode('|', $this->_units));
return false;
}
/**
* check free disk space on a given directory
* @param array $aParams
* array(
* "directory" directory that must exist
* "warning" space for warning (optional)
* "critical" minimal space
* )
* @return boolean
*/
public function checkDiskfree($aParams) {
$this->_checkArrayKeys($aParams, "directory", "critical");
$sDirectory = $aParams["directory"];
if(!is_dir($sDirectory)){
$this->_setReturn(RESULT_ERROR, 'directory [' . $sDirectory . '] does not exist. Maybe it is wrong or is not mounted.');
return true;
}
$iWarn = isset($aParams["warning"]) ? $this->_getSize($aParams["warning"]) : false;
$iCritical = $this->_getSize($aParams["critical"]);
$iSpaceLeft=disk_free_space($sDirectory);
$sMessage='[' . $sDirectory . '] has '.$this->_getHrSize($iSpaceLeft).' left.';
if($iWarn){
if($iWarn<=$iCritical){
header('HTTP/1.0 503 Service Unavailable');
die("ERROR in a Diskfree check - warning value must be larger than critical.<pre>" . print_r($aParams, true));
}
if ($iWarn<$iSpaceLeft){
$this->_setReturn(RESULT_OK, $sMessage.' Warning level is not reached yet (still '.$this->_getHrSize($iSpaceLeft-$iWarn).' over warning limit).');
return true;
}
if ($iWarn>$iSpaceLeft && $iCritical<$iSpaceLeft){
$this->_setReturn(RESULT_WARNING, $sMessage.' Warning level '.$this->_getHrSize($iWarn).' was reached (space is '.$this->_getHrSize($iWarn-$iSpaceLeft).' below warning limit; still '.$this->_getHrSize($iSpaceLeft-$iCritical).' over critical limit).');
return true;
}
}
// check space
if ($iCritical<$iSpaceLeft){
$this->_setReturn(RESULT_OK, $sMessage .' Minimum is not reached yet (still '.$this->_getHrSize($iSpaceLeft-$iCritical).' over critical limit).');
} else {
$this->_setReturn(RESULT_ERROR, $sMessage);
}
return true;
}
/**
* check a file
* @param array $aParams
* array(
* "filename" directory that must exist
* "writable" flag to check that it must be writable too
* "filename" directory that must exist
* "exists" "filename" must exist/ must be absent
* "dir" filetype directory
* "file" filetype file
* "link" filetype symbolic link
* "executable" flag executable
* "readable" flag is readable
* "writable" flag is writable
* )
* @return boolean
*/
public function checkFile($aParams) {
$aOK=array();
$aErrors=array();
$aOK = array();
$aErrors = array();
$this->_checkArrayKeys($aParams, "filename");
$sFile=$aParams["filename"];
if (isset($aParams['exists'])){
$sMyflag='exists='.($aParams['exists'] ? 'yes' : 'no');
if (file_exists($sFile) && $aParams['exists']){
$aOK[]=$sMyflag;
$sFile = $aParams["filename"];
if (isset($aParams['exists'])) {
$sMyflag = 'exists=' . ($aParams['exists'] ? 'yes' : 'no');
if (file_exists($sFile) && $aParams['exists']) {
$aOK[] = $sMyflag;
} else {
$aErrors[]=$sMyflag;
$aErrors[] = $sMyflag;
}
}
foreach(array('dir', 'executable', 'file', 'link', 'readable', 'writable') as $sFiletest){
if (isset($aParams[$sFiletest])){
$sTestCmd='return is_'.$sFiletest.'("'.$sFile.'");';
if (eval($sTestCmd) && $aParams[$sFiletest]){
$aOK[]=$sFiletest . '='.($aParams[$sFiletest] ? 'yes' : 'no');
foreach (array('dir', 'executable', 'file', 'link', 'readable', 'writable') as $sFiletest) {
if (isset($aParams[$sFiletest])) {
$sTestCmd = 'return is_' . $sFiletest . '("' . $sFile . '");';
if (eval($sTestCmd) && $aParams[$sFiletest]) {
$aOK[] = $sFiletest . '=' . ($aParams[$sFiletest] ? 'yes' : 'no');
} else {
$aErrors[]=$sFiletest . '='.($aParams[$sFiletest] ? 'yes' : 'no');
$aErrors[] = $sFiletest . '=' . ($aParams[$sFiletest] ? 'yes' : 'no');
}
}
}
$sMessage=(count($aOK) ? ' flags OK: ' .implode('|', $aOK) : '')
.' '. (count($aErrors) ? ' flags FAILED: '.implode('|', $aErrors) : '')
;
if(count($aErrors)){
$this->_setReturn(RESULT_ERROR, 'file test ['. $sFile . '] '.$sMessage);
$sMessage = (count($aOK) ? ' flags OK: ' . implode('|', $aOK) : '')
. ' ' . (count($aErrors) ? ' flags FAILED: ' . implode('|', $aErrors) : '')
;
if (count($aErrors)) {
$this->_setReturn(RESULT_ERROR, 'file test [' . $sFile . '] ' . $sMessage);
} else {
$this->_setReturn(RESULT_OK, 'file test ['. $sFile . '] '.$sMessage);
$this->_setReturn(RESULT_OK, 'file test [' . $sFile . '] ' . $sMessage);
}
return true;
}
......@@ -281,15 +456,20 @@ class appmonitorcheck {
* "user"
* "password"
* "db"
* "port" <<< optional
* )
*/
private function checkMysqlConnect($aParams) {
$this->_checkArrayKeys($aParams, "server,user,password,db");
if (!isset($aParams["port"])) {
$aParams["port"] = false;
}
$db = mysqli_connect(
$aParams["server"], $aParams["user"], $aParams["password"], $aParams["db"]
$aParams["server"], $aParams["user"], $aParams["password"], $aParams["db"], $aParams["port"]
);
if ($db) {
$this->_setReturn(RESULT_OK, "OK: Mysql database " . $aParams["db"] . " was connected");
mysqli_close($db);
return true;
} else {
$this->_setReturn(RESULT_ERROR, "ERROR: Mysql database " . $aParams["db"] . " was not connected. " . mysqli_connect_error());
......@@ -334,7 +514,11 @@ class appmonitorcheck {
/**
* most simple check: set values
* @return type
* @param array $aParams
* array(
* "result" integer; RESUL_nn
* "value" description text
* )
*/
private function checkSimple($aParams) {
$this->_checkArrayKeys($aParams, "result,value");
......@@ -345,7 +529,7 @@ class appmonitorcheck {
* check sqlite connection
* @param array $aParams
* array(
* "db"
* "db" full path of sqlite file
* )
* @return boolean
*/
......
......@@ -74,6 +74,32 @@ foreach(array('dataDir', 'buildDir', 'packageDir', 'archiveDir') as $sDirKey){
);
}
foreach(array('dataDir', 'buildDir', 'packageDir', 'archiveDir') as $sDirKey){
$oMonitor->addCheck(
array(
"name" => "Disk space in dir [$sDirKey]",
"description" => "Check if workdir $sDirKey has enough space",
"check" => array(
"function" => "Diskfree",
"params" => array(
"directory" => $aConfig[$sDirKey],
"warning" => "500MB",
"critical" => "100MB",
),
),
)
);
}
$oMonitor->addCheck(
array(
"name" => "Certificate check",
"description" => "Check if SSL cert is valid and does not expire soon",
"check" => array(
"function" => "Cert",
),
)
);
// ----------------------------------------------------------------------
// databases
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment