From 79500101c69cba36611e84b36bbb5071fb2efd65 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Sat, 10 Mar 2018 11:51:56 +0100 Subject: [PATCH] services: import monit service Some things to work on: * post-install should be a migration * move to system? * remove old notifications --- plist | 22 ++ src/etc/inc/plugins.inc.d/monit.inc | 66 ++++ .../OPNsense/Monit/Api/ServiceController.php | 79 ++++ .../OPNsense/Monit/Api/SettingsController.php | 341 ++++++++++++++++ .../OPNsense/Monit/Api/StatusController.php | 144 +++++++ .../OPNsense/Monit/IndexController.php | 51 +++ .../OPNsense/Monit/StatusController.php | 46 +++ .../OPNsense/Monit/forms/alerts.xml | 47 +++ .../OPNsense/Monit/forms/general.xml | 124 ++++++ .../OPNsense/Monit/forms/services.xml | 74 ++++ .../OPNsense/Monit/forms/tests.xml | 26 ++ .../mvc/app/models/OPNsense/Monit/ACL/ACL.xml | 10 + .../app/models/OPNsense/Monit/Menu/Menu.xml | 8 + .../mvc/app/models/OPNsense/Monit/Monit.php | 41 ++ .../mvc/app/models/OPNsense/Monit/Monit.xml | 269 +++++++++++++ .../mvc/app/views/OPNsense/Monit/index.volt | 372 ++++++++++++++++++ .../mvc/app/views/OPNsense/Monit/status.volt | 45 +++ .../scripts/OPNsense/Monit/post-install.php | 161 ++++++++ src/opnsense/scripts/OPNsense/Monit/setup.sh | 5 + .../service/conf/actions.d/actions_monit.conf | 29 ++ .../service/templates/OPNsense/Monit/+TARGETS | 2 + .../service/templates/OPNsense/Monit/monitrc | 133 +++++++ .../templates/OPNsense/Monit/rc.conf.d | 7 + 23 files changed, 2102 insertions(+) create mode 100644 src/etc/inc/plugins.inc.d/monit.inc create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/StatusController.php create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/IndexController.php create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/StatusController.php create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml create mode 100644 src/opnsense/mvc/app/models/OPNsense/Monit/ACL/ACL.xml create mode 100644 src/opnsense/mvc/app/models/OPNsense/Monit/Menu/Menu.xml create mode 100644 src/opnsense/mvc/app/models/OPNsense/Monit/Monit.php create mode 100644 src/opnsense/mvc/app/models/OPNsense/Monit/Monit.xml create mode 100644 src/opnsense/mvc/app/views/OPNsense/Monit/index.volt create mode 100644 src/opnsense/mvc/app/views/OPNsense/Monit/status.volt create mode 100755 src/opnsense/scripts/OPNsense/Monit/post-install.php create mode 100755 src/opnsense/scripts/OPNsense/Monit/setup.sh create mode 100644 src/opnsense/service/conf/actions.d/actions_monit.conf create mode 100644 src/opnsense/service/templates/OPNsense/Monit/+TARGETS create mode 100644 src/opnsense/service/templates/OPNsense/Monit/monitrc create mode 100644 src/opnsense/service/templates/OPNsense/Monit/rc.conf.d diff --git a/plist b/plist index d4aa563f0..e803092c7 100644 --- a/plist +++ b/plist @@ -35,6 +35,7 @@ /usr/local/etc/inc/plugins.inc.d/ipfw.inc /usr/local/etc/inc/plugins.inc.d/ipsec.inc /usr/local/etc/inc/plugins.inc.d/ipsec/auth-user.php +/usr/local/etc/inc/plugins.inc.d/monit.inc /usr/local/etc/inc/plugins.inc.d/netflow.inc /usr/local/etc/inc/plugins.inc.d/ntpd.inc /usr/local/etc/inc/plugins.inc.d/ntpd/ntpdate_sync_once.sh @@ -374,6 +375,15 @@ /usr/local/opnsense/mvc/app/controllers/OPNsense/IDS/forms/dialogRuleset.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/IDS/forms/dialogUserDefined.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/IDS/forms/generalSettings.xml +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/Api/StatusController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/IndexController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/StatusController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml +/usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/ServiceController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Proxy/IndexController.php @@ -481,6 +491,10 @@ /usr/local/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml /usr/local/opnsense/mvc/app/models/OPNsense/IDS/Menu/Menu.xml /usr/local/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_0_0.php +/usr/local/opnsense/mvc/app/models/OPNsense/Monit/ACL/ACL.xml +/usr/local/opnsense/mvc/app/models/OPNsense/Monit/Menu/Menu.xml +/usr/local/opnsense/mvc/app/models/OPNsense/Monit/Monit.php +/usr/local/opnsense/mvc/app/models/OPNsense/Monit/Monit.xml /usr/local/opnsense/mvc/app/models/OPNsense/Ntpd/ACL/ACL.xml /usr/local/opnsense/mvc/app/models/OPNsense/Ntpd/Menu/Menu.xml /usr/local/opnsense/mvc/app/models/OPNsense/Proxy/ACL/ACL.xml @@ -512,6 +526,8 @@ /usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/systemactivity.volt /usr/local/opnsense/mvc/app/views/OPNsense/Diagnostics/systemhealth.volt /usr/local/opnsense/mvc/app/views/OPNsense/IDS/index.volt +/usr/local/opnsense/mvc/app/views/OPNsense/Monit/index.volt +/usr/local/opnsense/mvc/app/views/OPNsense/Monit/status.volt /usr/local/opnsense/mvc/app/views/OPNsense/Proxy/index.volt /usr/local/opnsense/mvc/app/views/OPNsense/Routes/index.volt /usr/local/opnsense/mvc/app/views/OPNsense/TrafficShaper/index.volt @@ -572,6 +588,8 @@ /usr/local/opnsense/scripts/OPNsense/CaptivePortal/set_session_restrictions.py /usr/local/opnsense/scripts/OPNsense/CaptivePortal/sql/init.sql /usr/local/opnsense/scripts/OPNsense/CaptivePortal/strip_template.py +/usr/local/opnsense/scripts/OPNsense/Monit/post-install.php +/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh /usr/local/opnsense/scripts/dhcp/get_leases.py /usr/local/opnsense/scripts/dhcp/prefixes.php /usr/local/opnsense/scripts/dns/unbound_dhcpd.py @@ -681,6 +699,7 @@ /usr/local/opnsense/service/conf/actions.d/actions_interface.conf /usr/local/opnsense/service/conf/actions.d/actions_ipfw.conf /usr/local/opnsense/service/conf/actions.d/actions_ipsec.conf +/usr/local/opnsense/service/conf/actions.d/actions_monit.conf /usr/local/opnsense/service/conf/actions.d/actions_netflow.conf /usr/local/opnsense/service/conf/actions.d/actions_openssh.conf /usr/local/opnsense/service/conf/actions.d/actions_openvpn.conf @@ -733,6 +752,9 @@ /usr/local/opnsense/service/templates/OPNsense/IPFW/ipfw.fw.conf /usr/local/opnsense/service/templates/OPNsense/IPFW/rc.conf.d /usr/local/opnsense/service/templates/OPNsense/Macros/interface.macro +/usr/local/opnsense/service/templates/OPNsense/Monit/+TARGETS +/usr/local/opnsense/service/templates/OPNsense/Monit/monitrc +/usr/local/opnsense/service/templates/OPNsense/Monit/rc.conf.d /usr/local/opnsense/service/templates/OPNsense/Netflow/+TARGETS /usr/local/opnsense/service/templates/OPNsense/Netflow/flowd.conf /usr/local/opnsense/service/templates/OPNsense/Netflow/flowd.rc.conf.d diff --git a/src/etc/inc/plugins.inc.d/monit.inc b/src/etc/inc/plugins.inc.d/monit.inc new file mode 100644 index 000000000..b8f1a5382 --- /dev/null +++ b/src/etc/inc/plugins.inc.d/monit.inc @@ -0,0 +1,66 @@ + gettext('Monit System Monitoring'), + 'configd' => array( + 'restart' => array('monit restart'), + 'start' => array('monit start'), + 'stop' => array('monit stop'), + ), + 'name' => 'monit', + ); + } + return $services; +} + +/** + * sync configuration via xmlrpc + * @return array + */ +function monit_xmlrpc_sync() +{ + $result = array(); + + $result[] = array( + 'description' => gettext('Monit System Monitoring'), + 'section' => 'OPNsense.monit', + 'id' => 'monit', + ); + + return $result; +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php new file mode 100644 index 000000000..0b1a73522 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php @@ -0,0 +1,79 @@ +request->isPost()) { + $this->sessionClose(); + + $backend = new Backend(); + + $result['function'] = "configtest"; + $result['template'] = trim($backend->configdRun('template reload OPNsense/Monit')); + if ($result['template'] != 'OK') { + $result['result'] = "Template error: " . $result['template']; + return $result; + } + $result['result'] = trim($backend->configdRun('monit configtest')); + return $result; + } else { + return array('status' => 'failed'); + } + } + + /** + * avoid restarting Relayd on reconfigure + */ + protected function reconfigureForceRestart() + { + return 0; + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php new file mode 100644 index 000000000..621aaaf45 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php @@ -0,0 +1,341 @@ + "failed"); + if ($this->request->isGet() && $nodeType != null) { + $this->validateNodeType($nodeType); + $mdlMonit = new Monit(); + if ($nodeType == 'general') { + $node = $mdlMonit->getNodeByReference($nodeType); + } else { + if ($uuid != null) { + $node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid); + } else { + $node = $mdlMonit->$nodeType->Add(); + } + } + if ($node != null) { + $result[$nodeType] = $node->getNodes(); + $result["result"] = "ok"; + } + } + return $result; + } + + /** + * set monit properties + * @param $nodeType + * @param $uuid + * @return status array + */ + public function setAction($nodeType = null, $uuid = null) + { + $result = array("result" => "failed", "validations" => array()); + if ($this->request->isPost() && $this->request->hasPost("monit") && $nodeType != null) { + $this->validateNodeType($nodeType); + $mdlMonit = new Monit(); + if ($nodeType == 'general') { + $node = $mdlMonit->getNodeByReference($nodeType); + } else { + if ($uuid != null) { + $node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid); + } else { + $node = $mdlMonit->$nodeType->Add(); + } + } + if ($node != null) { + $monitInfo = $this->request->getPost("monit"); + + // perform plugin specific validations + if ($nodeType == 'service') { + switch ($monitInfo[$nodeType]['type']) { + case 'process': + if (empty($monitInfo[$nodeType]['pidfile']) && empty($monitInfo[$nodeType]['match'])) { + $result["validations"]['monit.service.pidfile'] = "Please set at least one of Pidfile or Match."; + $result["validations"]['monit.service.match'] = $result["validations"]['monit.service.pidfile']; + } + break; + case 'host': + if (empty($monitInfo[$nodeType]['address'])) { + $result["validations"]['monit.service.address'] = "Address is mandatory for 'Remote Host' checks."; + } + break; + case 'network': + if (empty($monitInfo[$nodeType]['address']) && empty($monitInfo[$nodeType]['interface'])) { + $result["validations"]['monit.service.address'] = "Please set at least one of Address or Interface."; + $result["validations"]['monit.service.interface'] = $result["validations"]['monit.service.address']; + } + break; + case 'system': + break; + default: + if (empty($monitInfo[$nodeType]['path'])) { + $result["validations"]['monit.service.path'] = "Path is mandatory."; + } + } + } + + $node->setNodes($monitInfo[$nodeType]); + $valMsgs = $mdlMonit->performValidation(); + foreach ($valMsgs as $field => $msg) { + $fieldnm = str_replace($node->__reference, "monit." . $nodeType, $msg->getField()); + $result["validations"][$fieldnm] = $msg->getMessage(); + } + if (empty($result["validations"])) { + unset($result["validations"]); + $result['result'] = 'ok'; + $mdlMonit->serializeToConfig(); + Config::getInstance()->save(); + if ($nodeType == 'general' && $monitInfo['general']['enabled'] == '0') { + $svcMonit = new ServiceController(); + $result = $svcMonit->stopAction(); + } + } + } + } + return $result; + } + + /** + * delete monit settings + * @param $nodeType + * @param $uuid + * @return status array + */ + public function delAction($nodeType = null, $uuid = null) + { + $result = array("result" => "failed"); + if ($nodeType != null) { + $this->validateNodeType($nodeType); + if ($uuid != null) { + $mdlMonit = new Monit(); + $node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid); + if ($node != null) { + if ($mdlMonit->$nodeType->del($uuid) == true) { + // delete relations + if ($nodeType == 'test') { + $nodeName = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid . '.name'); + if ($nodeName != null) { + $nodeName = $nodeName->__toString(); + $this->deleteRelations('service', 'tests', $uuid, 'test', $nodeName, $mdlMonit); + } + } + $mdlMonit->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "ok"; + } + } + } + } + return $result; + } + + /** + * toggle monit items (enable/disable) + * @param $nodeType + * @param $uuid + * @return result array + */ + public function toggleAction($nodeType = null, $uuid = null) + { + $result = array("result" => "failed"); + if ($this->request->isPost() && $nodeType != null) { + $mdlMonit = new Monit(); + if ($uuid != null) { + $node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid); + if ($node != null) { + if ($node->enabled->__toString() == "1") { + $node->enabled = "0"; + } else { + $node->enabled = "1"; + } + $mdlMonit->serializeToConfig(); + Config::getInstance()->save(); + $svcMonit = new ServiceController(); + $result= $svcMonit->reloadAction(); + } else { + $result['result'] = "not found"; + } + } else { + $result['result'] = "uuid not given"; + } + } + return $result; + } + + /** + * search monit settings + * @param $nodeType + * @return result array + */ + public function searchAction($nodeType = null) + { + $this->sessionClose(); + if ($this->request->isPost() && $nodeType != null) { + $this->validateNodeType($nodeType); + $mdlMonit = new Monit(); + $grid = new UIModelGrid($mdlMonit->$nodeType); + $fields = array(); + switch ($nodeType) { + case 'alert': + $fields = array("enabled", "recipient", "noton", "events", "description"); + break; + case 'service': + $fields = array("enabled", "name", "type", "description"); + break; + case 'test': + $fields = array("name", "condition", "action"); + break; + } + return $grid->fetchBindRequest($this->request, $fields); + } + } + + /** + * import system notification settings + * @return result array + */ + public function notificationAction() + { + $result = array("result" => "failed"); + if ($this->request->isPost()) { + $this->sessionClose(); + + $cfg = Config::getInstance(); + $cfgObj = $cfg->object(); + $mdlMonit = new Monit(); + $node = $mdlMonit->getNodeByReference('general'); + $generalSettings = array(); + + // inherit SMTP settings from System->Settings->Notifications + if (!empty($cfgObj->notifications->smtp->ipaddress)) { + $generalSettings['mailserver'] = $cfgObj->notifications->smtp->ipaddress; + } + if (!empty($cfgObj->notifications->smtp->port)) { + $generalSettings['port'] = $cfgObj->notifications->smtp->port; + } + $generalSettings['username'] = $cfgObj->notifications->smtp->username; + $generalSettings['password'] = $cfgObj->notifications->smtp->password; + if ((!empty($cfgObj->notifications->smtp->tls) && $cfgObj->notifications->smtp->tls == 1) || + (!empty($cfgObj->notifications->smtp->ssl) && $cfgObj->notifications->smtp->ssl == 1)) { + $generalSettings['ssl'] = 1; + } else { + $generalSettings['ssl'] = 0; + } + + // apply them + $node->setNodes($generalSettings); + $valMsgs = $mdlMonit->performValidation(); + foreach ($valMsgs as $field => $msg) { + $fieldnm = str_replace($node->__reference, "monit.general.", $msg->getField()); + $result["validations"][$fieldnm] = $msg->getMessage(); + } + if (empty($result["validations"])) { + unset($result["validations"]); + $result['result'] = 'ok'; + $mdlMonit->serializeToConfig(); + Config::getInstance()->save(); + } + } + return $result; + } + + /** + * validate nodeType + * @param $nodeType + * @throws \Exception + */ + private function validateNodeType($nodeType = null) + { + if (array_search($nodeType, $this->nodeTypes) === false) { + throw new \Exception('unknown nodeType: ' . $nodeType); + } + } + + /** + * delete relations + * @param $nodeType + * @param $uuid + * @param $relNodeType + * @param &$mdlMonit + * @throws \Exception + */ + private function deleteRelations($nodeType = null, $nodeField = null, $relUuid = null, $relNodeType = null, $relNodeName = null, &$mdlMonit = null) + { + $nodes = $mdlMonit->$nodeType->getNodes(); + // get nodes with relations + foreach ($nodes as $nodeUuid => $node) { + // get relation uuids + foreach ($node[$nodeField] as $fieldUuid => $field) { + // remove uuid from field + if ($fieldUuid == $relUuid) { + $refField = $nodeType . '.' . $nodeUuid . '.' . $nodeField; + $relNode = $mdlMonit->getNodeByReference($refField); + $nodeRels = str_replace($relUuid, '', $relNode->__toString()); + $nodeRels = str_replace(',,', ',', $nodeRels); + $nodeRels = rtrim($nodeRels, ','); + $nodeRels = ltrim($nodeRels, ','); + $mdlMonit->setNodeByReference($refField, $nodeRels); + if ($relNode->isEmptyAndRequired()) { + $nodeName = $mdlMonit->getNodeByReference($nodeType . '.' . $nodeUuid . '.name')->__toString(); + throw new \Exception("Cannot delete $relNodeType '$relNodeName' from $nodeType '$nodeName'"); + } + } + } + } + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/StatusController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/StatusController.php new file mode 100644 index 000000000..65646590a --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/StatusController.php @@ -0,0 +1,144 @@ + "failed"); + + $socketPath = "/var/run/monit.sock"; + + // map the requested html format from the status page to the Monit text format + $format = $format == 'html' ? 'text' : $format; + + // check monit httpd socket defined in monitrc by 'set httpd ...' + if (file_exists($socketPath) && filetype($socketPath) == "socket") { + // set curl options + $ch = curl_init("http://127.0.0.1/_status?format=" . $format); + curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, $socketPath); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + // get credentials if configured + $mdlMonit = new Monit(); + if ($mdlMonit->general->httpdUsername->__toString() != null && trim($mdlMonit->general->httpdUsername->__toString()) !== "" && + $mdlMonit->general->httpdPassword->__toString() != null && trim($mdlMonit->general->httpdPassword->__toString()) !== "") { + curl_setopt($ch, CURLOPT_USERPWD, $mdlMonit->general->httpdUsername->__toString() . ":" . $mdlMonit->general->httpdPassword->__toString()); + } + + // send request + if (!$response = curl_exec($ch)) { + $result['status'] = curl_error($ch); + return $result; + } + $HTTPCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + if ($HTTPCode != 200) { + $result['status'] = 'Monit returns with code ' . $HTTPCode; + } else { + $result['result'] = "ok"; + + // format the response + if ($format == 'xml') { + $result['status'] = simplexml_load_string($response); + } elseif ($format === 'text') { + $result['status'] = '
' . $this->bashColorToCSS($response) . '
'; + } + } + } else { + $msg = " +Either the file " . $socketPath . " does not exists or it is not a unix socket. +Please check if the Monit service is running. + +If you have started Monit recently, wait for StartDelay seconds and refresh this page."; + if ($format == 'xml') { + $result['status'] = $msg; + } elseif ($format === 'text') { + $result['status'] = '
' . $msg . '
'; + } + } + return $result; + } + + /** + * convert bash color escape codes to CSS + * @param $string + * @return string + */ + private function bashColorToCSS($string) + { + $colors = [ + '/\x1b\[0;30m(.*?)\x1b\[0m/s' => '$1', + + '/\x1b\[0;30m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;31m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;32m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;33m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;34m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;35m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;36m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;37m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;39m(.*?)\x1b\[0m/s' => '$1', + + '/\x1b\[1;30m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;31m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;32m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;33m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;34m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;35m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;36m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[1;37m(.*?)\x1b\[0m/s' => '$1', + + '/\x1b\[0;90m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;91m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;92m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;93m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;94m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;95m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;96m(.*?)\x1b\[0m/s' => '$1', + '/\x1b\[0;97m(.*?)\x1b\[0m/s' => '$1' + ]; + return preg_replace(array_keys($colors), $colors, $string); + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/IndexController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/IndexController.php new file mode 100644 index 000000000..86c38d3d3 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/IndexController.php @@ -0,0 +1,51 @@ +view->formGeneralSettings = $this->getForm("general"); + $this->view->formDialogEditAlert = $this->getForm("alerts"); + $this->view->formDialogEditService = $this->getForm("services"); + $this->view->formDialogEditTest = $this->getForm("tests"); + $this->view->pick('OPNsense/Monit/index'); + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/StatusController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/StatusController.php new file mode 100644 index 000000000..963836f19 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/StatusController.php @@ -0,0 +1,46 @@ +view->pick('OPNsense/Monit/status'); + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml new file mode 100644 index 000000000..643de6d59 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml @@ -0,0 +1,47 @@ +
+ + monit.alert.enabled + + checkbox + + + + monit.alert.recipient + + text + + + + + monit.alert.noton + + checkbox + + + + monit.alert.events + + select_multiple + 28 + + + + + monit.alert.format + + text + + Subject: $SERVICE on $HOST failed]]> + + + monit.alert.reminder + + text + + + + monit.alert.description + + text + +
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml new file mode 100644 index 000000000..1f5e476f4 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml @@ -0,0 +1,124 @@ +
+ + monit.general.enabled + + checkbox + + + + monit.general.interval + + text + + + + monit.general.startdelay + + text + + + + monit.general.mailserver + + select_multiple + true + + + + + monit.general.port + + text + + + + monit.general.username + + text + + + + monit.general.password + + password + + + + monit.general.ssl + + checkbox + + + + monit.general.logfile + + text + syslog or the path to a file.]]> + true + + + monit.general.statefile + + text + + true + + + monit.general.eventqueuePath + + text + + true + + + monit.general.eventqueueSlots + + text + + true + + + monit.general.httpdEnabled + + checkbox + + true + + + monit.general.httpdPort + + text + + true + + + monit.general.httpdAllow + + select_multiple + + true + See Monit Authentication]]> + true + user:password, @group... Finish with TAB. + + + monit.general.mmonitUrl + + text + https://user:pass@192.168.1.10:8443/collector
If you want to control Monit services from your M/Monit instance you have to configure the Monit Port too and add corresponding firewall rules as well.]]>
+ true +
+ + monit.general.mmonitTimeout + + text + true + + + monit.general.mmonitRegisterCredentials + + checkbox + + true + +
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml new file mode 100644 index 000000000..15d0f2c8c --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml @@ -0,0 +1,74 @@ +
+ + monit.service.enabled + + checkbox + + + + monit.service.name + + text + + + + monit.service.type + + dropdown + + + + monit.service.pidfile + + text + + + + monit.service.match + + text + monit procmatch <PATTERN>]]> + + + monit.service.path + + text + + + + monit.service.address + + text + + + + monit.service.interface + + dropdown + + + + monit.service.start + + text + + + + monit.service.stop + + text + + + + monit.service.tests + + select_multiple + + + + + monit.service.description + + text + +
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml new file mode 100644 index 000000000..5d96a0a21 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml @@ -0,0 +1,26 @@ +
+ + monit.test.name + + text + + + + monit.test.condition + + text + cpu is greater than 50%
failed host 127.0.0.1 port 22 protocol ssh
]]>
+
+ + monit.test.action + + dropdown + alert or restart the service or execute a program.]]> + + + monit.test.path + + text + + +
diff --git a/src/opnsense/mvc/app/models/OPNsense/Monit/ACL/ACL.xml b/src/opnsense/mvc/app/models/OPNsense/Monit/ACL/ACL.xml new file mode 100644 index 000000000..72937387e --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Monit/ACL/ACL.xml @@ -0,0 +1,10 @@ + + + WebCfg - Services: Monit System Monitoring page + Allow access to the 'Services: Monit System Monitoring' page. + + ui/monit/* + api/monit/* + + + diff --git a/src/opnsense/mvc/app/models/OPNsense/Monit/Menu/Menu.xml b/src/opnsense/mvc/app/models/OPNsense/Monit/Menu/Menu.xml new file mode 100644 index 000000000..841575d23 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Monit/Menu/Menu.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/opnsense/mvc/app/models/OPNsense/Monit/Monit.php b/src/opnsense/mvc/app/models/OPNsense/Monit/Monit.php new file mode 100644 index 000000000..a386f7c00 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Monit/Monit.php @@ -0,0 +1,41 @@ + + //OPNsense/monit + 1.0.3 + Monit settings + + + + 0 + Y + + + 120 + Y + 0 + 86400 + Polling Interval needs to be an integer value between 0 and 86400 + + + 120 + Y + 0 + 86400 + Start Delay needs to be an integer value between 0 and 86400 + + + 127.0.0.1 + Y + Y + /^([0-9a-zA-Z\.,_\-:]){0,1024}$/u + lower + Please specify a valid servername or IP address. + + + Y + 25 + 0 + 65535 + Port needs to be an integer value between 0 and 65535 + + + N + + + N + + + 0 + Y + + + N + syslog facility log_daemon + /^(\/[^\/ ]*)+\/?|syslog.*$/ + Should be a valid absolute path to the log file or the keyword "syslog". + + + N + /^(\/[^\/ ]*)+\/?$/ + Should be a valid absolute path to the state file. + + + N + /^(\/[^\/ ]*)+\/?$/ + Should be a valid absolute path to the eventqueue directory. + + + N + Eventqueue Slots must be a numeric value. + + + 0 + Y + + + + + 2812 + Y + 1 + 65535 + Local Monit Port needs to be an integer value between 0 and 65535 + + + N + Y + + + N + + + 5 + Y + 0 + 86400 + M/Monit Timeout needs to be an integer value between 0 and 86400 + + + 1 + Y + + + + + 0 + Y + + + root@localhost.local + Y + Please enter a valid email address. + + + Y + 0 + + + N + + Action done + Checksum failed + Download bytes exceeded + Upload bytes exceeded + Connection failed + Content failed + Data access error + Execution failed + Filesystem flags failed + GID failed + Ping failed + Monit instance changed + Invalid type + Does not exist + Download packets exceeded + Upload packets exceeded + Permission failed + PID failed + PPID failed + Resource limit matched + Saturation exceeded + Size failed + Speed failed + Status failed + Timeout + Timestamp failed + UID failed + Uptime failed + + + + N + /^.{1,255}$/u + Message format should be a string between 1 and 255 characters. + + + 10 + N + 0 + 86400 + Reminder needs to be an integer value between 0 and 86400 + + + N + /^.{1,255}$/u + Enter a description. + + + + + 0 + Y + + + Y + /^([0-9a-zA-Z\._\-\$]){1,255}$/u + Should be a string between 1 and 255 characters. Allowed characters are letters and numbers as well as underscore, minus, dot and the dollar sign. + + + Y + + Process + File + Fifo + Filesystem + Directory + Remote Host + System + Custom + Network + + + + N + /^(\/[^\/ ]*)+\/?$/ + Should be a valid absolute path to the PID file of the process. + + + N + + + N + /^(\/[^\/ ]*)+\/?.*$/ + Should be a valid absolute file or folder path. + +
+ N + /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?)$/ + Address must be a valid IPv4 address +
+ + N + N + + /^(?!0).*$/ + /^((?!dhcp).)*$/ + + + + N + /^(\/[^\/ ]*)+\/? .*$/ + Should be a valid absolute path to the executable with its arguments. + + + N + /^(\/[^\/ ]*)+\/? .*$/ + Should be a valid absolute path to the executable with its arguments. + + + + + + Related item not found + Y + N + +
+ + + Y + /^([0-9a-zA-Z\._\- ]){1,255}$/u + Should be a string between 1 and 255 characters. Allowed characters are letters and numbers as well as underscore, minus, dot and space. + + + Y + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + + + Y + + Alert + Restart + Start + Stop + Execute + Unmonitor + + + + N + /^(\/[^\/ ]*)+\/?.*$/ + Should be a valid absolute file path. + + +
+ diff --git a/src/opnsense/mvc/app/views/OPNsense/Monit/index.volt b/src/opnsense/mvc/app/views/OPNsense/Monit/index.volt new file mode 100644 index 000000000..5649844b3 --- /dev/null +++ b/src/opnsense/mvc/app/views/OPNsense/Monit/index.volt @@ -0,0 +1,372 @@ +{# + +Copyright © 2017-2018 by EURO-LOG AG +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +#} + + + + + +
+
+ + {{ partial("layout_partials/base_form",['fields':formGeneralSettings,'id':'frm_GeneralSettings','apply_btn_id':'btn_ApplyGeneralSettings'])}} +
+
+ + + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('Recipient') }}{{ lang._('Events') }}{{ lang._('Description') }}{{ lang._('ID') }}{{ lang._('Edit') }} | {{ lang._('Delete') }}
+ + +
+
+
+ + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('Name') }}{{ lang._('ID') }}{{ lang._('Edit') }} | {{ lang._('Delete') }}
+ + +
+
+
+ + + + + + + + + + + + + + + + + + +
{{ lang._('Name') }}{{ lang._('Condition') }}{{ lang._('Action') }}{{ lang._('ID') }}{{ lang._('Edit') }} | {{ lang._('Delete') }}
+ + +
+
+
+
+ + +
+
+
+
+{# include dialogs #} +{{ partial("layout_partials/base_dialog",['fields':formDialogEditAlert,'id':'DialogEditAlert','label':'Edit Alert  NOTE: For a detailed description see monit(1) section "ALERT MESSAGES".'])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogEditService,'id':'DialogEditService','label':'Edit Service'])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogEditTest,'id':'DialogEditTest','label':'Edit Test  NOTE: For a detailed description see monit(1) section "SERVICE TESTS".'])}} diff --git a/src/opnsense/mvc/app/views/OPNsense/Monit/status.volt b/src/opnsense/mvc/app/views/OPNsense/Monit/status.volt new file mode 100644 index 000000000..e9c279c01 --- /dev/null +++ b/src/opnsense/mvc/app/views/OPNsense/Monit/status.volt @@ -0,0 +1,45 @@ +{# + +Copyright © 2017-2018 by EURO-LOG AG +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +#} + + +
+Loading... +
diff --git a/src/opnsense/scripts/OPNsense/Monit/post-install.php b/src/opnsense/scripts/OPNsense/Monit/post-install.php new file mode 100755 index 000000000..b46f04aba --- /dev/null +++ b/src/opnsense/scripts/OPNsense/Monit/post-install.php @@ -0,0 +1,161 @@ +#!/usr/local/bin/php +object(); +$shellObj = new OPNsense\Core\Shell; +$generalNode = $mdlMonit->getNodeByReference('general'); + +if (empty($cfgObj->OPNsense->monit->general->httpdUsername) && empty($cfgObj->OPNsense->monit->general->httpdPassword)) { + print "Generate Monit httpd username and password\n"; + srand(); + $generalNode->setNodes(array( + "httpdUsername" => "root", + "httpdPassword" => substr(str_shuffle(str_repeat('0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz', 32)), rand(0, 16), rand(17, 32)) + )); + $mdlMonit->serializeToConfig(false, true); + $cfg->save(); +} + +$nodes = $mdlMonit->getNodes(); +// test if Monit is already configured +if (count($nodes['service']) != 0 || count($nodes['test']) != 0) { + exit; +} + +// get number of cpus and calculate load average limits +$nCPU = array(); +$shellObj->exec('/sbin/sysctl -n kern.smp.cpus', false, $nCPU); +$LoadAvg1 = $nCPU[0] * 2; +$LoadAvg5 = $nCPU[0] + ($nCPU[0] / 2); +$LoadAvg15 = $nCPU[0]; + +// inherit SMTP settings from System->Settings->Notifications +$generalSettings = array(); +if (!empty($cfgObj->notifications->smtp->ipaddress)) { + $generalSettings['mailserver'] = $cfgObj->notifications->smtp->ipaddress; +} +if (!empty($cfgObj->notifications->smtp->port)) { + $generalSettings['port'] = $cfgObj->notifications->smtp->port; +} +if (!empty($cfgObj->notifications->smtp->username)) { + $generalSettings['username'] = $cfgObj->notifications->smtp->username; +} +if (!empty($cfgObj->notifications->smtp->password)) { + $generalSettings['password'] = $cfgObj->notifications->smtp->password; +} +if ((!empty($cfgObj->notifications->smtp->tls) && $cfgObj->notifications->smtp->tls == 1) || + (!empty($cfgObj->notifications->smtp->ssl) && $cfgObj->notifications->smtp->ssl == 1)) { + $generalSettings['ssl'] = 1; +} + +$alertSettings = array(); +if (!empty($cfgObj->notifications->smtp->notifyemailaddress)) { + $alertSettings['recipient'] = $cfgObj->notifications->smtp->notifyemailaddress; +} +if (!empty($cfgObj->notifications->smtp->fromaddress)) { + $alertSettings['format'] = 'from: ' . $cfgObj->notifications->smtp->fromaddress; +} + +// define some tests +$defaultTests = array( + array("name" => "Ping", "condition" => "failed ping", "action" => "alert"), + array("name" => "NetworkLink", "condition" => "failed link", "action" => "alert"), + array("name" => "NetworkSaturation", "condition" => "saturation is greater than 75%", "action" => "alert"), + array("name" => "MemoryUsage", "condition" => "memory usage is greater than 75%", "action" => "alert"), + array("name" => "CPUUsage", "condition" => "cpu usage is greater than 75%", "action" => "alert"), + array("name" => "LoadAvg1", "condition" => "loadavg (1min) is greater than $LoadAvg1", "action" => "alert"), + array("name" => "LoadAvg5", "condition" => "loadavg (5min) is greater than $LoadAvg5", "action" => "alert"), + array("name" => "LoadAvg15", "condition" => "loadavg (15min) is greater than $LoadAvg15", "action" => "alert"), + array("name" => "SpaceUsage", "condition" => "space usage is greater than 75%", "action" => "alert") +); + +// define system service +$systemService = array( + "enabled" => 1, + "name" => '$HOST', + "type" => "system", + "tests" => "" +); + +// define root filesystem service +$rootFsService = array( + "enabled" => 1, + "name" => "RootFs", + "type" => "filesystem", + "path" => "/", + "tests" => "" +); + +foreach ($defaultTests as $defaultTest) { + $testNode = $mdlMonit->test->Add(); + $testNode->setNodes($defaultTest); + if ($defaultTest['name'] == "MemoryUsage" || + $defaultTest['name'] == "CPUUsage" || + $defaultTest['name'] == "LoadAvg1" || + $defaultTest['name'] == "LoadAvg5" ) { + $systemService['tests'] .= $testNode->getAttributes()['uuid'] . ","; + } + if ($defaultTest['name'] == "SpaceUsage") { + $rootFsService['tests'] .= $testNode->getAttributes()['uuid'] . ","; + } +} + +// remove last comma from tests csv +$systemService['tests'] = substr($systemService['tests'], 0, -1); +$rootFsService['tests'] = substr($rootFsService['tests'], 0, -1); + +// set general properties +$generalNode->setNodes($generalSettings); + +// add an alert with (almost) default settings +$alertNode = $mdlMonit->alert->Add(); +$alertNode->setNodes($alertSettings); + +// add system service +$serviceNode = $mdlMonit->service->Add(); +$serviceNode->setNodes($systemService); + +// add root filesystem service +$rootFsNode = $mdlMonit->service->Add(); +$rootFsNode->setNodes($rootFsService); + +// ignore validations because ModelRelationField does not work +$mdlMonit->serializeToConfig(false, true); +$cfg->save(); diff --git a/src/opnsense/scripts/OPNsense/Monit/setup.sh b/src/opnsense/scripts/OPNsense/Monit/setup.sh new file mode 100755 index 000000000..cf200fd2e --- /dev/null +++ b/src/opnsense/scripts/OPNsense/Monit/setup.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +# change permissions of the monit configuration file +chmod 600 /usr/local/etc/monitrc || exit 1 +exit 0 diff --git a/src/opnsense/service/conf/actions.d/actions_monit.conf b/src/opnsense/service/conf/actions.d/actions_monit.conf new file mode 100644 index 000000000..025e0185d --- /dev/null +++ b/src/opnsense/service/conf/actions.d/actions_monit.conf @@ -0,0 +1,29 @@ +[start] +command:/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh; /usr/local/etc/rc.d/monit start +type:script +message:starting monit + +[stop] +command:/usr/local/etc/rc.d/monit stop +type:script +message:stopping monit + +[status] +command:/usr/local/etc/rc.d/monit status; exit 0 +type:script_output +message:get monit status + +[restart] +command:/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh; /usr/local/etc/rc.d/monit restart +type:script +message:restarting monit + +[reload] +command:/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh; /usr/local/etc/rc.d/monit reload +type:script +message:reload monit configuration + +[configtest] +command:/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh; /usr/local/bin/monit -t 2>&1 || exit 0 +type:script_output +message:testing monit configuration diff --git a/src/opnsense/service/templates/OPNsense/Monit/+TARGETS b/src/opnsense/service/templates/OPNsense/Monit/+TARGETS new file mode 100644 index 000000000..d5be9309b --- /dev/null +++ b/src/opnsense/service/templates/OPNsense/Monit/+TARGETS @@ -0,0 +1,2 @@ +monitrc:/usr/local/etc/monitrc +rc.conf.d:/etc/rc.conf.d/monit diff --git a/src/opnsense/service/templates/OPNsense/Monit/monitrc b/src/opnsense/service/templates/OPNsense/Monit/monitrc new file mode 100644 index 000000000..1fa8bc96e --- /dev/null +++ b/src/opnsense/service/templates/OPNsense/Monit/monitrc @@ -0,0 +1,133 @@ +# DO NOT EDIT THIS FILE -- OPNsense auto-generated file + +{% from 'OPNsense/Macros/interface.macro' import physical_interface %} +{% if helpers.exists('OPNsense.monit.general') %} +{% if helpers.exists('OPNsense.monit.general.httpdEnabled') and OPNsense.monit.general.httpdEnabled|default('0') == '1' %} +{% set httpdCredentials = OPNsense.monit.general.httpdUsername ~ ':"' ~ OPNsense.monit.general.httpdPassword ~ '"' %} +{% set httpdport = "port " ~ OPNsense.monit.general.httpdPort %} +set httpd unixsocket /var/run/monit.sock {{ httpdport }} + allow localhost + allow {{ httpdCredentials }} +{% if helpers.exists('OPNsense.monit.general.httpdAllow') %} +{% for allow in OPNsense.monit.general.httpdAllow.split(",") %} +{% set cred = allow.split(":") %} +{% if cred[1] %} +{% set pass = cred[1].split() %} +{% set allow = cred[0] ~ ':"' ~ pass[0] ~ '" ' ~ pass[1] %} +{% endif %} + allow {{ allow }} +{% endfor %} +{% endif %} +{% if helpers.exists('OPNsense.monit.general.mmonitUrl') and OPNsense.monit.general.mmonitUrl|default('') != '' %} +{% set mregister = 'register without credentials' if OPNsense.monit.general.mmonitRegisterCredentials|default('1') == '0' %} + +set mmonit {{ OPNsense.monit.general.mmonitUrl }} timeout {{ OPNsense.monit.general.mmonitTimeout }} seconds {{ mregister }} +{% endif %} +{% else %} +set httpd unixsocket /var/run/monit.sock + allow localhost +{% endif %} + +set daemon {{ OPNsense.monit.general.interval }} with start delay {{ OPNsense.monit.general.startdelay }} + +{% if helpers.exists('OPNsense.monit.general.logfile') and OPNsense.monit.general.logfile|default('') != '' %} +set logfile {{ OPNsense.monit.general.logfile }} +{% else %} +set logfile syslog facility log_daemon +{% endif %} + +{% if helpers.exists('OPNsense.monit.general.statefile') and OPNsense.monit.general.statefile|default('') != '' %} +set statefile {{ OPNsense.monit.general.statefile }} +{% endif %} + +{% if helpers.exists('OPNsense.monit.general.eventqueuePath') and OPNsense.monit.general.eventqueuePath|default('') != '' %} +{% set slots = '' %} +{% if helpers.exists('OPNsense.monit.general.eventqueueSlots') %} +{% set slots = "slots " ~ OPNsense.monit.general.eventqueueSlots %} +{% endif %} + +set eventqueue basedir {{ OPNsense.monit.general.eventqueuePath }} {{ slots }} +{% endif %} + +{% if helpers.exists('OPNsense.monit.general.mailserver') %} +{% set port = "port " ~ OPNsense.monit.general.port if OPNsense.monit.general.port|default('') != '' %} +{% set username = '' %} +{% set password = '' %} +{% if helpers.exists('OPNsense.monit.general.username') and helpers.exists('OPNsense.monit.general.password') %} +{% set username = "username " ~ OPNsense.monit.general.username %} +{% set password = "password " ~ '"' ~ OPNsense.monit.general.password ~ '"' %} +{% endif %} +{% set ssl = 'using ssl' if OPNsense.monit.general.ssl|default('0') == '1' %} +set mailserver {{ OPNsense.monit.general.mailserver }} {{ port }} {{ username }} {{ password }} {{ ssl }} +{% endif %} + +{% if helpers.exists('OPNsense.monit.alert') %} +{% for alert in helpers.toList('OPNsense.monit.alert') %} +{% if alert.enabled|default('0') == '1' %} +{% set noton = 'not on' if alert.noton|default('0') == '1' %} +{% set mailformat = "mail-format { " ~ alert.format ~ " }" if alert.format|default('') != '' %} +{% set reminder = "reminder on " ~ alert.reminder ~ " cycles" if alert.reminder|default('0') != '0' %} +{% set events = "{ " ~ alert.events ~ " }" if alert.events|default('') != '' %} +set alert {{ alert.recipient }} {{ noton }} {{ events }} {{ mailformat }} {{ reminder }} +{% endif %} +{% endfor %} +{% endif %} + +{% if helpers.exists('OPNsense.monit.service') %} +{% for service in helpers.toList('OPNsense.monit.service') %} +{% if service.enabled|default('0') == '1' %} +{% set pidfile = '' %} +{% set match = '' %} +{% set path = '' %} +{% set address = '' %} +{% set interface = '' %} +{% if service.type == 'process' %} +{% if service.pidfile|default('') != '' %} +{% set pidfile = "pidfile " ~ service.pidfile %} +{% elif service.match|default('') != '' %} +{% set match = "matching " ~ service.match if service.match|default('') != '' %} +{% endif %} +check {{ service.type }} {{ service.name }} {{ pidfile }} {{ match }} +{% elif service.type == 'host' %} +{% set address = "address " ~ service.address %} +check {{ service.type }} {{ service.name }} {{ address }} +{% elif service.type == 'network' %} +{% if service.address|default('') != '' %} +{% set address = "address " ~ service.address %} +{% elif service.interface|default('') != '' %} +{% set interface = "interface " ~ physical_interface(service.interface) %} +{% endif %} +check {{ service.type }} {{ service.name }} {{ address }} {{ interface }} +{% elif service.type == 'system' %} +check {{ service.type }} {{ service.name }} +{% else %} +{% set path = "with path " ~ service.path %} +{% if service.type == 'custom' %} +check program {{ service.name }} {{ path }} +{% else %} +check {{ service.type }} {{ service.name }} {{ path }} +{% endif %} +{% endif %} +{% if service.start|default('') != '' %} + start program = "{{ service.start }}" +{% endif %} +{% if service.start|default('') != '' %} + stop program = "{{ service.stop }}" +{% endif %} +{% if service.tests is defined %} +{% for test in service.tests.split(",") %} +{% set test = helpers.getUUID(test) %} +{% if test.condition is defined and test.action is defined %} +{% set epath = '' %} +{% if test.action == 'exec' and test.path|default('') != '' %} +{% set epath = test.path %} +{% endif %} + if {{ test.condition }} then {{ test.action }} {{ epath }} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} + +{% endfor %} +{% endif %} +{% endif %} diff --git a/src/opnsense/service/templates/OPNsense/Monit/rc.conf.d b/src/opnsense/service/templates/OPNsense/Monit/rc.conf.d new file mode 100644 index 000000000..d19dee084 --- /dev/null +++ b/src/opnsense/service/templates/OPNsense/Monit/rc.conf.d @@ -0,0 +1,7 @@ +# DO NOT EDIT THIS FILE -- OPNsense auto-generated file +{% if helpers.exists('OPNsense.monit.general.enabled') and OPNsense.monit.general.enabled|default("0") == "1" %} +monit_var_script="/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh" +monit_enable="YES" +{% else %} +monit_enable="NO" +{% endif %}